Skip to content

Instantly share code, notes, and snippets.

@tid-kijyun
Last active June 11, 2023 06:25
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tid-kijyun/477c723ea42d22903ebe6b6cee3f77a1 to your computer and use it in GitHub Desktop.
Save tid-kijyun/477c723ea42d22903ebe6b6cee3f77a1 to your computer and use it in GitHub Desktop.
[OBS Script]Sets a text source to act as a tally counter when the source is active.
obs = obslua
source_name = ""
format_text = ""
start_number = 0
step_number = 0
now_count = 0
last_text = ""
activated = false
hotkey_reset_id = obs.OBS_INVALID_HOTKEY_ID
hotkey_up_id = obs.OBS_INVALID_HOTKEY_ID
hotkey_down_id = obs.OBS_INVALID_HOTKEY_ID
-- Function to set the time text
function set_time_text()
local text = string.format(format_text, now_count)
if text ~= last_text then
local source = obs.obs_get_source_by_name(source_name)
if source ~= nil then
local settings = obs.obs_data_create()
obs.obs_data_set_string(settings, "text", text)
obs.obs_source_update(source, settings)
obs.obs_data_release(settings)
obs.obs_source_release(source)
end
end
last_text = text
end
function activate(activating)
if activated == activating then
return
end
activated = activating
if activating then
now_count = start_number
-- Read the initial value
local source = obs.obs_get_source_by_name(source_name)
if source ~= nil then
local nowSettings = obs.obs_source_get_settings(source)
local val = obs.obs_data_get_string(nowSettings, "text")
local existing_count = string.match(val, "-%d+") or string.match(val, "%d+")
if existing_count ~= nil then
now_count = existing_count
end
obs.obs_data_release(nowSettings)
obs.obs_source_release(source)
end
set_time_text()
end
end
-- Called when a source is activated/deactivated
function activate_signal(cd, activating)
local source = obs.calldata_source(cd, "source")
if source ~= nil then
local name = obs.obs_source_get_name(source)
if (name == source_name) then
activate(activating)
end
end
end
function source_activated(cd)
activate_signal(cd, true)
end
function source_deactivated(cd)
activate_signal(cd, false)
end
function reset(pressed)
if not pressed then
return
end
activate(false)
local source = obs.obs_get_source_by_name(source_name)
if source ~= nil then
local active = obs.obs_source_active(source)
obs.obs_source_release(source)
activate(active)
end
end
function reset_button_clicked(props, p)
now_count = start_number
set_time_text()
reset(true)
return false
end
function up_button_clicked(props, p)
count_up(true)
return false
end
function down_button_clicked(props, p)
count_down(true)
return false
end
function count_up(pressed)
if not pressed then
return
end
now_count = now_count + step_number
set_time_text()
end
function count_down(pressed)
if not pressed then
return
end
now_count = now_count - step_number
set_time_text()
end
----------------------------------------------------------
-- A function named script_properties defines the properties that the user
-- can change for the entire script module itself
function script_properties()
local props = obs.obs_properties_create()
local p = obs.obs_properties_add_list(props, "source", "Text Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
local sources = obs.obs_enum_sources()
if sources ~= nil then
for _, source in ipairs(sources) do
source_id = obs.obs_source_get_id(source)
if source_id == "text_gdiplus" or source_id == "text_gdiplus_v2" or source_id == "text_ft2_source" or source_id == "text_ft2_source_v2" then
local name = obs.obs_source_get_name(source)
obs.obs_property_list_add_string(p, name, name)
end
end
end
obs.source_list_release(sources)
obs.obs_properties_add_text(props, "format_text", "Format Text", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_button(props, "up_button", " UP ", up_button_clicked)
obs.obs_properties_add_button(props, "down_button", "DOWN", down_button_clicked)
obs.obs_properties_add_int(props, "start_number", "Start Number", 0, 100000, 1)
obs.obs_properties_add_int(props, "step_number", "Step Number", 1, 100000, 1)
obs.obs_properties_add_button(props, "reset_button", "Reset", reset_button_clicked)
return props
end
-- A function named script_description returns the description shown to
-- the user
function script_description()
return "Sets a text source to act as a tally counter when the source is active.\n\nMade by _tid_"
end
-- A function named script_update will be called when settings are changed
function script_update(settings)
activate(false)
start_number = obs.obs_data_get_int(settings, "start_number")
step_number = obs.obs_data_get_int(settings, "step_number")
now_count = start_number
format_text = obs.obs_data_get_string(settings, "format_text")
source_name = obs.obs_data_get_string(settings, "source")
stop_text = obs.obs_data_get_string(settings, "stop_text")
reset(true)
end
-- A function named script_defaults will be called to set the default settings
function script_defaults(settings)
obs.obs_data_set_default_int(settings, "start_number", 1)
obs.obs_data_set_default_int(settings, "step_number", 1)
obs.obs_data_set_default_string(settings, "format_text", "Count: %d")
end
-- A function named script_save will be called when the script is saved
--
-- NOTE: This function is usually used for saving extra data (such as in this
-- case, a hotkey's save data). Settings set via the properties are saved
-- automatically.
function script_save(settings)
local hotkey_reset_save_array = obs.obs_hotkey_save(hotkey_reset_id)
obs.obs_data_set_array(settings, "reset_hotkey", hotkey_reset_array)
obs.obs_data_array_release(hotkey_reset_array)
local hotkey_up_save_array = obs.obs_hotkey_save(hotkey_up_id)
obs.obs_data_set_array(settings, "up_count_hotkey", hotkey_up_save_array)
obs.obs_data_array_release(hotkey_up_save_array)
local hotkey_down_save_array = obs.obs_hotkey_save(hotkey_down_id)
obs.obs_data_set_array(settings, "down_count_hotkey", hotkey_down_save_array)
obs.obs_data_array_release(hotkey_down_save_array)
end
-- a function named script_load will be called on startup
function script_load(settings)
-- Connect hotkey and activation/deactivation signal callbacks
--
-- NOTE: These particular script callbacks do not necessarily have to
-- be disconnected, as callbacks will automatically destroy themselves
-- if the script is unloaded. So there's no real need to manually
-- disconnect callbacks that are intended to last until the script is
-- unloaded.
local sh = obs.obs_get_signal_handler()
obs.signal_handler_connect(sh, "source_activate", source_activated)
obs.signal_handler_connect(sh, "source_deactivate", source_deactivated)
hotkey_reset_id = obs.obs_hotkey_register_frontend("reset_button_thingy", "[Tally-Counter]Reset", reset)
hotkey_up_id = obs.obs_hotkey_register_frontend("up_button_thingy", "[Tally-Counter]Up Count", count_up)
hotkey_down_id = obs.obs_hotkey_register_frontend("down_button_thingy", "[Tally-Counter]Down Count", count_down)
local hotkey_reset_save_array = obs.obs_data_get_array(settings, "reset_hotkey")
obs.obs_hotkey_load(hotkey_reset_id, hotkey_reset_save_array)
obs.obs_data_array_release(hotkey_reset_save_array)
local hotkey_up_save_array = obs.obs_data_get_array(settings, "up_count_hotkey")
obs.obs_hotkey_load(hotkey_up_id, hotkey_up_save_array)
obs.obs_data_array_release(hotkey_up_save_array)
local hotkey_down_save_array = obs.obs_data_get_array(settings, "down_count_hotkey")
obs.obs_hotkey_load(hotkey_down_id, hotkey_down_save_array)
obs.obs_data_array_release(hotkey_down_save_array)
end
@tid-kijyun
Copy link
Author

The screenshots are in Japanese, but I think the screen layout of OBS is the same, so I hope you find it useful.

Installation

  1. Download and unzip this script file

  2. Select Tools > Scripts from the OBS menu
    20190623203936

  3. Select + button in the script window and select the script file
    20190623204010

How to use

  1. Add text source to your scene
    20190623204600

  2. Select Tools > Scripts from the OBS menu
    20190623204641

  3. Select the registered script in the script window and select reload
    20190624164225

  4. Set the created text source in the Text Source field
    20190623211943

  5. Change Format to any character string. %d is replaced with the current count. (Example: Now %dth time)
    20190623205325

  6. You can count up (or down) by clicking the UP (or DOWN) button
    20190623205432

  7. You can reset the count by clicking the Reset button
    20190623212127

HotKey

It is convenient to set hotkeys if necessary.
20190623213511

@bridget7490
Copy link

I've been using this in my online classes for my students and love it! But is it possible to prevent the tally from re-setting each time I go to a different source? And would it also be possible to keep it from resetting when I close OBS? I'm trying to run an on-going tally for how many good questions my students answer!

@Appollyx
Copy link

Appollyx commented Mar 9, 2021 via email

@tid-kijyun
Copy link
Author

tid-kijyun commented Mar 9, 2021

@bridget7490 Thanks for using this script.

I've made the following changes: Please update the script.

  • Counts are no longer reset when OBS is restarted.
  • Counts are no longer reset when switching sources.

Thanks

@bridget7490
Copy link

Amazing! thank you! @tid-kijyun

@EmilyB-code
Copy link

The reset hotkey doesn't seem to be working for me; no matter what I set it to. Up & Down work fine, though. Using OBS Studio 27.0.1 64-bit.

@Chsbrgr
Copy link

Chsbrgr commented Nov 30, 2021

I encountered a bug when trying to use this script. If there is a digit in the "Format Text" field before the %d placeholder, it reads it as the reset value and resets it to that value when switching back and forth between scenes or selecting "Reset".
image

Works fine if there is a digit after the %d placeholder
image

Both images are after having just pressed "reset"

@Ramiro0045
Copy link

@tid-kijyun

193    function script_save(settings)
194       local hotkey_reset_save_array = obs.obs_hotkey_save(hotkey_reset_id)
195       obs.obs_data_set_array(settings, "reset_hotkey", hotkey_reset_array)
196       obs.obs_data_array_release(hotkey_reset_array)

hotkey_reset_array should be renamed to hotkey_reset_save_array

Also changed this:

80     function reset(pressed)
81         if not pressed then
82             return
83         end
84        
85         activate(false)
86         local source = obs.obs_get_source_by_name(source_name)
87         if source ~= nil then
88             local active = obs.obs_source_active(source)
89             obs.obs_source_release(source)
90             activate(active)
91         end
92     end
93     
94     function reset_button_clicked(props, p)
95         now_count = start_number
96         set_time_text()    
97         
98         reset(true)
99         return false
100   end

to this (so that it looked like the other ones that work):

80     function reset(pressed)
81         if not pressed then
82             return
83         end
84         
85         now_count = start_number
86         set_time_text()
87     end
88     
89     function reset_button_clicked(props, p)
90         reset(true)
91         return false
92     end

idk if that part is neccesary but it made the reset button to work and be saved after closing and opening again obs

@androng
Copy link

androng commented Oct 30, 2022

@Ramiro0045 I tested your changes and they fix the reset hotkey bug. I added the fixes to my fork: https://gist.github.com/androng/b1b32c97b6255978c2bb31ab8e805ad7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment