@@ -51,6 +51,8 @@ local osx_mouse_location = nil
51
51
local use_auto_follow_mouse = true
52
52
local use_follow_outside_bounds = false
53
53
local is_following_mouse = false
54
+ local force_16_9 = true
55
+ local auto_start = false
54
56
local follow_speed = 0.1
55
57
local follow_border = 0
56
58
local follow_safezone_sensitivity = 10
@@ -87,6 +89,8 @@ local m1, m2 = version:match("(%d+%.%d+)%.(%d+)")
87
89
local major = tonumber (m1 ) or 0
88
90
local minor = tonumber (m2 ) or 0
89
91
92
+ local __ar16_9__ = 16 / 9
93
+
90
94
-- Define the mouse cursor functions for each platform
91
95
if ffi .os == " Windows" then
92
96
ffi .cdef ([[
@@ -617,7 +621,7 @@ function refresh_sceneitem(find_newest)
617
621
source_height = monitor_info .height
618
622
else
619
623
log (" ERROR: Something went wrong determining source size.\n " ..
620
- " Try using the 'Set manual source position' option and adding override values" )
624
+ " Try using the 'Set manual source position' option and adding override values" )
621
625
end
622
626
else
623
627
log (" Using source size: " .. source_width .. " , " .. source_height )
@@ -784,7 +788,8 @@ function get_target_position(zoom)
784
788
-- Remember that because we are using a crop/pad filter making the size smaller (dividing by zoom) means that we see less of the image
785
789
-- in the same amount of space making it look bigger (aka zoomed in)
786
790
local new_size = {
787
- width = zoom .source_size .width / zoom .zoom_to ,
791
+ -- if aspect ratio should be fixed to 16:9, compute width from height instead of getting directly from display size
792
+ width = (force_16_9 and (zoom .source_size .height * __ar16_9__ ) or zoom .source_size .width ) / zoom .zoom_to ,
788
793
height = zoom .source_size .height / zoom .zoom_to
789
794
}
790
795
@@ -825,11 +830,27 @@ function on_toggle_follow(pressed)
825
830
end
826
831
end
827
832
828
- function on_toggle_zoom (pressed )
829
- if pressed then
833
+ function on_toggle_zoom (pressed , force_value )
834
+ if force_value or pressed then
830
835
-- Check if we are in a safe state to zoom
831
- if zoom_state == ZoomState .ZoomedIn or zoom_state == ZoomState .None then
832
- if zoom_state == ZoomState .ZoomedIn then
836
+ if force_value or zoom_state == ZoomState .ZoomedIn or zoom_state == ZoomState .None then
837
+ local should_zoom
838
+ if force_value == nil then
839
+ should_zoom = zoom_state == ZoomState .ZoomedIn or zoom_state == ZoomState .None
840
+ else
841
+ should_zoom = force_value
842
+ end
843
+
844
+ if should_zoom then
845
+ log (" Zooming in" )
846
+ -- To zoom in, we get a new target based on where the mouse was when zoom was clicked
847
+ zoom_state = ZoomState .ZoomingIn
848
+ zoom_info .zoom_to = zoom_value
849
+ zoom_time = 0
850
+ locked_center = nil
851
+ locked_last_pos = nil
852
+ zoom_target = get_target_position (zoom_info )
853
+ else
833
854
log (" Zooming out" )
834
855
-- To zoom out, we set the target back to whatever it was originally
835
856
zoom_state = ZoomState .ZoomingOut
@@ -841,15 +862,6 @@ function on_toggle_zoom(pressed)
841
862
is_following_mouse = false
842
863
log (" Tracking mouse is off (due to zoom out)" )
843
864
end
844
- else
845
- log (" Zooming in" )
846
- -- To zoom in, we get a new target based on where the mouse was when zoom was clicked
847
- zoom_state = ZoomState .ZoomingIn
848
- zoom_info .zoom_to = zoom_value
849
- zoom_time = 0
850
- locked_center = nil
851
- locked_last_pos = nil
852
- zoom_target = get_target_position (zoom_info )
853
865
end
854
866
855
867
-- Since we are zooming we need to start the timer for the animation and tracking
@@ -1136,6 +1148,11 @@ function on_settings_modified(props, prop, settings)
1136
1148
end
1137
1149
end
1138
1150
1151
+ if auto_start then
1152
+ on_toggle_zoom (true , true )
1153
+ else
1154
+ on_toggle_zoom (true , false )
1155
+ end
1139
1156
return false
1140
1157
end
1141
1158
@@ -1164,6 +1181,8 @@ function log_current_settings()
1164
1181
socket_port = socket_port ,
1165
1182
socket_poll = socket_poll ,
1166
1183
debug_logs = debug_logs ,
1184
+ force_16_9 = force_16_9 ,
1185
+ auto_start = auto_start ,
1167
1186
version = VERSION
1168
1187
}
1169
1188
@@ -1183,6 +1202,7 @@ function on_print_help()
1183
1202
" Zoom Factor: How much to zoom in by\n " ..
1184
1203
" Zoom Speed: The speed of the zoom in/out animation\n " ..
1185
1204
" Auto follow mouse: True to track the cursor while you are zoomed in\n " ..
1205
+ " Force 16:9: True to get zoomed window as 16:9 (fixes problems with wide resolutions)\n " ..
1186
1206
" Follow outside bounds: True to track the cursor even when it is outside the bounds of the source\n " ..
1187
1207
" Follow Speed: The speed at which the zoomed area will follow the mouse when tracking\n " ..
1188
1208
" Follow Border: The %distance from the edge of the source that will re-enable mouse tracking\n " ..
@@ -1238,6 +1258,8 @@ function script_properties()
1238
1258
-- Add the rest of the settings UI
1239
1259
local zoom = obs .obs_properties_add_float (props , " zoom_value" , " Zoom Factor" , 1 , 5 , 0.5 )
1240
1260
local zoom_speed = obs .obs_properties_add_float_slider (props , " zoom_speed" , " Zoom Speed" , 0.01 , 1 , 0.01 )
1261
+ local auto_start = obs .obs_properties_add_bool (props , " auto_start" , " Auto start " )
1262
+ local force_16_9 = obs .obs_properties_add_bool (props , " force_16_9" , " Force 16:9 aspect ratio " )
1241
1263
local follow = obs .obs_properties_add_bool (props , " follow" , " Auto follow mouse " )
1242
1264
obs .obs_property_set_long_description (follow ,
1243
1265
" When enabled mouse traking will auto-start when zoomed in without waiting for tracking toggle hotkey" )
@@ -1373,6 +1395,8 @@ function script_load(settings)
1373
1395
socket_port = obs .obs_data_get_int (settings , " socket_port" )
1374
1396
socket_poll = obs .obs_data_get_int (settings , " socket_poll" )
1375
1397
debug_logs = obs .obs_data_get_bool (settings , " debug_logs" )
1398
+ auto_start = obs .obs_data_get_bool (settings , " auto_start" )
1399
+ force_16_9 = obs .obs_data_get_bool (settings , " force_16_9" )
1376
1400
1377
1401
obs .obs_frontend_add_event_callback (on_frontend_event )
1378
1402
@@ -1431,6 +1455,10 @@ function script_unload()
1431
1455
if socket_server ~= nil then
1432
1456
stop_server ()
1433
1457
end
1458
+
1459
+ if auto_start then
1460
+ on_toggle_zoom (true , false )
1461
+ end
1434
1462
end
1435
1463
1436
1464
function script_defaults (settings )
@@ -1457,6 +1485,8 @@ function script_defaults(settings)
1457
1485
obs .obs_data_set_default_int (settings , " socket_port" , 12345 )
1458
1486
obs .obs_data_set_default_int (settings , " socket_poll" , 10 )
1459
1487
obs .obs_data_set_default_bool (settings , " debug_logs" , false )
1488
+ obs .obs_data_set_default_bool (settings , " force_16_9" , true )
1489
+ obs .obs_data_set_default_bool (settings , " auto_start" , false )
1460
1490
end
1461
1491
1462
1492
function script_save (settings )
@@ -1513,6 +1543,8 @@ function script_update(settings)
1513
1543
socket_port = obs .obs_data_get_int (settings , " socket_port" )
1514
1544
socket_poll = obs .obs_data_get_int (settings , " socket_poll" )
1515
1545
debug_logs = obs .obs_data_get_bool (settings , " debug_logs" )
1546
+ force_16_9 = obs .obs_data_get_bool (settings , " force_16_9" )
1547
+ auto_start = obs .obs_data_get_bool (settings , " auto_start" )
1516
1548
1517
1549
-- Only do the expensive refresh if the user selected a new source
1518
1550
if source_name ~= old_source_name and is_obs_loaded then
@@ -1545,6 +1577,12 @@ function script_update(settings)
1545
1577
stop_server ()
1546
1578
start_server ()
1547
1579
end
1580
+
1581
+ if auto_start then
1582
+ on_toggle_zoom (true , true )
1583
+ else
1584
+ on_toggle_zoom (true , false )
1585
+ end
1548
1586
end
1549
1587
1550
1588
function populate_zoom_sources (list )
0 commit comments