Advertisement
JHobz

ori_tourney_instant_replay.lua

Feb 9th, 2018
435
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.08 KB | None | 0 0
  1. obs = obslua
  2. source_names = {
  3.     left = "",
  4.     left_bg = "",
  5.     right = "",
  6.     right_bg = "",
  7.     both = "",
  8.     both_bg = ""
  9. }
  10. hotkey_ids = {
  11.     obs.OBS_INVALID_HOTKEY_ID,
  12.     obs.OBS_INVALID_HOTKEY_ID,
  13.     obs.OBS_INVALID_HOTKEY_ID
  14. }
  15. hotkey_pressed = ""
  16. attempts = 0
  17. animate_props = {
  18.     vid = {},
  19.     bg = {}
  20. }
  21. play_reverse = false
  22. dir = ""
  23.  
  24. ----------------------------------------------------------
  25.  
  26. function try_play()
  27.     local replay_buffer = obs.obs_frontend_get_replay_buffer_output()
  28.     if replay_buffer == nil then
  29.         obs.remove_current_callback()
  30.         return
  31.     end
  32.  
  33.     -- Call the procedure of the replay buffer named "get_last_replay" to
  34.     -- get the last replay created by the replay buffer
  35.     local cd = obs.calldata_create()
  36.     local ph = obs.obs_output_get_proc_handler(replay_buffer)
  37.     obs.proc_handler_call(ph, "get_last_replay", cd)
  38.     local path = obs.calldata_string(cd, "path")
  39.     obs.calldata_destroy(cd)
  40.  
  41.     obs.obs_output_release(replay_buffer)
  42.  
  43.     -- If the path is valid and the source exists, update it with the
  44.     -- replay file to play back the replay.  Otherwise, stop attempting to
  45.     -- replay after 10 seconds
  46.     if path == nil then
  47.         attempts = attempts + 1
  48.         if attempts >= 10 then
  49.             obs.remove_current_callback()
  50.         end
  51.     elseif hotkey_pressed == "" then
  52.         obs.remove_current_callback()
  53.     else
  54.         local name_v = source_names[hotkey_pressed]
  55.         local source_v = obs.obs_get_source_by_name(name_v)
  56.         local name_i = source_names[hotkey_pressed .. "_bg"]
  57.         local source_i = obs.obs_get_source_by_name(name_i)
  58.         hotkey_pressed = ""
  59.  
  60.         if source_v ~= nil and source_i ~= nil then
  61.             local settings = obs.obs_data_create()
  62.             obs.obs_data_set_string(settings, "local_file", path)
  63.             obs.obs_data_set_bool(settings, "is_local_file", true)
  64.             obs.obs_data_set_bool(settings, "close_when_inactive", true)
  65.             obs.obs_data_set_bool(settings, "restart_on_activate", false)
  66.  
  67.             -- updating will automatically cause the source to
  68.             -- refresh if the source is currently active, otherwise
  69.             -- the source will play whenever its scene is activated
  70.             obs.obs_source_update(source_v, settings)
  71.             transition_setup(name_v, name_i)
  72.  
  73.             obs.obs_data_release(settings)
  74.             obs.obs_source_release(source_v)
  75.             obs.obs_source_release(source_i)
  76.         else
  77.             obs.script_log(obs.LOG_WARNING, "You need to set your sources in the properties window!")
  78.         end
  79.  
  80.         obs.remove_current_callback()
  81.     end
  82. end
  83.  
  84. function transition_setup(name_v, name_i)
  85.     local scene = obs.obs_scene_from_source(obs.obs_frontend_get_current_scene())
  86.     local scene_item_v = obs.obs_scene_find_source(scene, name_v)
  87.     local transform_v = obs.obs_transform_info()
  88.     local scene_item_i = obs.obs_scene_find_source(scene, name_i)
  89.     local transform_i = obs.obs_transform_info()
  90.     obs.obs_sceneitem_get_info(scene_item_v, transform_v)
  91.     obs.obs_sceneitem_get_info(scene_item_i, transform_i)
  92.  
  93.     dir = "up"
  94.     if name_v == source_names.left then
  95.         dir = "right"
  96.     elseif name_v == source_names.right then
  97.         dir = "left"
  98.     end
  99.  
  100.     start_slides(scene_item_v, scene_item_i, transform_v, transform_i)
  101.     obs.timer_add(end_slides, 8000)
  102.     obs.obs_scene_release(scene)
  103.     -- obs.obs_sceneitem_release(scene_item_v)
  104.     -- obs.obs_sceneitem_release(scene_item_i)
  105. end
  106.  
  107. function start_slides(scene_item_v, scene_item_i, transform_v, transform_i)
  108.     local pos_v = transform_v.pos
  109.     local bounds_v = transform_v.bounds
  110.     local pos_i = transform_i.pos
  111.     local bounds_i = transform_i.bounds
  112.     animate_props.vid = {
  113.         item = scene_item_v,
  114.         pos = pos_v,
  115.         bounds = bounds_v
  116.     }
  117.     animate_props.bg = {
  118.         item = scene_item_i,
  119.         pos = pos_i,
  120.         bounds = bounds_i
  121.     }
  122.     play_reverse = false
  123.  
  124.     if dir == "up" then
  125.         pos_v.y = 1080 + bounds_v.y
  126.         pos_i.y = 1080 + bounds_i.y
  127.         obs.timer_add(slide_up, 10)
  128.     elseif dir == "right" then
  129.         pos_v.x = -bounds_v.x
  130.         pos_i.x = -bounds_i.x
  131.         obs.timer_add(slide_right, 10)
  132.     elseif dir == "left" then
  133.         pos_v.x = 1920 + bounds_v.x
  134.         pos_i.x = 1920 + bounds_i.x
  135.         obs.timer_add(slide_left, 10)
  136.     end
  137.     obs.obs_sceneitem_set_pos(scene_item_v, pos_v)
  138.     obs.obs_sceneitem_set_pos(scene_item_i, pos_i)
  139. end
  140.  
  141. function end_slides()
  142.     play_reverse = true
  143.     if dir == "up" then
  144.         obs.timer_add(slide_up, 10)
  145.     elseif dir == "right" then
  146.         obs.timer_add(slide_right, 10)
  147.     elseif dir == "left" then
  148.         obs.timer_add(slide_left, 10)
  149.     end
  150.     obs.remove_current_callback()
  151. end
  152.  
  153. -- Weird rounding bullshit leads to the odd numbers below
  154. function slide_up()
  155.     local remove_callback = false
  156.  
  157.     for _, props in pairs(animate_props) do
  158.         local dist = props.bounds.y
  159.         local tick = dist/20
  160.         if not play_reverse then
  161.             if props.pos.y <= 1081 or remove_callback then
  162.                 props.pos.y = 1080
  163.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  164.                 remove_callback = true
  165.             else
  166.                 props.pos.y = props.pos.y - tick
  167.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  168.             end
  169.         else
  170.             if props.pos.y >= (1079 + props.bounds.y) or remove_callback then
  171.                 props.pos.y = 1080 + props.bounds.y
  172.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  173.                 remove_callback = true
  174.             else
  175.                 props.pos.y = props.pos.y + tick
  176.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  177.             end
  178.         end
  179.     end
  180.  
  181.     if remove_callback then
  182.         obs.remove_current_callback()
  183.     end
  184. end
  185.  
  186. function slide_right()
  187.     local remove_callback = false
  188.  
  189.     for _,props in pairs(animate_props) do
  190.         local dist = props.bounds.x
  191.         local tick = dist/20
  192.         if not play_reverse then
  193.             if props.pos.x >= -1 or remove_callback then
  194.                 props.pos.x = 0
  195.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  196.                 remove_callback = true
  197.             else
  198.                 props.pos.x = props.pos.x + tick
  199.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  200.             end
  201.         else
  202.             if props.pos.x <= -(props.bounds.x - 1) or remove_callback then
  203.                 props.pos.x = -props.bounds.x
  204.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  205.                 remove_callback = true
  206.             else
  207.                 props.pos.x = props.pos.x - tick
  208.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  209.             end
  210.         end
  211.     end
  212.  
  213.     if remove_callback then
  214.         obs.remove_current_callback()
  215.     end
  216. end
  217.  
  218. function slide_left()
  219.     local remove_callback = false
  220.  
  221.     for _, props in pairs(animate_props) do
  222.         local dist = props.bounds.x
  223.         local tick = dist/20
  224.         if not play_reverse then
  225.             if props.pos.x <= 1921 or remove_callback then
  226.                 props.pos.x = 1920
  227.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  228.                 remove_callback = true
  229.             else
  230.                 props.pos.x = props.pos.x - tick
  231.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  232.             end
  233.         else
  234.             if props.pos.x >= 1919 + props.bounds.x or remove_callback then
  235.                 props.pos.x = 1920 + props.bounds.x
  236.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  237.                 remove_callback = true
  238.             else
  239.                 props.pos.x = props.pos.x + tick
  240.                 obs.obs_sceneitem_set_pos(props.item, props.pos)
  241.             end
  242.         end
  243.     end
  244.  
  245.     if remove_callback then
  246.         obs.remove_current_callback()
  247.     end
  248. end
  249.  
  250. -- The "Instant Replay" hotkey callbacks
  251. function instant_replay_left(pressed)
  252.     if not pressed then
  253.         return
  254.     end
  255.  
  256.     instant_replay("left")
  257. end
  258.  
  259. function instant_replay_right(pressed)
  260.     if not pressed then
  261.         return
  262.     end
  263.  
  264.     instant_replay("right")
  265. end
  266.  
  267. function instant_replay_both(pressed)
  268.     if not pressed then
  269.         return
  270.     end
  271.  
  272.     instant_replay("both")
  273. end
  274.  
  275. function instant_replay(pressed)
  276.     hotkey_pressed = pressed
  277.  
  278.     local replay_buffer = obs.obs_frontend_get_replay_buffer_output()
  279.     if replay_buffer ~= nil then
  280.         -- Call the procedure of the replay buffer named "get_last_replay" to
  281.         -- get the last replay created by the replay buffer
  282.         local ph = obs.obs_output_get_proc_handler(replay_buffer)
  283.         obs.proc_handler_call(ph, "save", nil)
  284.  
  285.         -- Set a 1-second timer to attempt playback every 1 second
  286.         -- until the replay is available
  287.         if obs.obs_output_active(replay_buffer) then
  288.             attempts = 0
  289.             obs.timer_add(try_play, 1000)
  290.         else
  291.             obs.script_log(obs.LOG_WARNING, "Tried to save an instant replay, but the replay buffer is not active!")
  292.         end
  293.  
  294.         obs.obs_output_release(replay_buffer)
  295.     else
  296.         obs.script_log(obs.LOG_WARNING, "Tried to save an instant replay, but found no active replay buffer!")
  297.     end
  298. end
  299.  
  300. ----------------------------------------------------------
  301.  
  302. -- A function named script_update will be called when settings are changed
  303. function script_update(settings)
  304.     source_names.left = obs.obs_data_get_string(settings, "v_source_left")
  305.     source_names.right = obs.obs_data_get_string(settings, "v_source_right")
  306.     source_names.both = obs.obs_data_get_string(settings, "v_source_both")
  307.     source_names.left_bg = obs.obs_data_get_string(settings, "i_source_left")
  308.     source_names.right_bg = obs.obs_data_get_string(settings, "i_source_right")
  309.     source_names.both_bg = obs.obs_data_get_string(settings, "i_source_both")
  310. end
  311.  
  312. -- A function named script_description returns the description shown to
  313. -- the user
  314. function script_description()
  315.     return "VVVVHow to use this script:\n\n    Step 1: Load this script (hey, you did that already!)\n    Step 2: Go to File -> Settings -> Hotkeys and add hotkeys for the 3 Instant Replay fields (I recommend F1-F3)\n    Step 3: Whenever you want to make a replay, press the hotkey corresponding to the runner (or runners) you want to showcase\n\nThat's it!\n\n\n-- Made by JHobz. Contact on Discord with questions/bug reports."
  316. end
  317.  
  318. -- A function named script_properties defines the properties that the user
  319. -- can change for the entire script module itself
  320. function script_properties()
  321.     props = obs.obs_properties_create()
  322.  
  323.     -- Find replay sources
  324.     local lvs = obs.obs_properties_add_list(props, "v_source_left", "Left Replay Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
  325.     local rvs = obs.obs_properties_add_list(props, "v_source_right", "Right Replay Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
  326.     local bvs = obs.obs_properties_add_list(props, "v_source_both", "Both Replay Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
  327.     local lis = obs.obs_properties_add_list(props, "i_source_left", "Left Replay Background", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
  328.     local ris = obs.obs_properties_add_list(props, "i_source_right", "Right Replay Background", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
  329.     local bis = obs.obs_properties_add_list(props, "i_source_both", "Both Replay Background", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
  330.  
  331.     local sources = obs.obs_enum_sources()
  332.     if sources ~= nil then
  333.         for _, source in ipairs(sources) do
  334.             source_id = obs.obs_source_get_id(source)
  335.             if source_id == "ffmpeg_source" then
  336.                 local name = obs.obs_source_get_name(source)
  337.                 if string.match(name, "^REPLAY") then
  338.                     obs.obs_property_list_add_string(lvs, name, name)
  339.                     obs.obs_property_list_add_string(rvs, name, name)
  340.                     obs.obs_property_list_add_string(bvs, name, name)
  341.                 end
  342.             elseif source_id == "image_source" then
  343.                 local name = obs.obs_source_get_name(source)
  344.                 if string.match(name, "Replay BG") then
  345.                     obs.obs_property_list_add_string(lis, name, name)
  346.                     obs.obs_property_list_add_string(ris, name, name)
  347.                     obs.obs_property_list_add_string(bis, name, name)
  348.                 end
  349.             end
  350.         end
  351.     end
  352.     obs.source_list_release(sources)
  353.  
  354.     return props
  355. end
  356.  
  357. -- A function named script_load will be called on startup
  358. function script_load(settings)
  359.     -- Register hotkeys
  360.     hotkey_ids[1] = obs.obs_hotkey_register_frontend("instant_replay_left.trigger", "Instant Replay (Left)", instant_replay_left)
  361.     local hotkey_save_array1 = obs.obs_data_get_array(settings, "instant_replay_left.trigger")
  362.     obs.obs_hotkey_load(hotkey_ids[1], hotkey_save_array1)
  363.     obs.obs_data_array_release(hotkey_save_array1)
  364.  
  365.     hotkey_ids[2] = obs.obs_hotkey_register_frontend("instant_replay_right.trigger", "Instant Replay (Right)", instant_replay_right)
  366.     local hotkey_save_array2 = obs.obs_data_get_array(settings, "instant_replay_right.trigger")
  367.     obs.obs_hotkey_load(hotkey_ids[2], hotkey_save_array2)
  368.     obs.obs_data_array_release(hotkey_save_array2)
  369.  
  370.     hotkey_ids[3] = obs.obs_hotkey_register_frontend("instant_replay_both.trigger", "Instant Replay (Both)", instant_replay_both)
  371.     local hotkey_save_array3 = obs.obs_data_get_array(settings, "instant_replay_both.trigger")
  372.     obs.obs_hotkey_load(hotkey_ids[3], hotkey_save_array3)
  373.     obs.obs_data_array_release(hotkey_save_array3)
  374. end
  375.  
  376. -- A function named script_save will be called when the script is saved
  377. --
  378. -- NOTE: This function is usually used for saving extra data (such as in this
  379. -- case, a hotkey's save data).  Settings set via the properties are saved
  380. -- automatically.
  381. function script_save(settings)
  382.     local hotkey_save_array1 = obs.obs_hotkey_save(hotkey_ids[1])
  383.     obs.obs_data_set_array(settings, "instant_replay_left.trigger", hotkey_save_array1)
  384.     obs.obs_data_array_release(hotkey_save_array1)
  385.  
  386.     local hotkey_save_array2 = obs.obs_hotkey_save(hotkey_ids[2])
  387.     obs.obs_data_set_array(settings, "instant_replay_right.trigger", hotkey_save_array2)
  388.     obs.obs_data_array_release(hotkey_save_array2)
  389.  
  390.     local hotkey_save_array3 = obs.obs_hotkey_save(hotkey_ids[3])
  391.     obs.obs_data_set_array(settings, "instant_replay_both.trigger", hotkey_save_array3)
  392.     obs.obs_data_array_release(hotkey_save_array3)
  393. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement