From 2a6da141b8e36fdc7d794cea09937576554ae04f Mon Sep 17 00:00:00 2001 From: zoton2 Date: Fri, 16 Feb 2024 18:09:38 +0100 Subject: [PATCH] Add scene cycler/intermission scene change to Companion --- .../companion-module-esa/src/actions.ts | 29 +++++++++++++++ src/extension/companion.ts | 37 ++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/companion-plugin/companion-module-esa/src/actions.ts b/companion-plugin/companion-module-esa/src/actions.ts index bac22e48..8d1f3a5f 100644 --- a/companion-plugin/companion-module-esa/src/actions.ts +++ b/companion-plugin/companion-module-esa/src/actions.ts @@ -62,6 +62,35 @@ function initActions(instance: ModuleInstance) { instance.wsSend({ name: 'twitch_commercials_disable' }); }, }, + scene_cycle: { + name: 'Scene Cycle', + description: 'Cycles through scenes as needed and if applicable, usually to be used by hosts', + options: [], + callback: () => { + instance.wsSend({ name: 'scene_cycle' }); + }, + }, + intermission_scene_change: { + name: 'Intermission Scene Change', + description: 'Changes to a supplied intermission scene', + options: [ + { + id: 'scene', + type: 'dropdown', + label: 'Scene', + choices: [ + { id: 'intermission', label: 'Intermission' }, + { id: 'intermissionCrowd', label: 'Intermission (crowd camera)' }, + ], + default: '', + }, + ], + callback: (action) => { + if (action.options.scene) { + instance.wsSend({ name: 'intermission_scene_change', value: action.options.scene }); + } + }, + }, }); } export default initActions; diff --git a/src/extension/companion.ts b/src/extension/companion.ts index 60a5298a..080a9c1d 100644 --- a/src/extension/companion.ts +++ b/src/extension/companion.ts @@ -1,8 +1,11 @@ import companion from './util/companion'; import { get as nodecg } from './util/nodecg'; -import { streamDeckData } from './util/replicants'; +import obs, { changeScene } from './util/obs'; +import { obsData, readerIntroduction, streamDeckData } from './util/replicants'; import { sc } from './util/speedcontrol'; +const config = nodecg().bundleConfig; + // Replicants only applicable to this file from another bundle. const twitchCommercialsDisabled = nodecg().Replicant('disabled', 'esa-commercials'); @@ -68,5 +71,37 @@ companion.evt.on('action', async (name, value) => { // Because we are using server-to-server messages, no confirmation yet. nodecg().sendMessageToBundle('disable', 'esa-commercials'); } + // Used to cycle scenes if applicable, usually used by hosts. + // Some of this is copied from obs-data.ts + } else if (name === 'scene_cycle') { + const { disableTransitioning, transitioning, connected } = obsData.value; + const { scenes } = config.obs.names; + // If transitioning is disabled, or we *are* transitioning, and OBS is connected, + // and the timer is not running or paused, we can trigger these actions. + if (!disableTransitioning && !transitioning && connected + && !['running', 'paused'].includes(sc.timer.value.state)) { + // If the current scene is any of the applicable intermission ones, the next scene + // will be the game layout, so change to it. + if (obs.isCurrentScene(scenes.commercials) + || obs.isCurrentScene(scenes.intermission) + || obs.isCurrentScene(scenes.intermissionCrowd)) { + await changeScene({ scene: config.obs.names.scenes.gameLayout }); + // If the current scene is the game layout, the next scene will be the intermission, + // so change to it. + } else if (obs.isCurrentScene(scenes.gameLayout)) { + // If the commercial intermission scene exists, use that, if not, use the regular one. + if (obs.findScene(scenes.commercials)) { + await changeScene({ scene: scenes.commercials }); + } else { + await changeScene({ scene: scenes.intermission }); + } + } + } + // Used to change between intermission scenes using a supplied scene name config key. + } else if (name === 'intermission_scene_change') { + const { scenes } = config.obs.names; + const val = value as string; + const scene = (scenes as { [k: string]: string })[val]; + await changeScene({ scene, force: true }); } });