1obs = obslua
2bit = require("bit")
3
4source_def = {}
5source_def.id = "lua_clock_source"
6source_def.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO, obs.OBS_SOURCE_CUSTOM_DRAW)
7
8function image_source_load(image, file)
9	obs.obs_enter_graphics();
10	obs.gs_image_file_free(image);
11	obs.obs_leave_graphics();
12
13	obs.gs_image_file_init(image, file);
14
15	obs.obs_enter_graphics();
16	obs.gs_image_file_init_texture(image);
17	obs.obs_leave_graphics();
18
19	if not image.loaded then
20		print("failed to load texture " .. file);
21	end
22end
23
24source_def.get_name = function()
25	return "Lua Clock"
26end
27
28source_def.create = function(source, settings)
29	local data = {}
30	data.image = obs.gs_image_file()
31	data.hour_image = obs.gs_image_file()
32	data.minute_image = obs.gs_image_file()
33	data.second_image = obs.gs_image_file()
34
35	image_source_load(data.image, script_path() .. "clock-source/dial.png")
36	image_source_load(data.hour_image, script_path() .. "clock-source/hour.png")
37	image_source_load(data.minute_image, script_path() .. "clock-source/minute.png")
38	image_source_load(data.second_image, script_path() .. "clock-source/second.png")
39
40	return data
41end
42
43source_def.destroy = function(data)
44	obs.obs_enter_graphics();
45	obs.gs_image_file_free(data.image);
46	obs.gs_image_file_free(data.hour_image);
47	obs.gs_image_file_free(data.minute_image);
48	obs.gs_image_file_free(data.second_image);
49	obs.obs_leave_graphics();
50end
51
52source_def.video_render = function(data, effect)
53	if not data.image.texture then
54		return;
55	end
56
57	local time = os.date("*t")
58	local seconds = time.sec
59	local mins = time.min + seconds / 60.0;
60	local hours = time.hour + (mins * 60.0) / 3600.0;
61
62	effect = obs.obs_get_base_effect(obs.OBS_EFFECT_DEFAULT)
63
64	obs.gs_blend_state_push()
65	obs.gs_reset_blend_state()
66
67	while obs.gs_effect_loop(effect, "Draw") do
68		obs.obs_source_draw(data.image.texture, 0, 0, data.image.cx, data.image.cy, false);
69	end
70
71	obs.gs_matrix_push()
72	obs.gs_matrix_translate3f(250, 250, 0)
73	obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2 * math.pi / 60 * mins);
74	obs.gs_matrix_translate3f(-250, -250, 0)
75
76	while obs.gs_effect_loop(effect, "Draw") do
77		obs.obs_source_draw(data.minute_image.texture, 0, 0, data.image.cx, data.image.cy, false);
78	end
79
80	obs.gs_matrix_pop()
81
82	obs.gs_matrix_push()
83	obs.gs_matrix_translate3f(250, 250, 0)
84	obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2.0 * math.pi / 12 * hours);
85	obs.gs_matrix_translate3f(-250, -250, 0)
86
87	while obs.gs_effect_loop(effect, "Draw") do
88		obs.obs_source_draw(data.hour_image.texture, 0, 0, data.image.cx, data.image.cy, false);
89	end
90
91	obs.gs_matrix_pop()
92
93	obs.gs_matrix_push()
94	obs.gs_matrix_translate3f(250, 250, 0)
95	obs.gs_matrix_rotaa4f(0.0, 0.0, 1.0, 2 * math.pi / 60 * seconds);
96	obs.gs_matrix_translate3f(-250, -250, 0)
97
98	while obs.gs_effect_loop(effect, "Draw") do
99		obs.obs_source_draw(data.second_image.texture, 0, 0, data.image.cx, data.image.cy, false);
100	end
101
102	obs.gs_matrix_pop()
103
104	obs.gs_blend_state_pop()
105end
106
107source_def.get_width = function(data)
108	return 500
109end
110
111source_def.get_height = function(data)
112	return 500
113end
114
115function script_description()
116	return "Adds a \"Lua Clock\" source which draws an animated analog clock."
117end
118
119obs.obs_register_source(source_def)
120