Resource icon

New ClockSource.Lua script 2020-08-17

DCStrato

Member
I am retired and just do this for fun. Here is the NewClock code if you want to play with it again sometime.
The source_def.get_properties function where the new face and hands options are offered is pretty simple. Seems like it would either work or not work. But OBS is its own kind of unique sometimes for sure.

D.C.
------------------------------
Code:
obs = obslua
bit = require("bit")

source_def = {}
source_def.id = "lua_clock_source"
source_def.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO, obs.OBS_SOURCE_CUSTOM_DRAW)

PartSeconds = 0

function timer_callback()
    PartSeconds = PartSeconds + 1
end

function image_source_load(image, file)
    obs.obs_enter_graphics();
    obs.gs_image_file_free(image);
    obs.obs_leave_graphics();

    obs.gs_image_file_init(image, file);

    obs.obs_enter_graphics();
    obs.gs_image_file_init_texture(image);
    obs.obs_leave_graphics();

    if not image.loaded then
        print("failed to load texture " .. file);
    end
end

source_def.get_name = function()
    return "Lua Clock"
end

source_def.update = function (data, settings)
    image_source_load(data.image, script_path() .. "clock-source/dial" .. obs.obs_data_get_string(settings, "Face") .. ".png")
    image_source_load(data.hour_image, script_path() .. "clock-source/hour" .. obs.obs_data_get_string(settings, "Hands") .. ".png")
    image_source_load(data.minute_image, script_path() .. "clock-source/minute" .. obs.obs_data_get_string(settings, "Hands") .. ".png")
    image_source_load(data.second_image, script_path() .. "clock-source/second" .. obs.obs_data_get_string(settings, "Hands") .. ".png")
    data.fast = obs.obs_data_get_bool(settings, "qrttics")
    return true
end

    
source_def.get_properties = function (data)
    local props = obs.obs_properties_create()
    local prop_face = obs.obs_properties_add_list(props, "Face", "Face Style", obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_STRING)
    obs.obs_property_list_add_string(prop_face,"Orignal", "")
    obs.obs_property_list_add_string(prop_face,"School", "1")
    obs.obs_property_list_add_string(prop_face,"MinTics", "2")
    obs.obs_property_list_add_string(prop_face,"NoTics", "3")
    obs.obs_property_list_add_string(prop_face,"Script", "4")
        obs.obs_property_list_add_string(prop_face,"Black", "5")
    local prop_hands = obs.obs_properties_add_list(props, "Hands", "Hand Style", obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_STRING)
    obs.obs_property_list_add_string(prop_hands,"Orignal", "")
    obs.obs_property_list_add_string(prop_hands,"Tapered", "1")
    obs.obs_property_list_add_string(prop_hands,"Fancy", "2")
        obs.obs_property_list_add_string(prop_hands,"White", "3")
    obs.obs_properties_add_bool(props,"qrttics","Increment Second Hand by 1/4 second")
    return props
end

source_def.get_defaults = function(settings) 
   obs.obs_data_set_default_string(settings, "Face", "")
   obs.obs_data_set_default_string(settings, "Hands", "")
   obs.obs_data_set_default_bool(settings, "qrttics", false)
end


source_def.create = function(settings, source)
    local data = {}
    data.image= obs.gs_image_file()
    data.hour_image = obs.gs_image_file()
    data.minute_image = obs.gs_image_file()
    data.second_image = obs.gs_image_file()

    image_source_load(data.image, script_path() .. "clock-source/dial" .. obs.obs_data_get_string(settings, "Face") .. ".png")
    image_source_load(data.hour_image, script_path() .. "clock-source/hour" .. obs.obs_data_get_string(settings, "Hands") .. ".png")
    image_source_load(data.minute_image, script_path() .. "clock-source/minute" .. obs.obs_data_get_string(settings, "Hands") .. ".png")
    image_source_load(data.second_image, script_path() .. "clock-source/second" .. obs.obs_data_get_string(settings, "Hands") .. ".png")
    data.fast = obs.obs_data_get_bool(settings, "qrttics")
    local time = os.date("*t")    
    return data
end

source_def.destroy = function(data)
    obs.obs_enter_graphics();
    obs.gs_image_file_free(data.image);
    obs.gs_image_file_free(data.hour_image);
    obs.gs_image_file_free(data.minute_image);
    obs.gs_image_file_free(data.second_image);
    obs.obs_leave_graphics();
end

source_def.video_render = function(data, effect)
    if not data.image.texture then
        return;
    end

    local time = os.date("*t")
    local secs = time.sec * 4

    if (time.min == 0) then
       PartSeconds = 0
    end
    
    if data.fast then
       secs = PartSeconds
    end
    
    local mins = time.min + time.sec / 60.0;
    local hours = time.hour + (mins * 60.0) / 3600.0;

    effect = obs.obs_get_base_effect(obs.OBS_EFFECT_DEFAULT)

    obs.gs_blend_state_push()
    obs.gs_reset_blend_state()

    while obs.gs_effect_loop(effect, "Draw") do
        obs.obs_source_draw(data.image.texture, 0, 0, data.image.cx, data.image.cy, false);
    end

    obs.gs_matrix_push()
    obs.gs_matrix_translate3f(250, 250, 0)
    obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2 * math.pi / 60 * mins);
    obs.gs_matrix_translate3f(-250, -250, 0)

    while obs.gs_effect_loop(effect, "Draw") do
        obs.obs_source_draw(data.minute_image.texture, 0, 0, data.image.cx, data.image.cy, false);
    end

    obs.gs_matrix_pop()

    obs.gs_matrix_push()
    obs.gs_matrix_translate3f(250, 250, 0)
    obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2.0 * math.pi / 12 * hours);
    obs.gs_matrix_translate3f(-250, -250, 0)

    while obs.gs_effect_loop(effect, "Draw") do
        obs.obs_source_draw(data.hour_image.texture, 0, 0, data.image.cx, data.image.cy, false);
    end

    obs.gs_matrix_pop()

    obs.gs_matrix_push()
    obs.gs_matrix_translate3f(250, 250, 0)
    obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2 * math.pi / 240 * secs);
    obs.gs_matrix_translate3f(-250, -250, 0)

    while obs.gs_effect_loop(effect, "Draw") do
        obs.obs_source_draw(data.second_image.texture, 0, 0, data.image.cx, data.image.cy, false);
    end

    obs.gs_matrix_pop()

    obs.gs_blend_state_pop()
end

source_def.get_width = function(data)
    return 500
end

source_def.get_height = function(data)
    return 500
end

function script_description()
    return "Adds a \"Lua Clock\" source which draws an animated analog clock."
end
        obs.timer_add(timer_callback, 250)

obs.obs_register_source(source_def)
 

Banyarola

Active Member
Thanks DC...taking what you said it seems OBS was trying to use the old code so I just replaced the code..
They should tell you when installing a replacement you need to delete the old one first...Otherwise, I and others would think it works like an upgrade and not a new install..
Anyway, that's for your help, it solved my problem..
 
Last edited:

muddflea

New Member
It doesn't show up in sources using OBS V27.0.1 period. Like the Move Transition 2.4.4, you need 2.4.1 or lower.
 

DCStrato

Member
It doesn't show up in sources using OBS V27.0.1 period. Like the Move Transition 2.4.4, you need 2.4.1 or lower.
Sorry muddflea,

I am unable to reproduce your issue of the source not showing up in V27.0.1 What is your operating environment?
1627193693107.png
 

Laczkó

New Member
The "Increment Second Hand by 1/4 second" is a good option, but I would like more that the second hand move contiously, so I tried to modify the code (with zero programming knowledge I didn't succed — what a surprise). I found where to change the tick angle, but I didn't figure out, what controls the frequency of ticking. Could somebody help in this? (Obviously the goal not necessarily to code a continous movement, one tick per frame frequency is enough, what is 50 tick per second in my case.)
 

DCStrato

Member
I tried to initially get it to 1/8th second but was not able to keep the code stable using callbacks. There might be a way to rotate the second hand at the frame rate and maybe still sync up every minute to manage any skipped frames. I will try to look at it again this weekend.

D.C.
 

DCStrato

Member
The "Increment Second Hand by 1/4 second" is a good option, but I would like more that the second hand move contiously, so I tried to modify the code (with zero programming knowledge I didn't succed — what a surprise). I found where to change the tick angle, but I didn't figure out, what controls the frequency of ticking. Could somebody help in this? (Obviously the goal not necessarily to code a continous movement, one tick per frame frequency is enough, what is 50 tick per second in my case.)
Here is an Analog version that uses Script_tick to increment seconds every frame.

D.C.
 

Attachments

  • Analog_clock_source.zip
    1.5 KB · Views: 72

advisionmatt

New Member
Love this clock. I've added it to a project along with a digital clock which is extracted from the PC system time. However - the LUA clcok always runs almost half a second fast - so the LUA clock is actually ahead of the systems time. Where in the script can I delay this - or even sync it?
 

DCStrato

Member
Love this clock. I've added it to a project along with a digital clock which is extracted from the PC system time. However - the LUA clcok always runs almost half a second fast - so the LUA clock is actually ahead of the systems time. Where in the script can I delay this - or even sync it?
Thanks. I didn't write the original Lua-clock, only modified it to have half-secs and additional clock graphics. I do not know if the video_render function can be delayed or not. It shows perfectly in sync wioth the system clock on my computer. I'll look into it if I get a chance.

DC
 
Top