-- [[ Hide2Show 5.4.3 BLOCK ]] -- [[ variable data ]] os = require("os") bit = require("bit") APP = { SHOW = 1; HIDE = 2; QK = 50; VF = 1; NR = 100; STEPS = 10;ACT = { ACT1 = "act1";ACT2 = "act2"; ACT3 = "act3" } } on_exit=false local __settings__ = nil local animation_list = { {id = "lr";name = "From left to right";opt_out = { "act1","act2","act3" },ignore_opt = { "anime_rt_list","anime_rt_cst" }},{id = "rl";name = "From right to left";opt_out = { "act1","act2","act3" },ignore_opt = { "anime_rt_list","anime_rt_cst" }}, {id = "tb";name = "From top to bottom";opt_out = { "act1","act2","act3" },ignore_opt = { "anime_rt_list","anime_rt_cst" }},{id = "bt";name = "From bottom to top";opt_out = { "act1","act2","act3" }, ignore_opt = { "anime_rt_list","anime_rt_cst" }},{id = "fl";name = "Flicker";ignore_opt = { "anime_velcity_value","anime_rt_list","anime_rt_cst" }},{id = "bnc";name = "Hover";ignore_opt = { "anime_velcity_value","anime_rt_list","anime_rt_cst" }},{id = "pls";name = "Pulsing";ignore_opt = { "anime_velcity_value","anime_rt_list","anime_rt_cst" }} } local rotation_list = { {id = "rt_90"; name = "90°"}, {id = "rt_180"; name = "180°"}, {id ="rt_360"; name = "360°"}, {id= "cst", name= "Custom"} } -- [[ Functionality ]] function setup(settings) local Hide2Show= obs.script.filter({ name="Hide2Show", id="hns-filter-iixisii-vs5.4.0", }); function Hide2Show.setup(src) src.currTime=os.clock() src.action=APP.HIDE src.init=false src.timer=nil src.anime_target="def" src.anime_rt=nil src.anime_rt_value=nil src.todate=false end function Hide2Show.defaults(settings) settings.bul("action_hide_group",true, true) settings.str("hide_interval_type","mis", true) settings.int("hide_time",1, true) settings.bul("hide_time_random",false, true) -- settings.bul("action_show_group",true, true) settings.str("show_interval_type","mis", true) settings.int("show_time",1, true) settings.bul("show_time_random",false, true) -- settings.int("defAction",-1, true) settings.int("anime_velcity_value", 10, true) end function Hide2Show.properties(src) local ui= obs.script.create() local ui_action= obs.script.create() -- [[ Hide ]] local ui_hide_action= obs.script.create() obs.script.group(ui, "action_hide_group","Hide Time", ui_hide_action) local hide_interval_type= obs.script.options(ui_hide_action, "hide_interval_type","") hide_interval_type.onchange(function(value) obs.script.get("hide_time").suffix(" " .. tostring(value)) return true end) hide_interval_type.add.str( "milliseconds", "mis" ).add.str("seconds", "sc").add.str( "minutes", "ms" ).add.str("hours", "hr") obs.script.number(ui_hide_action, 1, 999999999,1, "hide_time","") obs.script.bool(ui_hide_action, "hide_time_random","Randomness") -- [[ Show ]] local ui_show_action= obs.script.create() obs.script.group(ui, "action_show_group","Show Time", ui_show_action) local show_interval_type= obs.script.options(ui_show_action, "show_interval_type","") show_interval_type.onchange(function(value) obs.script.get("show_time").suffix(" " .. tostring(value)) return true end) show_interval_type.add.str( "milliseconds", "mis" ).add.str("seconds", "sc").add.str( "minutes", "ms" ).add.str("hours", "hr") obs.script.number(ui_show_action, 1, 999999999,1, "show_time","") obs.script.bool(ui_show_action, "show_time_random","Randomness") -- [[ Animation ]] local ui_anime= obs.script.create() obs.script.group(ui, "animation_group","Animation", ui_anime) -- [[ Animation List ]] -- [[ Animation Style ]] local anime_style_list= obs.script.options(ui_anime, "anime_style_list","Animation: ") anime_style_list.onchange(function(value, p, pp, settings) if value ~= "def" then obs.script.get("anime_speed_list").show() obs.script.get("anime_velcity_value").show() else obs.script.get("anime_speed_list").hide() obs.script.get("anime_velcity_value").hide() end return true end) anime_style_list.add.str( "View animations ( optional )","def" ) for _, iter in pairs(animation_list) do if iter and iter.opt_out ~= nil then local isvalid = true for _, itemValue in pairs(iter.opt_out) do if itemValue == value then isvalid = false break end end if isvalid then anime_style_list.add.str(iter.name, iter.id) if iter.id == current_anime then is_listed = true end end else anime_style_list.add.str(iter.name, iter.id) if iter.id == current_anime then is_listed = true end end end -- [[ Animation Rotation ]] -- [[ Custom Rotation ]] -- [[ Animation Speed ]] local anime_speed_list= obs.script.options(ui_anime, "anime_speed_list","Interval: ") anime_speed_list.add.str( "Normal ( system default )", "nr" ).add.str("Quick","qk").add.str( "Very fast","vf" ).add.str("Slow", "sl").hide() -- [[ Animation Velocity ]] local anime_velcity_value= obs.script.number( ui_anime, 1, 1000,1, "anime_velcity_value","Velocity: ", obs.enum.number.int,obs.enum.number.slider ).hide() return ui end function Hide2Show.update(src) if src.timer ~= nil then obslua.timer_remove(src.timer) end src.init=false;src.is_loading=false src.action= src.defAction if src.action == nil then src.action= APP.SHOW end src.timer=nil reset_to_default(src) -- Call a default setup function for the source -- src.currTime= os.clock() src.hide_time = src.settings.get_int("hide_time") src.hide_time_random = src.settings.get_bul("hide_time_random") local hide_time_type= src.settings.str("hide_interval_type") if hide_time_type == "sc" then src.hide_time = src.hide_time * 1000 elseif hide_time_type == "ms" then src.hide_time= src.hide_time * 60000 elseif hide_time_type == "hr" then src.hide_time= src.hide_time * 3600000 end src.hide_time_max= src.hide_time if src.hide_time_random then src.hide_time= math.random(1, src.hide_time_max) end -- src.show_time = src.settings.get_int("show_time") src.show_time_random = src.settings.get_bul("show_time_random") local show_time_type= src.settings.str("show_interval_type") if show_time_type == "sc" then src.show_time = src.show_time * 1000 elseif show_time_type == "ms" then src.show_time= src.show_time * 60000 elseif show_time_type == "hr" then src.show_time= src.show_time * 3600000 end src.show_time_max= src.show_time if src.show_time_random then src.show_time= math.random(1, src.show_time_max) end -- src.steps = src.settings.get_int("anime_velcity_value") src.anime_opt = src.settings.get_str("anime_style_list") src.anime_tim = src.settings.get_str("anime_speed_list") src.anime_target = src.settings.get_str("anime_list") if src and src.item and src.item.data then local defPos= src.settings.obj("defPos") local defScale= src.settings.obj("defScale") local item_info=obslua.obs_transform_info() obslua.obs_sceneitem_get_info2(src.item.data, item_info) src.defPos=item_info.pos src.defScale=item_info.scale if defPos and defPos.data ~= nil then defPos.int("x", src.defPos.x).int("y", src.defPos.y) src.settings.obj("defPos", defPos.data) defPos.free() end if defScale and defScale.data then defScale.int("x", src.defScale.x).int("y", src.defScale.y) src.settings.obj("defScale", defScale.data) defScale.free() end src.todate=true else src.todate=false return false end end function Hide2Show.video_tick(src) if src.source ~= nil and obslua.obs_source_enabled(src.source) == false then if not src.enabled_checked then src.enabled_checked= true if src.timer then obslua.timer_remove(src.timer) src.timer= nil end reset_to_default(src) src.settings.int("defAction",-1) src.is_loading=false src.defPos=nil;src.defScale=nil src.defRot=nil;src.init=false end return false else src.enabled_checked=false end if not src.todate then return Hide2Show.update(src) end if not src.init then src.init=true if src.item and src.item.data ~= nil then src.currTime= os.clock() if obslua.obs_sceneitem_visible(src.item.data) then src.action= APP.HIDE else src.action = APP.SHOW end src.defAction= src.settings.int("defAction") if src.defAction ~= APP.HIDE and src.defAction ~= APP.SHOW then if src.action == APP.HIDE then src.defAction= APP.SHOW else src.defAction= APP.HIDE end src.settings.int("defAction", src.defAction) end if src.defPos == nil then src.defPos= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, src.defPos) local pos= obs.PairStack() pos.int("x", src.defPos.x).int( "y", src.defPos.y ) src.settings.obj("defPos",pos.data) pos.free() end if src.defRot == nil then src.defRot= obslua.obs_sceneitem_get_rot( src.item.data ) src.settings.int("defRot", src.defRot) end if src.defScale == nil then src.defScale= obslua.vec2() obslua.obs_sceneitem_get_scale( src.item.data,src.defScale ) local scale= obs.PairStack() scale.int("x", src.defScale.x) scale.int("y", src.defScale.y) src.settings.obj("defScale", scale.data) scale.free() end end local scene= obs.scene:get_scene() src.base_width= scene.get_width() src.base_height= scene.get_height() scene.free() end if not src.is_loading then if src.currTime == nil then return end local currTick= (os.clock() - src.currTime) * 1000 -- [[ HANDLE HIDE ]] if currTick ~= nil and src.hide_time ~= nil and src.action == APP.HIDE and currTick >= src.hide_time then local function init_hide() src.currTime= os.clock() src.action= APP.SHOW if src.hide_time_random == true then src.hide_time= math.random(1, src.hide_time_max) else src.hide_time= src.hide_time_max end src.is_loading=false if not src.item or src.item.data == nil then return end obslua.obs_sceneitem_set_visible(src.item.data, false) end if src and src.item and src.item.data and src.anime_opt ~= nil and src.anime_opt ~= "" and src.anime_opt ~= "def" then src.is_loading=true local pos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, pos) local anime_config = nil local speed = APP.NR if src.anime_tim == "qk" then speed = APP.QK elseif src.anime_tim == "vf" then speed = APP.VF end if true then if src.anime_opt == "lr" then -- left to right animate(src, speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.x = p.x + src.steps if p.x >= src.base_width then p.x=src.base_width obslua.obs_sceneitem_set_pos(src.item.data, p) return true end obslua.obs_sceneitem_set_pos(src.item.data, p) return false end).after(init_hide) elseif src.anime_opt == "rl" then -- right to left --local p=obslua.vec2() --p.x= src.base_width - src.width --p.y= src.defPos.y --obslua.obs_sceneitem_set_pos(src.item.data, p) animate(src,speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.x = p.x - src.steps obslua.obs_sceneitem_set_pos(src.item.data, p) if p.x <= -src.width and tostring(p.x):sub(1,1) == "-" then p.x=-src.width obslua.obs_sceneitem_set_pos(src.item.data, p) return true end return false end).after(init_hide) elseif src.anime_opt == "tb" then -- top to bottom animate(src, speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.y = p.y - src.steps if tostring(p.y):sub(1,1) == "-" and math.abs(p.y) >= math.abs(src.height) then p.y=-src.height obslua.obs_sceneitem_set_pos(src.item.data, p) return true end obslua.obs_sceneitem_set_pos(src.item.data, p) return false end).after(init_hide) elseif src.anime_opt == "bt" then animate(src, speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.y = p.y + src.steps if p.y >= math.abs(src.base_height) then p.y=src.base_height obslua.obs_sceneitem_set_pos(src.item.data, p) return true end obslua.obs_sceneitem_set_pos(src.item.data, p) return false end).after(init_hide) elseif src.anime_opt == "fl" then animate(src, speed).flicker().after(init_hide) elseif src.anime_opt == "bnc" then -- hover animate(src, speed).bounce().after(init_hide) elseif src.anime_opt == "pls" then -- pulsing animate(src, speed).pulsing().after(init_hide) else init_hide() end else init_hide() end else init_hide() end -- [[ HANDLE SHOW ]] elseif currTick ~= nil and src.show_time ~= nil and src.action == APP.SHOW and currTick >= src.show_time then local function init_show() src.currTime = os.clock() src.action = APP.HIDE if src.show_time_random == true then src.show_time = math.random(1, src.show_time_max) end src.is_loading = false if not src.item or src.item.data == nil then return end obslua.obs_sceneitem_set_visible(src.item.data, true) end if src and src.item and src.item.data and src.anime_opt ~= nil and src.anime_opt ~= "def" then src.is_loading = true local pos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, pos) local speed = APP.NR if src.anime_tim == "qk" then speed = APP.QK elseif src.anime_tim == "vf" then speed = APP.VF end if true then obslua.obs_sceneitem_set_visible(src.item.data, true) if src.anime_opt == "lr" then -- left to right local p= obslua.vec2() p.y=src.defPos.y;p.x=-(src.width) obslua.obs_sceneitem_set_pos(src.item.data, p) animate(src, speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.x = p.x + src.steps if p.x >= src.defPos.x then p.x=src.defPos.x obslua.obs_sceneitem_set_pos(src.item.data, p) return true end obslua.obs_sceneitem_set_pos(src.item.data, p) return false end).after(init_show) elseif src.anime_opt == "rl" then -- right to left local p=obslua.vec2() p.x= src.base_width p.y= src.defPos.y obslua.obs_sceneitem_set_pos(src.item.data, p) animate(src, speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.x = p.x - src.steps obslua.obs_sceneitem_set_pos(src.item.data, p) if p.x == src.defPos.x or p.x <= src.defPos.x then p.x=src.defPos.x obslua.obs_sceneitem_set_pos(src.item.data, p) return true end return false end).after(init_show) elseif src.anime_opt == "tb" then -- top to bottom local p= obslua.vec2() p.y=src.base_height;p.x=src.defPos.x obslua.obs_sceneitem_set_pos(src.item.data, p) animate(src, speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.y = p.y + src.steps if p.x >= src.defPos.y then p.y=src.defPos.y obslua.obs_sceneitem_set_pos(src.item.data, p) return true end obslua.obs_sceneitem_set_pos(src.item.data, p) end).after(init_show) elseif src.anime_opt == "bt" then -- bottom to top local p= obslua.vec2() p.y=-src.height;p.x=src.defPos.x obslua.obs_sceneitem_set_pos(src.item.data, p) animate(src, speed).move_while(function(src) local p= obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, p) p.y = p.y + src.steps if p.y >= src.defPos.y then p.y=src.defPos.y obslua.obs_sceneitem_set_pos(src.item.data, p) return true end obslua.obs_sceneitem_set_pos(src.item.data, p) end).after(init_show) elseif src.anime_opt == "fl" then animate(src, speed).flicker().after(init_show) elseif src.anime_opt == "bnc" then -- hover animate(src, speed).bounce().after(init_show) elseif src.anime_opt == "pls" then -- pulsing animate(src, speed).pulsing().after(init_show) else init_show() end else end else init_show() end end end end function Hide2Show.destroy(src) if src and src.timer ~= nil then --pcall(function() return obslua.timer_remove(src.timer) end) end src.timer=nil reset_to_default(src) end obslua.obs_frontend_add_event_callback(function(event_id) if event_id == obslua.OBS_FRONTEND_EVENT_SCRIPTING_SHUTDOWN then for _, filter in pairs(obs.utils.filters) do if filter and filter.src and filter.src.timer then obslua.timer_remove(filter.src.timer) filter.src.timer=nil end end end end) end function reset_to_default(src) if src == nil then return false end if src.item ~=nil and src.item.data ~= nil then if src.defRot ~= nil then obslua.obs_sceneitem_set_rot(src.item.data, src.defRot) end if src.defPos ~= nil then obslua.obs_sceneitem_set_pos(src.item.data, src.defPos) end if src.defAction == APP.HIDE then obslua.obs_sceneitem_set_visible(src.item.data, false) elseif src.defAction == APP.SHOW then obslua.obs_sceneitem_set_visible(src.item.data, true) end return true end return false end function animate(src, speed) return { move_while= function(cb) if type(cb) ~= "function"then return false end local __calback_back__=nil src.timer= function() if not src or src.timer == nil then return end if cb(src) then obslua.timer_remove(src.timer) if __calback_back__ and type(__calback_back__) == "function" then __calback_back__(src) end return true end end obslua.timer_add(src.timer, speed) return { after=function(cc) __calback_back__=cc end } end,pulsing = function() if src.timer~= nil then -- add the animation to the queue return end local scale = obslua.vec2() obslua.obs_sceneitem_get_scale(src.item.data, scale) local __calback_back__ = nil local debounce = 10 local gp = -1 src.timer= function() if src.timer== nil then return end if debounce <= 0 then obslua.timer_remove(src.timer) if type(__calback_back__) == "function" then __calback_back__() end src.is_loading = false src.timer= nil return else if gp == -1 then scale.x = scale.x - 0.1 scale.y = scale.y - 0.1 gp = 1;debounce=debounce-1 else scale.x = scale.x + 0.1 scale.y = scale.y + 0.1 gp = -1;debounce=debounce-1 end local currScale = obslua.vec2() obslua.obs_sceneitem_get_scale(src.item.data, currScale) local currPos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, currPos) local scale_down = obslua.vec2() scale_down.x = currScale.x - scale.x scale_down.y = currScale.y - scale.y obslua.obs_sceneitem_set_scale(src.item.data, scale); if src.defPos ~= nil then local newPos = obslua.vec2() local w = obslua.obs_source_get_base_width(obslua.obs_sceneitem_get_source(src.item.data)) local h = obslua.obs_source_get_base_height(obslua.obs_sceneitem_get_source(src.item.data)) newPos.x = currPos.x + (scale_down.x * w / 2) newPos.y = currPos.y + (scale_down.y * h / 2) obslua.obs_sceneitem_set_pos(src.item.data, newPos) end end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end;bounce = function() if src.timer~= nil then -- add the animation to the queue return end local bounce_limit = 20 local debounce = 3 local __calback_back__ = nil local currPos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, currPos) local old_pos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, old_pos) local gp = -1 src.timer= function() if src.timer== nil then return end if debounce <= 0 then obslua.timer_remove(src.timer) if type(__calback_back__) == "function" then __calback_back__() end src.is_loading = false src.timer= nil obslua.obs_sceneitem_set_pos(src.item.data, old_pos) return end if gp == -1 then currPos.y = currPos.y - 1 else currPos.y = currPos.y + 1 end if bounce_limit <= 10 then gp = 1 else gp = -1 end if bounce_limit <= 0 then debounce = debounce - 1 bounce_limit = 20 gp = -1 end obslua.obs_sceneitem_set_pos(src.item.data, currPos) bounce_limit = bounce_limit - 1 end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end;flicker = function() if src.timer~= nil then -- add the animation to the queue return end local flicker_limit = 5 local __calback_back__ = nil src.timer= function() if src.timer== nil then return end if flicker_limit <= 0 then obslua.timer_remove(src.timer) if type(__calback_back__) == "function" then __calback_back__() end src.is_loading = false src.timer= nil return end local hidden = obslua.obs_sceneitem_visible(src.item.data) if hidden then hidden = false else hidden = true end obslua.obs_sceneitem_set_visible(src.item.data, hidden) flicker_limit = flicker_limit - 1 end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end;left_to_right = function(limit) if src.timer~= nil then -- add the animation to the queue return end local pos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, pos) local __calback_back__ = nil src.timer= function() if src.timer== nil then return end if pos.x >= limit then obslua.timer_remove(src.timer) if type(__calback_back__) == "function" then __calback_back__() end src.is_loading = false src.timer= nil return else pos.x = pos.x + src.steps if pos.x > limit then pos.x = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end;right_to_left = function(limit) if src.timer~= nil then -- add the animation to the queue return end local pos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, pos) local __calback_back__ = nil src.timer= function() if src.timer== nil then return end if pos.x <= limit then obslua.timer_remove(src.timer) src.is_loading = false if type(__calback_back__) == "function" then __calback_back__() end src.timer= nil return else pos.x = pos.x - src.steps if pos.x < limit then pos.x = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end; top_to_bottom = function(limit) if src.timer~= nil then -- add the animation to the queue return end local __calback_back__ = nil local pos = obslua.vec2() obslua.obs_sceneitem_get_pos(src.item.data, pos) src.timer= function() if src.timer== nil then return end if pos.y >= limit then obslua.timer_remove(src.timer) src.is_loading = false if type(__calback_back__) == "function" then __calback_back__() end src.timer= nil return else pos.y = pos.y + src.steps if pos.y > limit then pos.y = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback return true end;returnValue = true } end; bottom_to_top = function(limit) if src.timer~= nil then -- add the animation to the queue return end local pos = obslua.vec2() local __calback_back__ = nil obslua.obs_sceneitem_get_pos(src.item.data, pos) src.timer= function() if src.timer== nil then return end if pos.y <= limit then obslua.timer_remove(src.timer) src.is_loading = false if type(__calback_back__) == "function" then __calback_back__() end src.timer= nil return else pos.y = pos.y - src.steps if pos.y < limit then pos.y = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after= function(callback) __calback_back__ = callback return true end;returnValue = true } end; to_left = function(limit) if src.timer~= nil then -- add the animation to the queue return end local pos = obslua.vec2() local __calback_back__ = nil obslua.obs_sceneitem_get_pos(src.item.data, pos) src.timer= function() if src.timer== nil then return end if pos.x <= limit then obslua.timer_remove(src.timer) src.is_loading = false if type(__calback_back__) == "function" then __calback_back__() end src.timer= nil return else pos.x = pos.x - src.steps if pos.x < limit then pos.x = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end; to_right = function(limit) if src.timer~= nil then -- add the animation to the queue return end local pos = obslua.vec2() local __calback_back__ = nil obslua.obs_sceneitem_get_pos(src.item.data, pos) src.timer= function() if src.timer== nil then return end if pos.x >= limit then obslua.timer_remove(src.timer) src.is_loading = false if type(__calback_back__) == "function" then __calback_back__() end src.timer= nil return else pos.x = pos.x + src.steps if pos.x > limit then pos.x = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end; to_top = function(limit) if src.timer~= nil then -- add the animation to the queue return end local pos = obslua.vec2() local __calback_back__ = nil obslua.obs_sceneitem_get_pos(src.item.data, pos) src.timer= function() if src.timer== nil then return end if pos.y <= limit then obslua.timer_remove(src.timer) src.is_loading = false if type(__calback_back__) == "function" then __calback_back__() end src.timer= nil return else pos.y = pos.y - src.steps if pos.y < limit then pos.y = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end; to_bottom = function(limit) if src.timer~= nil then -- add the animation to the queue return end local pos = obslua.vec2() local __calback_back__ = nil obslua.obs_sceneitem_get_pos(src.item.data, pos) src.timer= function() if src.timer== nil then return end if pos.y >= limit then obslua.timer_remove(src.timer) src.is_loading = false if type(__calback_back__) == "function" then __calback_back__() end src.timer= nil return else pos.y = pos.y + src.steps if pos.y > limit then pos.y = limit end obslua.obs_sceneitem_set_pos(src.item.data, pos) end end obslua.timer_add(src.timer, speed) return { after = function(callback) __calback_back__ = callback end;returnValue = true } end } end function IndexPage() return [[
Select a source and add a filter called 'Hide2Show'.
The time to hide a source in seconds.
The time to show a source in seconds.
When enabled, it will randomize the time it takes to hide/show
You can animate hide/show, by default it is disabled.]] end function script_properties() local p = obs.script.create() obs.script.label(p,"label", IndexPage()) return p; end -- function script_unload() -- for _, filter in pairs(obs.utils.filters) do -- if filter and filter.src and filter.src.timer then -- obslua.timer_remove(filter.src.timer) -- filter.src.timer=nil -- end -- end -- end -- [[ END OF Hide2Show BLOCK ]] --[[ Author: iixisii contact: @iixisii ]] -- [[ OBS CUSTOM API BEGIN ]] function script_load(settings) settings= obs.PairStack(settings) obs.utils.settings= settings if setup and type(setup) == "function" then setup(settings) end for _, filter in pairs(obs.utils.filters) do obslua.obs_register_source(filter) end end obs={utils={ OBS_SCENEITEM_TYPE = 1;OBS_SRC_TYPE = 2;OBS_OBJ_TYPE = 3; OBS_ARR_TYPE = 4;OBS_SCENE_TYPE = 5;OBS_SCENEITEM_LIST_TYPE = 6; OBS_SRC_LIST_TYPE = 7;OBS_UN_IN_TYPE = -1;table={}; expect_wrapper={}, properties={ list={};options={}; };filters={}};scene={};client={};mem={};script={},enum={ path={ read=obslua.OBS_PATH_FILE;write=obslua.OBS_PATH_FILE_SAVE;folder=obslua.OBS_PATH_DIRECTORY }; button={ default=obslua.OBS_BUTTON_DEFAULT;url=obslua.OBS_BUTTON_URL; };list={ string=obslua.OBS_EDITABLE_LIST_TYPE_STRINGS; url=obslua.OBS_EDITABLE_LIST_TYPE_FILES_AND_URLS; file=obslua.OBS_EDITABLE_LIST_TYPE_FILES }; text={ error=obslua.OBS_TEXT_INFO_ERROR; default=obslua.OBS_TEXT_INFO; warn=obslua.OBS_TEXT_INFO_WARNING; input=obslua.OBS_TEXT_DEFAULT;password=obslua.OBS_TEXT_PASSWORD; textarea=obslua.OBS_TEXT_MULTILINE; };group={ normal= obslua.OBS_GROUP_NORMAL;checked= obslua.OBS_GROUP_CHECKABLE; };options={ string=obslua.OBS_COMBO_FORMAT_STRING; int=obslua.OBS_COMBO_FORMAT_INT; float=obslua.OBS_COMBO_FORMAT_FLOAT;bool=obslua.OBS_COMBO_FORMAT_BOOL; edit=obslua.OBS_COMBO_TYPE_EDITABLE;default=obslua.OBS_COMBO_TYPE_LIST; radio=obslua.OBS_COMBO_TYPE_RADIO; };number={ int=obslua.OBS_COMBO_FORMAT_INT;float=obslua.OBS_COMBO_FORMAT_FLOAT; slider=1000;input=2000 } }}; bit= require('bit') -- dkjson= require('dkjson') math.randomseed(os.time()) -- schedule an event scheduled_events = {} function obs.utils.scheduler(timeout) -- if type(timeout) ~= "number" or timeout < 0 then -- return obs.script_log(obslua.LOG_ERROR, "[Scheduler] invalid timeout value") -- end local scheduler_callback = nil local function interval() obslua.timer_remove(interval) if type(scheduler_callback) ~= "function" then return end return scheduler_callback(scheduler_callback) end local self = nil; self = { after = function(callback) if type(callback) == "function" or type(timeout) ~= "number" or timeout < 0 then scheduler_callback = callback else obslua.script_log(obslua.LOG_ERROR, "[Scheduler] invalid callback/timeout " .. type(callback)) return false end obslua.timer_add(interval, timeout) end;push = function(callback) if callback == nil or type(callback) ~= "function" then obslua.script_log(obslua.LOG_WARNING, "[Scheduler] invalid callback at {push} " .. type(callback)) return false end obslua.timer_add(callback, timeout) table.insert(scheduled_events, callback) return { clear = function() if callback == nil or type(callback) ~= "function" then return nil end return obslua.timer_remove(callback) end; } end; clear = function() if scheduler_callback ~= nil then obslua.timer_remove(scheduler_callback) end for _, clb in pairs(scheduled_events) do obslua.timer_remove(clb) end scheduled_events = {}; scheduler_callback = nil end;update=function(timeout_t) if type(timeout_t) ~= "number" or timeout_t < 0 then obslua.script_log(obslua.LOG_ERROR, "[Scheduler] invalid timeout value") return false end timeout= timeout_t return self end } return self end function obs.wrap(object, object_type) local self = nil self = { type = object_type, data = object;item=object; get_source=function() if self.type == obs.utils.OBS_SRC_TYPE then return self.data elseif self.type == obs.utils.OBS_SCENEITEM_TYPE then return obslua.obs_sceneitem_get_source(self.data) else return self.data end end; free = function() if self.type == obs.utils.OBS_SCENE_TYPE then obslua.obs_scene_release(self.data) elseif self.type == obs.utils.OBS_SRC_TYPE then obslua.obs_source_release(self.data) elseif self.type == obs.utils.OBS_ARR_TYPE then obslua.obs_data_array_release(self.data) elseif self.type == obs.utils.OBS_OBJ_TYPE then obslua.obs_data_release(self.data) elseif self.type == obs.utils.OBS_SCENEITEM_TYPE then obslua.obs_sceneitem_release(self.data) elseif self.type == obs.utils.OBS_SCENEITEM_LIST_TYPE then obslua.sceneitem_list_release(self.data) elseif self.type == obs.utils.OBS_SRC_LIST_TYPE then obslua.source_list_release(self.data) elseif self.type == obs.utils.OBS_UN_IN_TYPE then self.data = nil;self.item=nil return else self.data = nil end end } table.insert(obs.utils.expect_wrapper, self) return self end function obs.expect(callback) return function(...) local args = {...} local data = nil local caller = "" for i, v in ipairs(args) do if caller ~= "" then caller = caller .. "," end caller = caller .. "args[" .. tostring(i) .. "]" end caller = "return function(callback,args) return callback(" .. caller .. ") end"; local run = loadstring(caller) local success, result = pcall(function() data = run()(callback, args) end) local free_count=0 if not success then for _, iter in pairs(obs.utils.expect_wrapper) do if iter and type(iter.free) == "function" then local s, r = pcall(function() iter.free() end) if s then free_count = free_count + 1 end end end obslua.script_log(obslua.LOG_ERROR, "[ErrorWrapper ERROR] => " .. tostring(result)) end return data end end -- array handle function obs.ArrayStack(stack, name, fallback) if fallback == nil then fallback=true end local self = nil self = { index = 0;get = function(index) if type(index) ~= "number" or index < 0 or index > self.size() then return nil end return obs.PairStack(obslua.obs_data_array_item(self.data, index), nil, true) end;next = obs.expect(function(__index) if type(self.index) ~= "number" or self.index < 0 or self.index > self.size() then return assert(false,"[ArrayStack] Invalid data provided or corrupted data for (" .. tostring(name)..")") end return coroutine.wrap(function() if self.size() <= 0 then return nil end local i =0 if __index == nil or type(__index) ~= "number" or __index < 0 or __index > self.size() then __index=0 end for i=__index, self.size()-1 do coroutine.yield(obs.PairStack( obslua.obs_data_array_item(self.data, i), nil, false )) end end) -- local temp = self.index;self.index = self.index + 1 -- return obs.PairStack(obslua.obs_data_array_item(self.data, temp), nil, true) end);find= function(key, value) local index=0 for itm in self.next() do if itm.get_str(key) == value or itm.get_int(key) == value or itm.get_bul(key) == value or itm.get_dbl(key) == value then return itm, index end index = index + 1 itm.free() end return nil, nil end; free = function() if self.data == nil then return false end obslua.obs_data_array_release(self.data) self.data = nil return true end;insert = obs.expect(function(value) if value == nil or type(value) ~= "userdata" then obslua.script_log("FAILED TO INSERT OBJECT INTO [ArrayStack]") return false end obslua.obs_data_array_push_back(self.data, value) return self end); size = obs.expect(function() if self.data == nil then return 0 end return obslua.obs_data_array_count(self.data); end); rm= obs.expect(function(idx) if idx < 0 or self.size() <=0 or idx > self.size() then obslua.script_log("FAILED TO RM DATA FROM [ArrayStack] (INVALID INDEX)") return false end obslua.obs_data_array_erase(self.data, idx) return self end) } if stack and name then self.data = obslua.obs_data_get_array(stack, name) elseif not stack and fallback then self.data = obslua.obs_data_array_create() else self.data = stack end table.insert(obs.utils.expect_wrapper, self) return self end -- pair stack used to manage memory stuff :) function obs.PairStack(stack, name, fallback) if fallback == nil then fallback=true end local self = nil; self = { free = function() if self.data == nil then return false end obslua.obs_data_release(self.data) self.data = nil return true end; str = obs.expect(function(name, value, def) if name and value == nil then return self.get_str(name) end if (name == nil or type(name) ~= "string" or name == "") or (self.data == nil or type(self.data) ~= "userdata") or (value == nil or type(value) ~="string") then obslua.script_log(obslua.LOG_ERROR,"FAILED TO INSERT STR INTO [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return false end if def then obslua.obs_data_set_default_string(self.data, name, value) else obslua.obs_data_set_string(self.data, name, value) end return self end);int = obs.expect(function(name, value, def) if name and value == nil then return self.get_int(name) end if (name == nil or type(name) ~= "string" or name == "") or (self.data == nil or type(self.data) ~= "userdata") or (value == nil or type(value) ~="number") then obslua.script_log(obslua.LOG_ERROR,"FAILED TO INSERT INT INTO [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return false end if def then obslua.obs_data_set_default_int(self.data, name, value) else obslua.obs_data_set_int(self.data, name, value) end return self end);dbl=obs.expect(function(name, value, def) if name and value == nil then return self.get_dbl(name) end if (name == nil or type(name) ~= "string" or name == "") or (self.data == nil or type(self.data) ~= "userdata") or (value == nil or type(value) ~="number") then obslua.script_log(obslua.LOG_ERROR,"FAILED TO INSERT INT INTO [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if def then obslua.obs_data_set_default_double(self.data, name, value) else obslua.obs_data_set_double(self.data, name, value) end return self end);bul = obs.expect(function(name, value, def) if name and value == nil then return self.get_bul(name) end if (name == nil or type(name) ~= "string" or name == "") or (self.data == nil or type(self.data) ~= "userdata") or (type(value) == "nil" or type(value) ~="boolean") then obslua.script_log(obslua.LOG_ERROR,"FAILED TO INSERT BUL [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if def then obslua.obs_data_set_default_bool(self.data, name, value) else obslua.obs_data_set_bool(self.data, name, value) end return self end); arr = obs.expect(function(name, value, def) if name and value == nil then return self.get_arr(name) end if (name == nil or type(name) ~= "string" or name == "") or (self.data == nil or type(self.data) ~= "userdata") or (type(value) ~="userdata") then obslua.script_log(obslua.LOG_ERROR,"FAILED TO INSERT ARR INTO [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if def then obslua.obs_data_set_default_array(self.data, name, value) else obslua.obs_data_set_array(self.data, name, value) end return self end); obj = obs.expect(function(name, value, def) if name and value == nil then return self.get_obj(name) end if (name == nil or type(name) ~= "string" or name == "") or (type(self.data) ~= "userdata") or (type(value) ~="userdata") then obslua.script_log(obslua.LOG_ERROR,"FAILED TO INSERT OBJ INTO [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if def then obslua.obs_data_set_default_obj(self.data, name, value) else obslua.obs_data_set_obj(self.data, name, value) end return self end); -- getter get_str = obs.expect(function(name, def) if (name == nil or type(name) ~= "string" or name == "") or (type(self.data) ~= "userdata")then obslua.script_log(obslua.LOG_ERROR,"FAILED TO GET STR FROM [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if not def then return obslua.obs_data_get_string(self.data, name) else return obslua.obs_data_get_default_string(self.data, name) end end);get_int = obs.expect(function(name, def) if (name == nil or type(name) ~= "string" or name == "") or (type(self.data) ~= "userdata")then obslua.script_log(obslua.LOG_ERROR,"FAILED TO GET INT FROM [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if not def then return obslua.obs_data_get_int(self.data, name) else return obslua.obs_data_get_default_int(self.data, name) end end);get_dbl = obs.expect(function(name, def) if (name == nil or type(name) ~= "string" or name == "") or (type(self.data) ~= "userdata")then obslua.script_log(obslua.LOG_ERROR,"FAILED TO GET DBL FROM [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if not def then return obslua.obs_data_get_double(self.data, name) else return obslua.obs_data_get_default_double(self.data, name) end end);get_obj = obs.expect(function(name, def) if (name == nil or type(name) ~= "string" or name == "") or (type(self.data) ~= "userdata")then obslua.script_log(obslua.LOG_ERROR,"FAILED TO GET OBJ FROM [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if not def then return obs.PairStack( obslua.obs_data_get_obj(self.data, name),nil, false ) else return obs.PairStack( obslua.obs_data_get_default_obj(self.data, name),nil, false ) end end);get_arr = obs.expect(function(name, def) if (name == nil or type(name) ~= "string" or name == "") or (type(self.data) ~= "userdata")then obslua.script_log(obslua.LOG_ERROR,"FAILED TO GET ARR FROM [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if not def then return obs.ArrayStack( obslua.obs_data_get_array(self.data, name),nil, false ) else return obs.ArrayStack(obslua.obs_data_get_default_array(self.data, name),nil, false) end end);get_bul = obs.expect(function(name, def) if (name == nil or type(name) ~= "string" or name == "") or (type(self.data) ~= "userdata") then obslua.script_log(obslua.LOG_ERROR,"FAILED TO GET BUL FROM [PairStack] " .. "FOR [" .. tostring(name) .. "] " .. " OF VALUE [" .. tostring(value) .. "] TYPE: " .. tostring(type(value))) return nil end if not def then return obslua.obs_data_get_bool(self.data, name) else return obslua.obs_data_get_default_bool(self.data, name) end end); del= obs.expect(function(name) obslua.obs_data_erase(self.data, name) return true end); } if stack and name then self.data = obslua.obs_data_get_obj(stack, name) elseif not stack and fallback then self.data = obslua.obs_data_create() else self.data = stack end table.insert(obs.utils.expect_wrapper, self) return self end -- [[ OBS FILTER CUSTOM API]] function obs.script.filter(filter) local self;self={ id= filter and filter.id or obs.utils.get_unique_id(3), type= filter and filter.type or obslua.OBS_SOURCE_TYPE_FILTER, output_flags= filter and filter.output_flags or bit.bor( obslua.OBS_SOURCE_VIDEO ), get_height=function(src) return src and src.height or 0 end, get_width= function(src) return src and src.width or 0 end,update= function(_, settings) if filter and type(filter) == "table" and filter["update"] and type(filter["update"]) == "function" then return filter.update(_, obs.PairStack(settings)) end end, create= function(settings, source) if filter and type(filter) == "table" and filter["create"] and type(filter["create"]) == "function" then local src=filter.create( obs.PairStack(settings), obs.wrap(source, obs.utils.OBS_SRC_TYPE) ) self.src=src;src.filter=source src.is_custom=true function src.sceneitem() local a_source=obslua.obs_filter_get_target(src.filter) while true do local temp= obslua.obs_filter_get_target(a_source) if temp == nil then break end a_source= temp end if not a_source then return nil end local source_name= obslua.obs_source_get_name(a_source) local a_scene= obs.scene:get_scene() local a_scene_item= a_scene.get(source_name) a_scene.free() return a_scene_item end if filter and filter["setup"] and type(filter["setup"]) == "function" then filter.setup(src) end return src end -- default creation shader = [[ uniform float4x4 ViewProj; uniform texture2d image; uniform int width; uniform int height; sampler_state textureSampler { Filter = Linear; AddressU = Border; AddressV = Border; BorderColor = 00000000; }; struct VertData { float4 pos : POSITION; float2 uv : TEXCOORD0; }; float4 ps_get(VertData v_in) : TARGET { return image.Sample(textureSampler, v_in.uv.xy); } VertData VSDefault(VertData v_in) { VertData vert_out; vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); vert_out.uv = v_in.uv; return vert_out; } technique Draw { pass { vertex_shader = VSDefault(v_in); pixel_shader = ps_get(v_in); } } ]] obslua.obs_enter_graphics() local src= { source= source,filter=source, shader= obslua.gs_effect_create(shader, nil, nil), params=nil;height=nil;width=nil;settings=obs.PairStack(settings) } function src.sceneitem() local a_source=obslua.obs_filter_get_target(src.filter) while true do local temp= obslua.obs_filter_get_target(a_source) if temp == nil then break end a_source= temp end if not a_source then return nil end local source_name= obslua.obs_source_get_name(a_source) local a_scene= obs.scene:get_scene() local a_scene_item= a_scene.get(source_name) a_scene.free() return a_scene_item end -- get width and height of source if source ~= nil then local target= obslua.obs_filter_get_target(source) if target ~= nil then local scene= obs.scene:get_scene() src.item= src.sceneitem() scene.free() src.width= obslua.obs_source_get_base_width(target) src.height= obslua.obs_source_get_base_height(target) end else src.width= 0;src.height= 0 end -- obslua.obs_leave_graphics() if src.shader ~= nil then src.params= { width= obslua.gs_effect_get_param_by_name(src.shader, "width"), height= obslua.gs_effect_get_param_by_name(src.shader, "height"), image= obslua.gs_effect_get_param_by_name(src.shader, "image"), } else return self.destroy() end if filter and filter["setup"] and type(filter["setup"]) == "function" then filter.setup(src) end self.src=src return src end, destroy= function(src) if filter and type(filter) == "table" and filter["destroy"] and type(filter["destroy"]) == "function" then local result= filter.destroy(src) if src and src.is_custom then return result end end -- default destruction if src and src.item and src.item.data then src.item.free() end if src.shader then obslua.obs_enter_graphics() obslua.gs_effect_destroy(src.shader) obslua.obs_leave_graphics() end end,video_tick=function(src, fps) -- get width and height of source if src.item and src.item.data then local mt= obslua.matrix4() obslua.obs_sceneitem_get_box_transform(src.item.data, mt) src.width= mt.x.x src.height= mt.y.y else src.width= 0;src.height= 0 end -- call user-defined video_tick function if filter and type(filter) == "table" and filter["video_tick"] and type(filter["video_tick"]) == "function" then filter.video_tick(src, fps) end end, video_render= function(src) if filter and type(filter) == "table" and filter["video_render"] and type(filter["video_render"]) == "function" then local result = filter.video_render(src) if src.is_custom then return result end end -- default render if not src or not src.source or not src.shader or not src.params then return end if not src.item or not src.item.data then local target= obslua.obs_filter_get_target(src.source) if target ~= nil then local scene= obs.scene:get_scene() src.item= src.sceneitem() scene.free() src.width= obslua.obs_source_get_base_width(target) src.height= obslua.obs_source_get_base_height(target) end end local width= src.width;local height= src.height if not obslua.obs_source_process_filter_begin( src.source,obslua.GS_RGBA, obslua.OBS_NO_DIRECT_RENDERING ) then obslua.obs_source_skip_video_filter(src.source) return nil end if not src.params then obslua.obs_source_process_filter_end(src.source, src.shader, width, height) return nil end if type(width) == "number" then obslua.gs_effect_set_int(src.params.width, width) end if type(height) == "number" then obslua.gs_effect_set_int(src.params.height, height) end obslua.gs_blend_state_push() obslua.gs_blend_function( obslua.GS_BLEND_ONE, obslua.GS_BLEND_INVSRCALPHA ) if width and height then obslua.obs_source_process_filter_end(src.source, src.shader, width, height) end obslua.gs_blend_state_pop() return true end, get_name=function() return filter and filter.name or "Custom Filter" end,get_defaults=function(settings) local defaults=nil if filter and type(filter) == "table" and filter["get_defaults"] and type(filter["get_defaults"]) == "function" then defaults = filter.get_defaults end if filter and type(filter) == "table" and filter["defaults"] and type(filter["defaults"]) == "function" then defaults = filter.defaults end if defaults and type(defaults) == "function" then return defaults(obs.PairStack(settings)) end end,get_properties=function(src) local properties= nil if filter and type(filter) == "table" and filter["get_properties"] and type(filter["get_properties"]) == "function" then properties = filter.get_properties end if filter and type(filter) == "table" and filter["properties"] and type(filter["properties"]) == "function" then properties = filter.properties end if properties and type(properties) == "function" then return properties(src) end return nil end } table.insert(obs.utils.filters, self) if not filter or not type(filter) == "table" then filter={} end filter.get_name= self.get_name if not filter.id then filter.id= self.id end filter.get_width= self.get_width filter.get_height= self.get_height filter.type= self.type filter.output_flags= self.output_flags --filter.destroy= self.destroy return filter end --[[ OBS API CUSTOM ]] function obs.scene:get_source(source_name) if not source_name or not type(source_name) == "string" then return nil end local source = obslua.obs_get_source_by_name(source_name) if not source then return nil end return obs.wrap(source, obs.utils.OBS_SRC_TYPE) end function obs.scene:get_scene(scene_name) local scene;local source_scene; if not scene_name or not type(scene_name) == "string" then source_scene=obslua.obs_frontend_get_current_scene() if not source_scene then return nil end scene= obslua.obs_scene_from_source(source_scene) else source_scene= obslua.obs_get_source_by_name(scene_name) if not source_scene then return nil end scene=obslua.obs_scene_from_source(source_scene) end local obj_scene_t;obj_scene_t= { group_names=function() local scene_items_list = obs.wrap( obslua.obs_scene_enum_items(scene), obs.utils.OBS_SCENEITEM_LIST_TYPE ) if scene_items_list == nil or scene_items_list.data == nil then return nil end local list={} for _, item in ipairs(scene_items_list.data) do local source = obslua.obs_sceneitem_get_source(item) if source ~= nil then local sourceName = obslua.obs_source_get_name(source) if obslua.obs_sceneitem_is_group(item) then table.insert(list, sourceName) end end end scene_items_list.free() return list end;source_names=function(source_id_type) local scene_nodes_name_list= {} local scene_items_list = obs.wrap( obslua.obs_scene_enum_items(scene), obs.utils.OBS_SCENEITEM_LIST_TYPE ) for _, item in ipairs(scene_items_list.data) do local source = obslua.obs_sceneitem_get_source(item) if source ~= nil then local sourceName = obslua.obs_source_get_name(source) if source_id_type == nil or type(source_id_type) ~= "string" or source_id_type == "" then table.insert(scene_nodes_name_list, sourceName) else local sourceId = obslua.obs_source_get_id(source) if sourceId == source_id_type then table.insert(scene_nodes_name_list, sourceName) end end source= nil end end scene_items_list.free() return scene_nodes_name_list end;get= function(source_name) if not scene then return nil end local c=1 local scene_item;local scene_items_list = obs.wrap( obslua.obs_scene_enum_items(scene), obs.utils.OBS_SCENEITEM_LIST_TYPE ) if scene_items_list == nil or scene_items_list.data == nil then return nil end for _, item in ipairs(scene_items_list.data) do c = c + 1 local src= obslua.obs_sceneitem_get_source(item) local src_name= obslua.obs_source_get_name(src) if src ~= nil and src_name == source_name then obslua.obs_sceneitem_addref(item) scene_item= obs.wrap(item, obs.utils.OBS_SCENEITEM_TYPE) break end end scene_items_list.free() if scene_item == nil or scene_item.data == nil then return nil end local obj_source_t; obj_source_t={ free=scene_item.free; item=scene_item.data; data=scene_item.data; get_source=function() return obslua.obs_sceneitem_get_source(scene_item.data) end } return obj_source_t end;add=function(source) if not source then return false end local sceneitem= obslua.obs_scene_add(scene, source) if sceneitem == nil then return nil end obslua.obs_sceneitem_addref(sceneitem) return obs.wrap(sceneitem, obs.utils.OBS_SCENEITEM_TYPE) end;get_label=function(name, source) if (source == nil or source.data == nil) and name ~= nil and type(name) == "string" and name ~= "" then source= obj_scene_t.get(name) end if not source or not source.data then return nil end local obj_label_t;obj_label_t={ remove= function() if obj_label_t.data == nil then return true end obslua.obs_sceneitem_remove(obj_label_t.data) source.free(); obj_label_t.data=nil;obj_label_t.item=nil return true end; hide= function() return obslua.obs_sceneitem_set_visible(obj_label_t.data, false) end;show = function() return obslua.obs_sceneitem_set_visible(obj_label_t.data, true) end; font= { size= function(font_size) local src= obs.PairStack( obslua.obs_source_get_settings(source.get_source()), nil,true ) if not src or not src.data then src= obs.PairStack() end local font= src.get_obj("font") if not font or not font.data then font= obs.PairStack() --font.str("face","Arial") end if font_size == nil or not type(font_size) == "number" or font_size <= 0 then font_size=font.get_int("size") font.free();src.free(); return font_size else font.int("size", font_size) end font.free(); obslua.obs_source_update(source.get_source(), src.data) src.free() return true end;face= function(face_name) end };text=function(txt) local src= obs.PairStack( obslua.obs_source_get_settings(source.get_source()), nil,true ) if not src or not src.data then src= obs.PairStack() end local res=true if txt == nil or txt == "" or type(txt) ~= "string" then res=src.get_str("text") if not res == nil then res= "" end else src.str("text", txt) end obslua.obs_source_update(source.get_source(), src.data) src.free() return res end;free=function() source.free() obj_label_t=nil return true end;data=source.data;item=source.data;size={ width= function(w) --local default_transform= obslua.obs_transform_info() --local default_source_info=obslua.obs_source_info() --obslua.obs_source_get_info(source.get_source(), default_source_info) --obslua.obs_sceneitem_get_info(source.data, default_transform) local default_width= obslua.obs_source_get_width(source.get_source()) --local default_scale_x= default_transform.scale.x; if w == nil then return default_width end return w end; height= function(h) local default_height= obslua.obs_source_get_height(source.get_source()) if h == nil then return default_height end return h end; };pos = { x=function(val) local default_transform= obslua.obs_transform_info() obslua.obs_sceneitem_get_info2(source.data, default_transform) if val == nil then return default_transform.pos.x end default_transform.pos.x= val obslua.obs_sceneitem_set_info(source.data, default_transform) return true end; y=function(val) local default_transform= obslua.obs_transform_info() obslua.obs_sceneitem_get_info2(source.data, default_transform) if val == nil then return default_transform.pos.y end default_transform.pos.y= val obslua.obs_sceneitem_set_info(source.data, default_transform) return true end; } } return obj_label_t end; add_label= function(name, text) local src= obs.PairStack() if not text then text= "Text - Label" end src.str("text", text) local source_label=obslua.obs_source_create("text_gdiplus", name, src.data, nil) src.free() local obj= obj_scene_t.get_label( nil, obj_scene_t.add(source_label) ) if not obj or not obj.data then if source_label then obslua.obs_source_release(source_label) end return nil end -- re-write the release function -- [[SEEM LIKE THIS LEADS TO CRUSHES?]] local free_func= obj.free; obj.free= function() obslua.obs_source_release(source_label) return free_func() end return obj end;add_group= function(name, refresh) if refresh == nil then refresh=true end local obj=obj_scene_t.get_group(nil, obslua.obs_scene_add_group2(scene, name, refresh)) if not obj or obj.data == nil then return nil end -- overwrite the free function to prevent crush/bugs obj.free=function() end return obj end;get_group= function(name, gp) local obj;if not gp and name ~= nil then obj= obs.wrap(obslua.obs_scene_get_group(scene, name), obs.utils.OBS_SCENEITEM_TYPE) elseif gp ~= nil then obj= obs.wrap(gp, obs.utils.OBS_SCENEITEM_TYPE) else return nil end obj["add"]= function(sceneitem) if not sceneitem then return false end obslua.obs_sceneitem_group_add_item(obj.data, sceneitem) return true end obj["release"]= function() return obj.free() end;obj["item"]= obj.data return obj end;free= function() obslua.obs_source_release(source_scene) scene=nil end;release= function() return obj_scene_t.free() end;get_width= function() return obslua.obs_source_get_base_width(source_scene) end;get_height = function() return obslua.obs_source_get_base_height(source_scene) end;data=scene;item=scene; }; return obj_scene_t end function obs.scene:name() source_scene=obslua.obs_frontend_get_current_scene() if not source_scene then return nil end local source_name= obslua.obs_source_get_name(source_scene) obslua.obs_source_release(source_scene) return source_name end function obs.scene:add_to_scene(source) if not source then return false end local current_source_scene= obslua.obs_frontend_get_current_scene() if not current_source_scene then return false end local current_scene= obslua.obs_scene_from_source(current_source_scene) if not current_scene then obslua.obs_source_release(current_source_scene) return false end obslua.obs_scene_add(current_scene, source) obslua.obs_source_release(current_source_scene) return true end function obs.scene:names() local scenes= obs.wrap( obslua.obs_frontend_get_scenes(), obs.utils.OBS_SRC_LIST_TYPE ); local obj_table_t= {} for _, a_scene in pairs(scenes.data) do if a_scene then local scene_source_name= obslua.obs_source_get_name(a_scene) table.insert(obj_table_t, scene_source_name) end end scenes.free() return obj_table_t end -- [[ OBS SCRIPT PROPERTIES CUSTOM API]] function obs.script.create() return obslua.obs_properties_create() end function obs.script.options(p, unique_id, desc, enum_type_id, enum_format_id) if not desc or type(desc) ~= "string" then desc="" end if not unique_id or type(unique_id) ~= "string" or unique_id == "" then unique_id= obs.utils.get_unique_id(20) end if enum_format_id == nil then enum_format_id= obs.enum.options.string; end if enum_type_id == nil then enum_type_id= obs.enum.options.default; end local obj=obslua.obs_properties_add_list(p, unique_id, desc, enum_type_id, enum_format_id); if not obj then obslua.script_log(obslua.LOG_ERROR, "[obsapi_custom.lua] Failed to create list property: " .. tostring(unique_id) .. " description: " .. tostring(desc) .. " enum_type_id: " .. tostring(enum_type_id) .. " enum_format_id: " .. tostring(enum_format_id)) return nil end obs.utils.properties.options[unique_id]= { enum_format_id= enum_format_id; enum_type_id= enum_type_id; } local obj_raw= obs.utils.obs_api_properties_patch(obj, p) obj_raw.type= enum_format_id; obs.utils.properties[unique_id]= obj_raw return obj_raw end function obs.script.button(p, unique_id, label, callback) if not label or type(label) ~= "string" then label="button" end if not unique_id or type(unique_id) ~= "string" or unique_id == "" then unique_id= obs.utils.get_unique_id(20) end if type(callback)~="function" then callback=function() end end obs.utils.properties[unique_id]=obs.utils.obs_api_properties_patch( obslua.obs_properties_add_button(p, unique_id, label, function(properties_t, property_t, obs_data_t) return callback(properties_t, property_t, obs.PairStack(obs_data_t)) end) ,p) return obs.utils.properties[unique_id] end function obs.script.label(p, unique_id, text, enum_type) if not text or type(text) ~= "string" then text="" end if not unique_id or type(unique_id) == nil or unique_id == "" or type(unique_id) ~= "string" then unique_id= obs.utils.get_unique_id(20) end local default_enum_type= obslua.OBS_TEXT_INFO; if(enum_type == nil) then enum_type= default_enum_type end local obj= obs.utils.obs_api_properties_patch(obslua.obs_properties_add_text(p, unique_id, text, default_enum_type), p) if enum_type == obs.enum.text.error then obj.error(text) elseif enum_type == obs.enum.text.warn then obj.warn(text) end obj.type= enum_type; obs.utils.properties[unique_id]= obj return obj; end function obs.script.group(p, unique_id, desc, op, enum_type) if not desc or type(desc) ~= "string" then desc="" end if not unique_id or type(unique_id) ~= "string" or unique_id == "" then unique_id= obs.utils.get_unique_id(20) end if enum_type == nil then enum_type= obs.enum.group.normal; end if enum_type == obs.enum.group.bool and obs.utils.settings.get_bul(unique_id) == nil then obs.utils.settings.bul(unique_id, false) end obs.utils.properties[unique_id]= obs.utils.obs_api_properties_patch(obslua.obs_properties_add_group(p, unique_id, desc, enum_type, op), p) return obs.utils.properties[unique_id] end function obs.script.bool(p, unique_id, desc) if not desc or type(desc) ~= "string" then desc="" end if not unique_id or type(unique_id) ~= "string" or unique_id == "" then unique_id= obs.utils.get_unique_id(20) end -- create a default value -- if obs.utils.settings.get_bul(name) == nil then -- obs.utils.settings.bul(name, false) -- end obs.utils.properties[unique_id]=obs.utils.obs_api_properties_patch(obslua.obs_properties_add_bool(p, unique_id, desc), p) return obs.utils.properties[unique_id] end function obs.script.path(p, unique_id, desc, enum_type_id, filter_string, default_path_string) if not unique_id or type(unique_id) ~= "string" or unique_id == "" then unique_id= obs.utils.get_unique_id(20) end if not desc or type(desc) ~= "string" then desc= "" end if enum_type_id == nil or type(enum_type_id) ~= "number" then enum_type_id= obs.enum.path.read end if filter_string == nil or type(filter_string) ~= "string" then filter_string="" end if default_path_string == nil or type(default_path_string) ~= "string" then default_path_string= "" end obs.utils.properties[unique_id]= obs.utils.obs_api_properties_patch(obslua.obs_properties_add_path(p, unique_id, desc, enum_type_id, filter_string, default_path_string), p) return obs.utils.properties[unique_id] end function obs.script.form(properties, title, unique_id) local pp= obs.script.create();local __exit_click_callback__=nil;local __onexit_type__=1; local __cancel_click_callback__=nil;local __oncancel_type__=1; if unique_id == nil then unique_id=obs.utils.get_unique_id(20) end local group_form= obs.script.group(properties,unique_id, "", pp, obs.enum.group.normal) local label= obs.script.label(pp, unique_id .. "_label", title, obslua.OBS_TEXT_INFO); obs.script.label(pp,"form_tt","