Skip to content

Instantly share code, notes, and snippets.

@rishubil
Created April 11, 2019 01:21
Show Gist options
  • Save rishubil/ece475cc4b3f71caee714ce43dd8e4b2 to your computer and use it in GitHub Desktop.
Save rishubil/ece475cc4b3f71caee714ce43dd8e4b2 to your computer and use it in GitHub Desktop.
Zoooooom.lua
local obs = obslua
local pow = math.pow
local source, interval, duration, iPosX, iPosY, iScaleX, iScaleY, zRatio, zCenterX, zCenterY, targetScale, debug
local sceneItem
local iWidth = 0
local iHeight = 0
local isZoomed = false
local isZooming = false
local zoomT = 0
local hk = {}
local hotkeys = {
ZOOM_action = "Toggle zoom-in source",
ZOOM_reset = "Reset zoom-in source"
}
local function currentSceneName()
local src = obs.obs_frontend_get_current_scene()
local name = obs.obs_source_get_name(src)
obs.obs_source_release(src)
return name
end
local function findSceneItem(itemName)
local src = obs.obs_get_source_by_name(currentSceneName())
if src then
local scene = obs.obs_scene_from_source(src)
obs.obs_source_release(src)
if scene then
sceneItem = obs.obs_scene_find_source(scene, source)
if sceneItem and debug then obs.script_log(obs.LOG_INFO, string.format("Found : %s", source)) end
return true
end
end
sceneItem = nil
end
local function inOutQuad(t, b, c, d)
-- https://github.com/EmmanuelOga/easing/blob/master/lib/easing.lua
-- t = elapsed time
-- b = begin
-- c = change == ending - beginning
-- d = duration (total time)
t = t / d * 2
if t < 1 then
return c / 2 * pow(t, 2) + b
else
return -c / 2 * ((t - 1) * (t - 3) - 1) + b
end
end
local function updateScale(ratio)
if sceneItem then
local scaleV = obs.vec2()
scaleV.x = iScaleX * ratio
scaleV.y = iScaleY * ratio
if debug then obs.script_log(obs.LOG_INFO, string.format("scaleV.x : %s", scaleV.x)) end
if debug then obs.script_log(obs.LOG_INFO, string.format("scaleV.y : %s", scaleV.y)) end
obs.obs_sceneitem_set_scale(sceneItem, scaleV)
end
end
local function updatePos(ratio)
if sceneItem then
local posV = obs.vec2()
posV.x = iPosX + (zCenterX / 100) * iWidth * (1 - ratio)
posV.y = iPosY + (zCenterY / 100) * iHeight * (1 - ratio)
if debug then obs.script_log(obs.LOG_INFO, string.format("posV.x : %s", posV.x)) end
if debug then obs.script_log(obs.LOG_INFO, string.format("posV.y : %s", posV.y)) end
obs.obs_sceneitem_set_pos(sceneItem, posV)
end
end
local function zoom()
if isZooming then
zoomT = zoomT + interval
if debug then obs.script_log(obs.LOG_INFO, string.format("zoomT : %s", zoomT)) end
if zoomT > duration then
isZooming = false
isZoomed = not isZoomed
zoomT = 0
return obs.remove_current_callback()
end
local easeRatio = 0
if isZoomed then
easeRatio = inOutQuad(zoomT, zRatio, 100 - zRatio, duration) / 100
else
easeRatio = inOutQuad(zoomT, 100, zRatio - 100, duration) / 100
end
if debug then obs.script_log(obs.LOG_INFO, string.format("easeRatio : %s", easeRatio)) end
updateScale(easeRatio)
updatePos(easeRatio)
else
return obs.remove_current_callback()
end
end
local function doZoom()
if sceneItem then
local zoomSource = obs.obs_sceneitem_get_source(sceneItem)
iWidth = obs.obs_source_get_width(zoomSource) * iScaleX
iHeight = obs.obs_source_get_height(zoomSource) * iScaleY
end
obs.timer_remove(zoom)
zoomT = 0
isZooming = true
obs.timer_add(zoom, interval)
end
local function printCurrent()
if sceneItem then
local posV = obs.vec2()
local scaleV = obs.vec2()
obs.obs_sceneitem_get_pos(sceneItem, posV)
obs.obs_sceneitem_get_scale(sceneItem, scaleV)
obs.script_log(obs.LOG_INFO, string.format("posV.x : %s", posV.x))
obs.script_log(obs.LOG_INFO, string.format("posV.y : %s", posV.y))
obs.script_log(obs.LOG_INFO, string.format("scaleV.x : %s", scaleV.x))
obs.script_log(obs.LOG_INFO, string.format("scaleV.y : %s", scaleV.y))
else
obs.remove_current_callback()
end
end
local function resetZoom()
obs.timer_remove(zoom)
if sceneItem then
local posV = obs.vec2()
posV.x = iPosX
posV.y = iPosY
local scaleV = obs.vec2()
scaleV.x = iScaleX
scaleV.y = iScaleY
obs.obs_sceneitem_set_pos(sceneItem, posV)
obs.obs_sceneitem_set_scale(sceneItem, scaleV)
zoomT = 0
isZoomed = false
isZooming = false
else
obs.remove_current_callback()
end
end
-- add any custom actions here
local function onHotKey(action)
if debug then obs.script_log(obs.LOG_INFO, string.format("Hotkey : %s", action)) end
if action == "ZOOM_action" then
doZoom()
elseif action == "ZOOM_reset" then
resetZoom()
end
end
----------------------------------------------------------
-- called on startup
function script_load(settings)
for k, v in pairs(hotkeys) do
hk[k] = obs.obs_hotkey_register_frontend(k, v, function(pressed) if pressed then onHotKey(k) end end)
local hotkeyArray = obs.obs_data_get_array(settings, k)
obs.obs_hotkey_load(hk[k], hotkeyArray)
obs.obs_data_array_release(hotkeyArray)
end
end
-- called on unload
function script_unload()
end
-- called when settings changed
function script_update(settings)
source = obs.obs_data_get_string(settings, "source")
duration = obs.obs_data_get_int(settings, "duration")
interval = obs.obs_data_get_int(settings, "interval")
iPosX = obs.obs_data_get_double(settings, "iPosX")
iPosY = obs.obs_data_get_double(settings, "iPosY")
iScaleX = obs.obs_data_get_double(settings, "iScaleX")
iScaleY = obs.obs_data_get_double(settings, "iScaleY")
zRatio = obs.obs_data_get_double(settings, "zRatio")
zCenterX = obs.obs_data_get_double(settings, "zCenterX")
zCenterY = obs.obs_data_get_double(settings, "zCenterY")
debug = obs.obs_data_get_bool(settings, "debug")
findSceneItem()
end
-- return description shown to user
function script_description()
return "Zoom-in and zoom-out source with hotkeys"
end
-- define properties that user can change
function script_properties()
local props = obs.obs_properties_create()
obs.obs_properties_add_text(props, "source", "Source to zoom", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_int(props, "duration", "Duration (ms)", 10, 100000, 1)
obs.obs_properties_add_int(props, "interval", "Interval (ms)", 5, 100, 1)
obs.obs_properties_add_float(props, "iPosX", "Initial x Position", -1000000, 1000000, 0.01)
obs.obs_properties_add_float(props, "iPosY", "Initial y Position", -1000000, 1000000, 0.01)
obs.obs_properties_add_float(props, "iScaleX", "Initial x Scale", 0, 100, 0.01)
obs.obs_properties_add_float(props, "iScaleY", "Initial y Scale", 0, 100, 0.01)
obs.obs_properties_add_float(props, "zRatio", "Zoom ratio (%)", 0, 10000, 0.01)
obs.obs_properties_add_float_slider(props, "zCenterX", "Horizontal center to zoom (%)", 0, 100, 0.01)
obs.obs_properties_add_float_slider(props, "zCenterY", "Vertical center to zoom (%)", 0, 100, 0.01)
obs.obs_properties_add_button(props, "printCurrent", "Print current values", printCurrent)
obs.obs_properties_add_button(props, "reset", "Reset zoom", resetZoom)
obs.obs_properties_add_button(props, "doZoom", "Test zoom", doZoom)
obs.obs_properties_add_bool(props, "debug", "Debug")
return props
end
-- set default values
function script_defaults(settings)
obs.obs_data_set_default_string(settings, "source", "")
obs.obs_data_set_default_int(settings, "duration", 5)
obs.obs_data_set_default_int(settings, "interval", 10)
obs.obs_data_set_default_double(settings, "iPosX", 0.0)
obs.obs_data_set_default_double(settings, "iPosY", 0.0)
obs.obs_data_set_default_double(settings, "iScaleX", 1.0)
obs.obs_data_set_default_double(settings, "iScaleY", 1.0)
obs.obs_data_set_default_double(settings, "zRatio", 100.0)
obs.obs_data_set_default_double(settings, "zCenterX", 50.0)
obs.obs_data_set_default_double(settings, "zCenterY", 50.0)
obs.obs_data_set_default_bool(settings, "debug", false)
end
-- save additional data not set by user
function script_save(settings)
for k, v in pairs(hotkeys) do
local hotkeyArray = obs.obs_hotkey_save(hk[k])
obs.obs_data_set_array(settings, k, hotkeyArray)
obs.obs_data_array_release(hotkeyArray)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment