Skip to content

Commit 476bec6

Browse files
Merge pull request #5 from BlankSourceCode/search-nested-scenes
Search into nested scenes
2 parents ffad708 + cfec333 commit 476bec6

File tree

1 file changed

+63
-25
lines changed

1 file changed

+63
-25
lines changed

obs-zoom-to-mouse.lua

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ function release_sceneitem()
248248
sceneitem = nil
249249
end
250250

251-
if source ~= nil then
251+
if source ~= nil then
252252
obs.obs_source_release(source)
253253
source = nil
254254
end
@@ -267,36 +267,69 @@ function refresh_sceneitem(find_newest)
267267
release_sceneitem()
268268

269269
-- Get a matching source we can use for zooming in the current scene
270+
log("Finding sceneitem for Zoom Source '" .. source_name .. "'")
270271
if source_name ~= nil then
271272
source = obs.obs_get_source_by_name(source_name)
272273
if source ~= nil then
273274
-- Get the source size, for some reason this works during load but the sceneitem source doesn't
274275
source_raw.width = obs.obs_source_get_width(source)
275276
source_raw.height = obs.obs_source_get_height(source)
276277

278+
-- Get the current scene
277279
local scene_source = obs.obs_frontend_get_current_scene()
278280
if scene_source ~= nil then
279-
local scene = obs.obs_scene_from_source(scene_source)
280-
if scene ~= nil then
281-
sceneitem = obs.obs_scene_sceneitem_from_source(scene, source)
282-
283-
local x = obs.obs_scene_find_source(scene, source_name)
284-
285-
if not x then
286-
log("Warning: Source not part of the current scene")
287-
obs.obs_source_release(scene_source)
288-
obs.obs_sceneitem_release(sceneitem)
289-
obs.obs_source_release(source)
281+
local function find_scene_item_by_name(root_scene)
282+
local queue = {}
283+
table.insert(queue, root_scene)
284+
285+
while #queue > 0 do
286+
local s = table.remove(queue, 1)
287+
log("Looking in scene '" .. obs.obs_source_get_name(obs.obs_scene_get_source(s)) .. "'")
288+
289+
-- Check if the current scene has the target scene item
290+
local found = obs.obs_scene_find_source(s, source_name)
291+
if found ~= nil then
292+
log("Found sceneitem")
293+
obs.obs_sceneitem_addref(found)
294+
return found
295+
end
290296

291-
sceneitem = nil
292-
source = nil
293-
return
297+
-- If the current scene has nested scenes, enqueue them for later examination
298+
local all_items = obs.obs_scene_enum_items(s)
299+
if all_items then
300+
for _, item in pairs(all_items) do
301+
local nested = obs.obs_sceneitem_get_source(item)
302+
if nested ~= nil and obs.obs_source_is_scene(nested) then
303+
local nested_scene = obs.obs_scene_from_source(nested)
304+
table.insert(queue, nested_scene)
305+
end
306+
end
307+
obs.sceneitem_list_release(all_items)
308+
end
294309
end
295-
monitor_info = get_monitor_info(source)
310+
311+
return nil
296312
end
297313

314+
-- Find the sceneitem for the source_name by looking through all the items
315+
-- We start at the current scene and use a BFS to look into any nested scenes
316+
local current = obs.obs_scene_from_source(scene_source)
317+
sceneitem = find_scene_item_by_name(current)
318+
298319
obs.obs_source_release(scene_source)
299320
end
321+
322+
if not sceneitem then
323+
log("Warning: Source not part of the current scene hierarchy")
324+
obs.obs_sceneitem_release(sceneitem)
325+
obs.obs_source_release(source)
326+
327+
sceneitem = nil
328+
source = nil
329+
return
330+
end
331+
332+
monitor_info = get_monitor_info(source)
300333
end
301334
end
302335
end
@@ -333,11 +366,13 @@ function refresh_sceneitem(find_newest)
333366
log("Source size determined as " .. source_width .. ", " .. source_height)
334367
if source_width == 0 or source_height == 0 then
335368
if monitor_info and monitor_info.height > 0 and monitor_info.height > 0 then
336-
log("Warning: Something went wrong determining source size, defaulting to monitor size " .. monitor_info.width .. ", " .. monitor_info.height)
369+
log("Warning: Something went wrong determining source size, defaulting to monitor size " ..
370+
monitor_info.width .. ", " .. monitor_info.height)
337371
source_width = monitor_info.width
338372
source_height = monitor_info.height
339373
else
340-
log("Error: Something went wrong determining source size, try using the 'Set manual monitor position' option and adding override values")
374+
log("Error: Something went wrong determining source size," ..
375+
"try using the 'Set manual monitor position' option and adding override values")
341376
end
342377
end
343378

@@ -508,11 +543,10 @@ function get_target_position(zoom_info)
508543
}
509544

510545
-- Keep the zoom in bounds of the source so that we never show something outside that user is trying to hide with existing crop settings
511-
crop.x = clamp(0, (zoom_info.source_size.width - new_size.width), crop.x)
512-
crop.y = clamp(0, (zoom_info.source_size.height - new_size.height), crop.y)
513-
546+
crop.x = math.floor(clamp(0, (zoom_info.source_size.width - new_size.width), crop.x))
547+
crop.y = math.floor(clamp(0, (zoom_info.source_size.height - new_size.height), crop.y))
514548

515-
return { crop = crop, raw_center = mouse, clamped_center = { x = crop.x + crop.w * 0.5, y = crop.y + crop.h * 0.5 } }
549+
return { crop = crop, raw_center = mouse, clamped_center = { x = math.floor(crop.x + crop.w * 0.5), y = math.floor(crop.y + crop.h * 0.5) } }
516550
end
517551

518552
function on_toggle_follow(pressed)
@@ -542,6 +576,10 @@ function on_toggle_zoom(pressed)
542576
zoom_time = 0
543577
locked_center = nil
544578
zoom_target = { crop = crop_filter_info_orig, c = sceneitem_crop_orig }
579+
if is_following_mouse then
580+
is_following_mouse = false
581+
log("Tracking mouse is off (due to zoom out)")
582+
end
545583
else
546584
log("Zooming in")
547585
-- To zoom in, we get a new target based on where the mouse was when zoom was clicked
@@ -593,12 +631,12 @@ function on_timer()
593631
end
594632

595633
if not skip_frame then
596-
-- If we have a locked_center it means we are currently in a locked zone and
634+
-- If we have a locked_center it means we are currently in a locked zone and
597635
-- shouldn't track the mouse until it moves out of the area
598636
if locked_center ~= nil then
599637
local diff = {
600-
x = math.abs(zoom_target.raw_center.x - locked_center.x),
601-
y = math.abs(zoom_target.raw_center.y - locked_center.y)
638+
x = zoom_target.raw_center.x - locked_center.x,
639+
y = zoom_target.raw_center.y - locked_center.y
602640
}
603641

604642
local track = {

0 commit comments

Comments
 (0)