mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 12:45:28 -05:00
Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e3e621ae5 | ||
|
|
9dfbd266fc | ||
|
|
8d02f63c36 | ||
|
|
f31c54fd72 | ||
|
|
7719087065 | ||
|
|
0b175a41d1 | ||
|
|
0824abc4f5 | ||
|
|
efef29603b | ||
|
|
034a1b0c93 | ||
|
|
86fefe1e9e | ||
|
|
0bc15b4c2d | ||
|
|
7cfa956b80 | ||
|
|
9670a01e1a | ||
|
|
371f6daf5a | ||
|
|
1c141abd06 | ||
|
|
13788c2dfa | ||
|
|
daf36365a8 | ||
|
|
cea4df90b1 | ||
|
|
80b824e0a7 | ||
|
|
0bfdc3890b | ||
|
|
cc067de021 | ||
|
|
57c0734ba6 | ||
|
|
913682e128 | ||
|
|
92711c5798 | ||
|
|
80334088d0 | ||
|
|
bdd9d12257 | ||
|
|
decee4647b | ||
|
|
4991e74a72 | ||
|
|
baa158bb33 | ||
|
|
0975ffabfa | ||
|
|
beec7d5939 | ||
|
|
1bf2a154e2 | ||
|
|
aa691cf51c | ||
|
|
8fc12bee99 | ||
|
|
5e8a0f92ee | ||
|
|
86029e8e0e | ||
|
|
a86d6f1f76 | ||
|
|
8ef798c70c | ||
|
|
efc8726054 | ||
|
|
7b72abb100 | ||
|
|
311ee5d0a0 | ||
|
|
5e4258968a | ||
|
|
ae4e861f7f | ||
|
|
d692444687 | ||
|
|
6976c98fd8 | ||
|
|
75f8d0cb07 | ||
|
|
a7e03245bd | ||
|
|
056e7ef737 | ||
|
|
675c23d7cc | ||
|
|
c4b66ef7f6 | ||
|
|
5cae1bca41 | ||
|
|
407d338b8b | ||
|
|
edd9f18de0 | ||
|
|
c9769a799d | ||
|
|
047ca93486 |
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -160,6 +160,7 @@ jobs:
|
||||
libxcb-xinerama0-dev \
|
||||
libxcomposite-dev \
|
||||
libxinerama-dev \
|
||||
libxtst-dev \
|
||||
libmbedtls-dev \
|
||||
pkg-config \
|
||||
python3-dev \
|
||||
|
||||
@@ -81,37 +81,50 @@ set(advanced-scene-switcher_HEADERS
|
||||
src/headers/switch-generic.hpp
|
||||
src/headers/macro-action-edit.hpp
|
||||
src/headers/macro-action-audio.hpp
|
||||
src/headers/macro-action-file.hpp
|
||||
src/headers/macro-action-filter.hpp
|
||||
src/headers/macro-action-hotkey.hpp
|
||||
src/headers/macro-action-macro.hpp
|
||||
src/headers/macro-action-media.hpp
|
||||
src/headers/macro-action-plugin-state.hpp
|
||||
src/headers/macro-action-recording.hpp
|
||||
src/headers/macro-action-replay-buffer.hpp
|
||||
src/headers/macro-action-run.hpp
|
||||
src/headers/macro-action-scene-order.hpp
|
||||
src/headers/macro-action-scene-switch.hpp
|
||||
src/headers/macro-action-scene-transform.hpp
|
||||
src/headers/macro-action-scene-visibility.hpp
|
||||
src/headers/macro-action-source.hpp
|
||||
src/headers/macro-action-streaming.hpp
|
||||
src/headers/macro-action-virtual-cam.hpp
|
||||
src/headers/macro-action-wait.hpp
|
||||
src/headers/macro-condition-edit.hpp
|
||||
src/headers/macro-condition-audio.hpp
|
||||
src/headers/macro-condition-counter.hpp
|
||||
src/headers/macro-condition-date.hpp
|
||||
src/headers/macro-condition-macro.hpp
|
||||
src/headers/macro-condition-file.hpp
|
||||
src/headers/macro-condition-filter.hpp
|
||||
src/headers/macro-condition-hotkey.hpp
|
||||
src/headers/macro-condition-idle.hpp
|
||||
src/headers/macro-condition-interval.hpp
|
||||
src/headers/macro-condition-media.hpp
|
||||
src/headers/macro-condition-plugin-state.hpp
|
||||
src/headers/macro-condition-process.hpp
|
||||
src/headers/macro-condition-recording.hpp
|
||||
src/headers/macro-condition-region.hpp
|
||||
src/headers/macro-condition-replay-buffer.hpp
|
||||
src/headers/macro-condition-scene-order.hpp
|
||||
src/headers/macro-condition-scene.hpp
|
||||
src/headers/macro-condition-source.hpp
|
||||
src/headers/macro-condition-streaming.hpp
|
||||
src/headers/macro-condition-timer.hpp
|
||||
src/headers/macro-condition-video.hpp
|
||||
src/headers/macro-condition-virtual-cam.hpp
|
||||
src/headers/macro-condition-window.hpp
|
||||
src/headers/macro.hpp
|
||||
src/headers/macro-selection.hpp
|
||||
src/headers/curl-helper.hpp
|
||||
src/headers/hotkey.hpp
|
||||
src/headers/scene-selection.hpp
|
||||
src/headers/screenshot-helper.hpp
|
||||
src/headers/name-dialog.hpp
|
||||
src/headers/duration-control.hpp
|
||||
@@ -149,38 +162,50 @@ set(advanced-scene-switcher_SOURCES
|
||||
src/switch-generic.cpp
|
||||
src/macro-action-edit.cpp
|
||||
src/macro-action-audio.cpp
|
||||
src/macro-action-file.cpp
|
||||
src/macro-action-filter.cpp
|
||||
src/macro-action-hotkey.cpp
|
||||
src/macro-action-macro.cpp
|
||||
src/macro-action-media.cpp
|
||||
src/macro-action-plugin-state.cpp
|
||||
src/macro-action-recording.cpp
|
||||
src/macro-action-replay-buffer.cpp
|
||||
src/macro-action-run.cpp
|
||||
src/macro-action-scene-order.cpp
|
||||
src/macro-action-scene-switch.cpp
|
||||
src/macro-action-scene-transform.cpp
|
||||
src/macro-action-scene-visibility.cpp
|
||||
src/macro-action-source.cpp
|
||||
src/macro-action-streaming.cpp
|
||||
src/macro-action-virtual-cam.cpp
|
||||
src/macro-action-wait.cpp
|
||||
src/macro-condition-edit.cpp
|
||||
src/macro-condition-audio.cpp
|
||||
src/macro-condition-counter.cpp
|
||||
src/macro-condition-date.cpp
|
||||
src/macro-condition-macro.cpp
|
||||
src/macro-condition-file.cpp
|
||||
src/macro-condition-filter.cpp
|
||||
src/macro-condition-hotkey.cpp
|
||||
src/macro-condition-idle.cpp
|
||||
src/macro-condition-interval.cpp
|
||||
src/macro-condition-media.cpp
|
||||
src/macro-condition-plugin-state.cpp
|
||||
src/macro-condition-process.cpp
|
||||
src/macro-condition-recording.cpp
|
||||
src/macro-condition-region.cpp
|
||||
src/macro-condition-replay-buffer.cpp
|
||||
src/macro-condition-scene-order.cpp
|
||||
src/macro-condition-scene.cpp
|
||||
src/macro-condition-source.cpp
|
||||
src/macro-condition-streaming.cpp
|
||||
src/macro-condition-timer.cpp
|
||||
src/macro-condition-video.cpp
|
||||
src/macro-condition-virtual-cam.cpp
|
||||
src/macro-condition-window.cpp
|
||||
src/macro.cpp
|
||||
src/macro-selection.cpp
|
||||
src/macro-tab.cpp
|
||||
src/curl-helper.cpp
|
||||
src/scene-selection.cpp
|
||||
src/screenshot-helper.cpp
|
||||
src/name-dialog.cpp
|
||||
src/duration-control.cpp
|
||||
|
||||
@@ -284,6 +284,8 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="Audio Quelle stu
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="Audio Quelle aktiv schalten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="Szenenwechsler starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="Szenenwechsler stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="Virtuelle Kamera starten"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="Virtuelle Kamera stoppen"
|
||||
AdvSceneSwitcher.sceneTriggerTab.entry="Wenn {{scenes}} {{triggers}} {{actions}} {{audioSources}} nach {{duration}} "
|
||||
AdvSceneSwitcher.sceneTriggerTab.help="Dieser Tab ermöglicht es automatisiert Handlungen, wie etwa das Stoppen von einer Aufnahme oder des Streamens, bei einem Szenenwechsel auszuführen."
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ AdvSceneSwitcher.condition.scene.type.previous="Previous"
|
||||
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} scene is {{scenes}}"
|
||||
AdvSceneSwitcher.condition.window="Window"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused"
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed"
|
||||
AdvSceneSwitcher.condition.file="File"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} {{browseButton}} matches:"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
@@ -124,15 +124,22 @@ AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for {{duratio
|
||||
AdvSceneSwitcher.condition.pluginState="Plugin state"
|
||||
AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene change was triggered in this interval"
|
||||
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
||||
AdvSceneSwitcher.condition.interval="Interval"
|
||||
AdvSceneSwitcher.condition.interval.entry="{{duration}} have passed"
|
||||
AdvSceneSwitcher.condition.counter="Count"
|
||||
AdvSceneSwitcher.condition.counter.type.below="Less than"
|
||||
AdvSceneSwitcher.condition.counter.type.above="More than"
|
||||
AdvSceneSwitcher.condition.counter.type.equal="Exactly"
|
||||
AdvSceneSwitcher.condition.counter.reset="Reset"
|
||||
AdvSceneSwitcher.condition.counter.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
|
||||
AdvSceneSwitcher.condition.counter.entry.line2="Current count: {{currentCount}} {{resetCount}}"
|
||||
AdvSceneSwitcher.condition.timer="Timer"
|
||||
AdvSceneSwitcher.condition.timer.entry.line1="{{duration}} have passed"
|
||||
AdvSceneSwitcher.condition.timer.entry.line2="Time remaining: {{remaining}} seconds"
|
||||
AdvSceneSwitcher.condition.timer.entry.line3="{{reset}} {{autoReset}} Automatically reset timer after duration was reached"
|
||||
AdvSceneSwitcher.condition.timer.reset="Reset"
|
||||
AdvSceneSwitcher.condition.macro="Macro"
|
||||
AdvSceneSwitcher.condition.macro.type.count="Count"
|
||||
AdvSceneSwitcher.condition.macro.type.state="State"
|
||||
AdvSceneSwitcher.condition.macro.type.selection="Condition type: {{types}}"
|
||||
AdvSceneSwitcher.condition.macro.count.type.below="Less than"
|
||||
AdvSceneSwitcher.condition.macro.count.type.above="More than"
|
||||
AdvSceneSwitcher.condition.macro.count.type.equal="Exactly"
|
||||
AdvSceneSwitcher.condition.macro.count.reset="Reset"
|
||||
AdvSceneSwitcher.condition.macro.state.entry="Conditions of {{macros}} are true"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} was executed {{conditions}} {{count}} times"
|
||||
AdvSceneSwitcher.condition.macro.count.entry.line2="Current count: {{currentCount}} {{resetCount}}"
|
||||
AdvSceneSwitcher.condition.source="Source"
|
||||
AdvSceneSwitcher.condition.source.type.active="Is active"
|
||||
AdvSceneSwitcher.condition.source.type.showing="Is showing"
|
||||
@@ -142,6 +149,37 @@ AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.virtualCamera="Virtual camera"
|
||||
AdvSceneSwitcher.condition.virtualCamera.state.start="Virtual camera started"
|
||||
AdvSceneSwitcher.condition.virtualCamera.state.stop="Virtual camera stopped"
|
||||
AdvSceneSwitcher.condition.virtualCamera.entry="{{states}}"
|
||||
AdvSceneSwitcher.condition.filter="Filter"
|
||||
AdvSceneSwitcher.condition.filter.type.active="Is enabled"
|
||||
AdvSceneSwitcher.condition.filter.type.showing="Is disabled"
|
||||
AdvSceneSwitcher.condition.filter.type.settings="Settings match"
|
||||
AdvSceneSwitcher.condition.filter.regex="Use regular expressions"
|
||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.position="Is at position"
|
||||
AdvSceneSwitcher.condition.sceneOrder.positionInfo="The position value starts at the bottom with 0 and increases by one for each scene item including the ones in scene groups"
|
||||
AdvSceneSwitcher.condition.sceneOrder.entry="On {{scenes}} {{sources}} {{conditions}} {{sources2}} {{position}}"
|
||||
AdvSceneSwitcher.condition.hotkey="Hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.name="Macro trigger hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.tip="Note: You can configure the keybindings for this hotkey in the OBS settings window"
|
||||
AdvSceneSwitcher.condition.hotkey.entry="Name: {{name}}"
|
||||
AdvSceneSwitcher.condition.replay="Replay buffer"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="Replay buffer stopped"
|
||||
AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
|
||||
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
|
||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||
AdvSceneSwitcher.condition.date="Date"
|
||||
AdvSceneSwitcher.condition.date.entry.line1="{{dateTime}} {{ignoreDate}} Ignore date selection {{ignoreTime}} Ignore time selection"
|
||||
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Repeat every {{duration}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||
@@ -174,6 +212,9 @@ AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Start streaming"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.run="Run"
|
||||
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
||||
AdvSceneSwitcher.action.run.entry="Run {{filePath}} {{browseButton}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||
@@ -182,7 +223,9 @@ AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sourc
|
||||
AdvSceneSwitcher.action.filter="Filter"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
||||
AdvSceneSwitcher.action.filter.type.settings="Set settings"
|
||||
AdvSceneSwitcher.action.filter.entry="On {{sources}} {{actions}} {{filters}}"
|
||||
AdvSceneSwitcher.action.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.action.source="Source"
|
||||
AdvSceneSwitcher.action.source.type.enable="Enable"
|
||||
AdvSceneSwitcher.action.source.type.disable="Disable"
|
||||
@@ -205,7 +248,37 @@ AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Plugin state"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}} {{values}} {{scenes}}"
|
||||
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.type.start="Start virtual camera"
|
||||
AdvSceneSwitcher.action.virtualCamera.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.hotkey="Hotkey"
|
||||
AdvSceneSwitcher.action.hotkey.leftShift="Left Shift"
|
||||
AdvSceneSwitcher.action.hotkey.rightShift="Right Shift"
|
||||
AdvSceneSwitcher.action.hotkey.leftCtrl="Left Ctrl"
|
||||
AdvSceneSwitcher.action.hotkey.rightCtrl="Right Ctrl"
|
||||
AdvSceneSwitcher.action.hotkey.leftAlt="Left Alt"
|
||||
AdvSceneSwitcher.action.hotkey.rightAlt="Right Alt"
|
||||
AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate key presses - functionality disabled!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}}"
|
||||
AdvSceneSwitcher.action.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Move to top"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Move to bottom"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Move to position"
|
||||
AdvSceneSwitcher.action.sceneOrder.entry="On {{scenes}} {{actions}} {{sources}} {{position}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="Scene item transform"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="Get transform"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="On {{scenes}} transform {{sources}}"
|
||||
AdvSceneSwitcher.action.file="File"
|
||||
AdvSceneSwitcher.action.file.type.write="Write"
|
||||
AdvSceneSwitcher.action.file.type.append="Append"
|
||||
AdvSceneSwitcher.action.file.entry="{{actions}} to {{filePath}} {{browseButton}}:"
|
||||
|
||||
; Transition Tab
|
||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||
@@ -439,6 +512,8 @@ AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.muteSource="mute source"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.unmuteSource="unmute source"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startSwitcher="start the scene switcher"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopSwitcher="stop the scene switcher"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.startVirtualCamera="start virtual camera"
|
||||
AdvSceneSwitcher.sceneTriggerTab.sceneTriggerAction.stopVirtualCamera="stop virtual camera"
|
||||
AdvSceneSwitcher.sceneTriggerTab.entry="When {{scenes}} {{triggers}} {{actions}} {{audioSources}} after {{duration}}"
|
||||
AdvSceneSwitcher.sceneTriggerTab.help="This tab allows you to trigger actions on scene changes, like stopping recording or streaming."
|
||||
|
||||
@@ -456,6 +531,8 @@ AdvSceneSwitcher.browse="Browse"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
AdvSceneSwitcher.selectAnyScene="Any Scene"
|
||||
AdvSceneSwitcher.currentTransition="Current Transition"
|
||||
AdvSceneSwitcher.selectTransition="--select transition--"
|
||||
AdvSceneSwitcher.selectWindow="--select window--"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <QMainWindow>
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
#include <regex>
|
||||
|
||||
#include <obs-module.h>
|
||||
#include <obs-frontend-api.h>
|
||||
@@ -199,6 +200,7 @@ void SwitcherData::Thread()
|
||||
if (checkPause()) {
|
||||
continue;
|
||||
}
|
||||
setPreconditions();
|
||||
match = checkForMatch(scene, transition, linger,
|
||||
setPrevSceneAfterLinger, macroMatch);
|
||||
if (stop) {
|
||||
@@ -252,6 +254,31 @@ void SwitcherData::Thread()
|
||||
blog(LOG_INFO, "stopped");
|
||||
}
|
||||
|
||||
void SwitcherData::setPreconditions()
|
||||
{
|
||||
// Window title
|
||||
lastTitle = currentTitle;
|
||||
std::string title;
|
||||
GetCurrentWindowTitle(title);
|
||||
for (auto &window : ignoreWindowsSwitches) {
|
||||
bool equals = (title == window);
|
||||
bool matches = false;
|
||||
if (!equals) {
|
||||
try {
|
||||
std::regex expr(window);
|
||||
matches = std::regex_match(title, expr);
|
||||
|
||||
} catch (const std::regex_error &) {
|
||||
}
|
||||
}
|
||||
if (equals || matches) {
|
||||
title = lastTitle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentTitle = title;
|
||||
}
|
||||
|
||||
bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
||||
OBSWeakSource &transition, int &linger,
|
||||
bool &setPrevSceneAfterLinger,
|
||||
@@ -327,7 +354,8 @@ void switchScene(const sceneSwitchInfo &sceneSwitch)
|
||||
}
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
|
||||
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||
obs_source_t *currentSource =
|
||||
obs_weak_source_get_source(switcher->currentScene);
|
||||
|
||||
if (source && source != currentSource) {
|
||||
transitionData currentTransitionData;
|
||||
@@ -433,6 +461,8 @@ extern "C" void FreeSceneSwitcher()
|
||||
loaded_curl_lib = nullptr;
|
||||
}
|
||||
|
||||
PlatformCleanup();
|
||||
|
||||
delete switcher;
|
||||
switcher = nullptr;
|
||||
}
|
||||
@@ -444,15 +474,21 @@ void handleSceneChange()
|
||||
switcher->cv.notify_one();
|
||||
}
|
||||
|
||||
// Set previous scene
|
||||
// Set current and previous scene
|
||||
obs_source_t *source = obs_frontend_get_current_scene();
|
||||
obs_weak_source_t *ws = obs_source_get_weak_source(source);
|
||||
|
||||
if (ws && ws != switcher->currentScene) {
|
||||
switcher->previousScene = switcher->currentScene;
|
||||
switcher->currentScene = ws;
|
||||
vblog(LOG_INFO, "current scene: %s",
|
||||
GetWeakSourceName(switcher->currentScene).c_str());
|
||||
vblog(LOG_INFO, "previous scene: %s",
|
||||
GetWeakSourceName(switcher->previousScene).c_str());
|
||||
}
|
||||
|
||||
obs_source_release(source);
|
||||
obs_weak_source_release(ws);
|
||||
if (source && switcher->previousSceneHelper != ws) {
|
||||
switcher->previousScene = switcher->previousSceneHelper;
|
||||
switcher->previousSceneHelper = ws;
|
||||
}
|
||||
|
||||
switcher->checkTriggers();
|
||||
switcher->checkDefaultSceneTransitions();
|
||||
@@ -497,6 +533,11 @@ void handlePeviewSceneChange()
|
||||
}
|
||||
}
|
||||
|
||||
void setReplayBufferSaved()
|
||||
{
|
||||
switcher->replayBufferSaved = true;
|
||||
}
|
||||
|
||||
// Note to future self:
|
||||
// be careful using switcher->m here as there is potential for deadlocks when using
|
||||
// frontend functions such as obs_frontend_set_current_scene()
|
||||
@@ -528,6 +569,9 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
||||
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
|
||||
resetLiveTime();
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
|
||||
setReplayBufferSaved();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -546,6 +590,8 @@ extern "C" void InitSceneSwitcher()
|
||||
switcher->curl = f_curl_init();
|
||||
}
|
||||
|
||||
PlatformInit();
|
||||
|
||||
auto cb = []() {
|
||||
QMainWindow *window =
|
||||
(QMainWindow *)obs_frontend_get_main_window();
|
||||
|
||||
@@ -33,6 +33,17 @@ bool resolveCurl()
|
||||
|
||||
bool loadCurl()
|
||||
{
|
||||
loaded_curl_lib = new QLibrary(curl_library_name, nullptr);
|
||||
if (resolveCurl()) {
|
||||
blog(LOG_INFO, "[adv-ss] found curl library");
|
||||
return true;
|
||||
} else {
|
||||
delete loaded_curl_lib;
|
||||
loaded_curl_lib = nullptr;
|
||||
blog(LOG_WARNING,
|
||||
"[adv-ss] couldn't find the curl library in PATH");
|
||||
}
|
||||
|
||||
QStringList locations;
|
||||
locations << QDir::currentPath();
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
||||
@@ -32,6 +32,20 @@ bool Duration::DurationReached()
|
||||
return runTime.count() >= seconds * 1000;
|
||||
}
|
||||
|
||||
double Duration::TimeRemaining()
|
||||
{
|
||||
if (_startTime.time_since_epoch().count() == 0) {
|
||||
return seconds;
|
||||
}
|
||||
auto runTime = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::high_resolution_clock::now() - _startTime);
|
||||
|
||||
if (runTime.count() >= seconds * 1000) {
|
||||
return 0;
|
||||
}
|
||||
return (seconds * 1000 - runTime.count()) / 1000.;
|
||||
}
|
||||
|
||||
void Duration::Reset()
|
||||
{
|
||||
_startTime = {};
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#if defined(WIN32)
|
||||
constexpr auto curl_library_name = "libcurl.dll";
|
||||
#elif __APPLE__
|
||||
#define curl_library_name "libcurl.4.dylib"
|
||||
constexpr auto curl_library_name = "libcurl.4.dylib";
|
||||
#else
|
||||
#define curl_library_name "libcurl.so.4"
|
||||
constexpr auto curl_library_name = "libcurl.so.4";
|
||||
#endif
|
||||
|
||||
typedef CURL *(*initFunction)(void);
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
const char *unitName = "displayUnit");
|
||||
|
||||
bool DurationReached();
|
||||
double TimeRemaining();
|
||||
void Reset();
|
||||
std::string ToString();
|
||||
|
||||
|
||||
125
src/headers/hotkey.hpp
Normal file
125
src/headers/hotkey.hpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
extern bool canSimulateKeyPresses;
|
||||
|
||||
enum class HotkeyType {
|
||||
Key_NoKey = 0,
|
||||
|
||||
Key_A,
|
||||
Key_B,
|
||||
Key_C,
|
||||
Key_D,
|
||||
Key_E,
|
||||
Key_F,
|
||||
Key_G,
|
||||
Key_H,
|
||||
Key_I,
|
||||
Key_J,
|
||||
Key_K,
|
||||
Key_L,
|
||||
Key_M,
|
||||
Key_N,
|
||||
Key_O,
|
||||
Key_P,
|
||||
Key_Q,
|
||||
Key_R,
|
||||
Key_S,
|
||||
Key_T,
|
||||
Key_U,
|
||||
Key_V,
|
||||
Key_W,
|
||||
Key_X,
|
||||
Key_Y,
|
||||
Key_Z,
|
||||
|
||||
Key_0,
|
||||
Key_1,
|
||||
Key_2,
|
||||
Key_3,
|
||||
Key_4,
|
||||
Key_5,
|
||||
Key_6,
|
||||
Key_7,
|
||||
Key_8,
|
||||
Key_9,
|
||||
|
||||
Key_F1,
|
||||
Key_F2,
|
||||
Key_F3,
|
||||
Key_F4,
|
||||
Key_F5,
|
||||
Key_F6,
|
||||
Key_F7,
|
||||
Key_F8,
|
||||
Key_F9,
|
||||
Key_F10,
|
||||
Key_F11,
|
||||
Key_F12,
|
||||
Key_F13,
|
||||
Key_F14,
|
||||
Key_F15,
|
||||
Key_F16,
|
||||
Key_F17,
|
||||
Key_F18,
|
||||
Key_F19,
|
||||
Key_F20,
|
||||
Key_F21,
|
||||
Key_F22,
|
||||
Key_F23,
|
||||
Key_F24,
|
||||
|
||||
Key_Escape,
|
||||
Key_Space,
|
||||
Key_Return,
|
||||
Key_Backspace,
|
||||
Key_Tab,
|
||||
|
||||
Key_Shift_L,
|
||||
Key_Shift_R,
|
||||
Key_Control_L,
|
||||
Key_Control_R,
|
||||
Key_Alt_L,
|
||||
Key_Alt_R,
|
||||
Key_Win_L,
|
||||
Key_Win_R,
|
||||
Key_Apps,
|
||||
|
||||
Key_CapsLock,
|
||||
Key_NumLock,
|
||||
Key_ScrollLock,
|
||||
|
||||
Key_PrintScreen,
|
||||
Key_Pause,
|
||||
|
||||
Key_Insert,
|
||||
Key_Delete,
|
||||
Key_PageUP,
|
||||
Key_PageDown,
|
||||
Key_Home,
|
||||
Key_End,
|
||||
|
||||
Key_Left,
|
||||
Key_Right,
|
||||
Key_Up,
|
||||
Key_Down,
|
||||
|
||||
Key_Numpad0,
|
||||
Key_Numpad1,
|
||||
Key_Numpad2,
|
||||
Key_Numpad3,
|
||||
Key_Numpad4,
|
||||
Key_Numpad5,
|
||||
Key_Numpad6,
|
||||
Key_Numpad7,
|
||||
Key_Numpad8,
|
||||
Key_Numpad9,
|
||||
|
||||
Key_NumpadAdd,
|
||||
Key_NumpadSubtract,
|
||||
Key_NumpadMultiply,
|
||||
Key_NumpadDivide,
|
||||
Key_NumpadDecimal,
|
||||
Key_NumpadEnter
|
||||
};
|
||||
|
||||
void registerHotkeys();
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -51,6 +52,8 @@ private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void VolumeChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_audioSources;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QComboBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <deque>
|
||||
#include "macro.hpp"
|
||||
#include "section.hpp"
|
||||
@@ -44,10 +45,19 @@ public:
|
||||
|
||||
private slots:
|
||||
void ActionSelectionChanged(const QString &text);
|
||||
void HeaderInfoChanged(const QString &);
|
||||
signals:
|
||||
void MacroAdded(const QString &name);
|
||||
void MacroRemoved(const QString &name);
|
||||
void MacroRenamed(const QString &oldName, const QString newName);
|
||||
void SceneGroupAdded(const QString &name);
|
||||
void SceneGroupRemoved(const QString &name);
|
||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||
|
||||
protected:
|
||||
QComboBox *_actionSelection;
|
||||
Section *_section;
|
||||
QLabel *_headerInfo;
|
||||
|
||||
std::shared_ptr<MacroAction> *_entryData;
|
||||
|
||||
|
||||
66
src/headers/macro-action-file.hpp
Normal file
66
src/headers/macro-action-file.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
enum class FileAction {
|
||||
WRITE,
|
||||
APPEND,
|
||||
};
|
||||
|
||||
class MacroActionFile : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionFile>();
|
||||
}
|
||||
|
||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
std::string _text = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
FileAction _action = FileAction::WRITE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionFileEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionFileEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionFile> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionFileEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionFile>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void FilePathChanged();
|
||||
void BrowseButtonClicked();
|
||||
void TextChanged();
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QLineEdit *_filePath;
|
||||
QPushButton *_browseButton;
|
||||
QPlainTextEdit *_text;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionFile> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
enum class FilterAction {
|
||||
ENABLE,
|
||||
DISABLE,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroActionFilter : public MacroAction {
|
||||
@@ -13,6 +15,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -22,6 +25,7 @@ public:
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterAction _action = FilterAction::ENABLE;
|
||||
std::string _settings = "";
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -48,14 +52,20 @@ private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void FilterChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_filters;
|
||||
QComboBox *_actions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
std::shared_ptr<MacroActionFilter> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
void SetWidgetVisibility(bool);
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
78
src/headers/macro-action-hotkey.hpp
Normal file
78
src/headers/macro-action-hotkey.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "hotkey.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
|
||||
class MacroActionHotkey : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionHotkey>();
|
||||
}
|
||||
|
||||
OBSWeakSource _HotkeySource;
|
||||
HotkeyType _key = HotkeyType::Key_NoKey;
|
||||
bool _leftShift = false;
|
||||
bool _rightShift = false;
|
||||
bool _leftCtrl = false;
|
||||
bool _rightCtrl = false;
|
||||
bool _leftAlt = false;
|
||||
bool _rightAlt = false;
|
||||
bool _leftMeta = false;
|
||||
bool _rightMeta = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionHotkeyEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionHotkeyEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionHotkey> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionHotkeyEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionHotkey>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void KeyChanged(int key);
|
||||
void LShiftChanged(int state);
|
||||
void RShiftChanged(int state);
|
||||
void LCtrlChanged(int state);
|
||||
void RCtrlChanged(int state);
|
||||
void LAltChanged(int state);
|
||||
void RAltChanged(int state);
|
||||
void LMetaChanged(int state);
|
||||
void RMetaChanged(int state);
|
||||
|
||||
protected:
|
||||
QComboBox *_keys;
|
||||
QCheckBox *_leftShift;
|
||||
QCheckBox *_rightShift;
|
||||
QCheckBox *_leftCtrl;
|
||||
QCheckBox *_rightCtrl;
|
||||
QCheckBox *_leftAlt;
|
||||
QCheckBox *_rightAlt;
|
||||
QCheckBox *_leftMeta;
|
||||
QCheckBox *_rightMeta;
|
||||
|
||||
std::shared_ptr<MacroActionHotkey> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -48,6 +49,8 @@ private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
MacroSelection *_macros;
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -50,6 +51,8 @@ public:
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_mediaSources;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
enum class PluginStateAction {
|
||||
STOP,
|
||||
NO_MATCH_BEHAVIOUR,
|
||||
};
|
||||
|
||||
class MacroActionPluginState : public MacroAction {
|
||||
@@ -19,6 +20,8 @@ public:
|
||||
}
|
||||
|
||||
PluginStateAction _action = PluginStateAction::STOP;
|
||||
int _value = 0;
|
||||
OBSWeakSource _scene;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -44,12 +47,17 @@ public:
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
void ValueChanged(int value);
|
||||
void SceneChanged(const QString &text);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
QComboBox *_values;
|
||||
QComboBox *_scenes;
|
||||
std::shared_ptr<MacroActionPluginState> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(PluginStateAction, int);
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <QStringList>
|
||||
|
||||
class MacroActionRun : public MacroAction {
|
||||
public:
|
||||
@@ -10,6 +12,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -17,6 +20,7 @@ public:
|
||||
}
|
||||
|
||||
std::string _path = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||
QStringList _args;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -41,6 +45,12 @@ public:
|
||||
private slots:
|
||||
void FilePathChanged();
|
||||
void BrowseButtonClicked();
|
||||
void AddArg();
|
||||
void RemoveArg();
|
||||
void ArgUp();
|
||||
void ArgDown();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MacroActionRun> _entryData;
|
||||
@@ -48,5 +58,10 @@ protected:
|
||||
private:
|
||||
QLineEdit *_filePath;
|
||||
QPushButton *_browseButton;
|
||||
QListWidget *_argList;
|
||||
QPushButton *_addArg;
|
||||
QPushButton *_removeArg;
|
||||
QPushButton *_argUp;
|
||||
QPushButton *_argDown;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
72
src/headers/macro-action-scene-order.hpp
Normal file
72
src/headers/macro-action-scene-order.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
enum class SceneOrderAction {
|
||||
MOVE_UP,
|
||||
MOVE_DOWN,
|
||||
MOVE_TOP,
|
||||
MOVE_BOTTOM,
|
||||
POSITION,
|
||||
};
|
||||
|
||||
class MacroActionSceneOrder : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneOrder>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
SceneOrderAction _action = SceneOrderAction::MOVE_UP;
|
||||
int _position = 0;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneOrderEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneOrderEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneOrder> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneOrderEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSceneOrder>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void PositionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_actions;
|
||||
QSpinBox *_position;
|
||||
std::shared_ptr<MacroActionSceneOrder> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -3,12 +3,15 @@
|
||||
#include "switch-generic.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
// TODO: Switch to using SceneSelection class and widget instead
|
||||
|
||||
class MacroActionSwitchScene : public MacroAction, public SceneSwitcherEntry {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
@@ -42,6 +45,9 @@ public:
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void ChangeHeaderInfo(const QString &);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
DurationSelection *_duration;
|
||||
|
||||
66
src/headers/macro-action-scene-transform.hpp
Normal file
66
src/headers/macro-action-scene-transform.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
class MacroActionSceneTransform : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneTransform>();
|
||||
}
|
||||
std::string GetSettings();
|
||||
void SetSettings(std::string &);
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
struct obs_transform_info _info;
|
||||
struct obs_sceneitem_crop _crop;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneTransformEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneTransformEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneTransform> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneTransformEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionSceneTransform>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
std::shared_ptr<MacroActionSceneTransform> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
enum class SceneVisibilityAction {
|
||||
SHOW,
|
||||
@@ -13,13 +14,14 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionSceneVisibility>();
|
||||
}
|
||||
|
||||
OBSWeakSource _scene;
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
SceneVisibilityAction _action = SceneVisibilityAction::SHOW;
|
||||
|
||||
@@ -46,12 +48,14 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const QString &text);
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_scenes;
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
@@ -54,6 +55,8 @@ private slots:
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
@@ -65,6 +68,5 @@ protected:
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool);
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
55
src/headers/macro-action-virtual-cam.hpp
Normal file
55
src/headers/macro-action-virtual-cam.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include <QDoubleSpinBox>
|
||||
#include "macro-action-edit.hpp"
|
||||
|
||||
enum class VCamAction {
|
||||
STOP,
|
||||
START,
|
||||
};
|
||||
|
||||
class MacroActionVCam : public MacroAction {
|
||||
public:
|
||||
bool PerformAction();
|
||||
void LogAction();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroAction> Create()
|
||||
{
|
||||
return std::make_shared<MacroActionVCam>();
|
||||
}
|
||||
|
||||
VCamAction _action = VCamAction::STOP;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionVCamEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionVCamEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionVCam> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionVCamEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionVCam>(action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionVCam> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -60,6 +61,8 @@ private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void VolumeThresholdChanged(int vol);
|
||||
void ConditionChanged(int cond);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_audioSources;
|
||||
|
||||
67
src/headers/macro-condition-date.hpp
Normal file
67
src/headers/macro-condition-date.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QDateTimeEdit>
|
||||
#include "duration-control.hpp"
|
||||
|
||||
class MacroConditionDate : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionDate>();
|
||||
}
|
||||
|
||||
QDateTime _dateTime;
|
||||
bool _ignoreDate = false;
|
||||
bool _ignoreTime = false;
|
||||
bool _repeat = false;
|
||||
Duration _duration;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionDateEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionDateEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionDate> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionDateEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionDate>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DateTimeChanged(const QDateTime &datetime);
|
||||
void IgnoreDateChanged(int state);
|
||||
void IgnoreTimeChanged(int state);
|
||||
void RepeatChanged(int state);
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QDateTimeEdit *_dateTime;
|
||||
QCheckBox *_ignoreDate;
|
||||
QCheckBox *_ignoreTime;
|
||||
QCheckBox *_repeat;
|
||||
DurationSelection *_duration;
|
||||
std::shared_ptr<MacroConditionDate> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -51,11 +51,20 @@ private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void DurationConditionChanged(DurationCondition cond);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
void HeaderInfoChanged(const QString &);
|
||||
signals:
|
||||
void MacroAdded(const QString &name);
|
||||
void MacroRemoved(const QString &name);
|
||||
void MacroRenamed(const QString &oldName, const QString newName);
|
||||
void SceneGroupAdded(const QString &name);
|
||||
void SceneGroupRemoved(const QString &name);
|
||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||
|
||||
protected:
|
||||
QComboBox *_logicSelection;
|
||||
QComboBox *_conditionSelection;
|
||||
Section *_section;
|
||||
QLabel *_headerInfo;
|
||||
DurationConstraintEdit *_dur;
|
||||
|
||||
std::shared_ptr<MacroCondition> *_entryData;
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -66,6 +67,8 @@ private slots:
|
||||
void UseRegexChanged(int state);
|
||||
void CheckModificationDateChanged(int state);
|
||||
void OnlyMatchIfChangedChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_fileType;
|
||||
|
||||
74
src/headers/macro-condition-filter.hpp
Normal file
74
src/headers/macro-condition-filter.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class FilterCondition {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroConditionFilter : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionFilter>();
|
||||
}
|
||||
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterCondition _condition = FilterCondition::ENABLED;
|
||||
std::string _settings = "";
|
||||
bool _regex = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionFilterEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionFilterEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionFilter> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionFilterEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionFilter>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const QString &text);
|
||||
void FilterChanged(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
QComboBox *_filters;
|
||||
QComboBox *_conditions;
|
||||
QPushButton *_getSettings;
|
||||
QPlainTextEdit *_settings;
|
||||
QCheckBox *_regex;
|
||||
|
||||
std::shared_ptr<MacroConditionFilter> _entryData;
|
||||
|
||||
private:
|
||||
void SetSettingsSelectionVisible(bool visible);
|
||||
bool _loading = true;
|
||||
};
|
||||
54
src/headers/macro-condition-hotkey.hpp
Normal file
54
src/headers/macro-condition-hotkey.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
|
||||
class MacroConditionHotkey : public MacroCondition {
|
||||
public:
|
||||
MacroConditionHotkey();
|
||||
~MacroConditionHotkey();
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionHotkey>();
|
||||
}
|
||||
void SetPressed() { _pressed = true; }
|
||||
|
||||
std::string _name;
|
||||
obs_hotkey_id _hotkeyID = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
private:
|
||||
bool _pressed = false;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionHotkeyEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionHotkeyEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionHotkey> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionHotkeyEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionHotkey>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void NameChanged();
|
||||
|
||||
protected:
|
||||
QLineEdit *_name;
|
||||
std::shared_ptr<MacroConditionHotkey> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -6,65 +6,84 @@
|
||||
#include <QLabel>
|
||||
#include <QTimer>
|
||||
|
||||
enum class MacroConditionMacroType {
|
||||
COUNT,
|
||||
STATE,
|
||||
};
|
||||
|
||||
enum class CounterCondition {
|
||||
BELOW,
|
||||
ABOVE,
|
||||
EQUAL,
|
||||
};
|
||||
|
||||
class MacroConditionCounter : public MacroRefCondition {
|
||||
class MacroConditionMacro : public MacroRefCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionCounter>();
|
||||
return std::make_shared<MacroConditionMacro>();
|
||||
}
|
||||
|
||||
CounterCondition _condition = CounterCondition::BELOW;
|
||||
MacroConditionMacroType _type = MacroConditionMacroType::STATE;
|
||||
CounterCondition _counterCondition = CounterCondition::BELOW;
|
||||
int _count = 0;
|
||||
|
||||
private:
|
||||
bool CheckCountCondition();
|
||||
bool CheckStateCondition();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionCounterEdit : public QWidget {
|
||||
class MacroConditionMacroEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionCounterEdit(
|
||||
MacroConditionMacroEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionCounter> cond = nullptr);
|
||||
std::shared_ptr<MacroConditionMacro> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionCounterEdit(
|
||||
return new MacroConditionMacroEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionCounter>(cond));
|
||||
std::dynamic_pointer_cast<MacroConditionMacro>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void MacroRemove(const QString &name);
|
||||
void TypeChanged(int type);
|
||||
void CountChanged(int value);
|
||||
void ConditionChanged(int cond);
|
||||
void ResetClicked();
|
||||
void UpdateCount();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
MacroSelection *_macros;
|
||||
QComboBox *_conditions;
|
||||
QComboBox *_types;
|
||||
QComboBox *_counterConditions;
|
||||
QSpinBox *_count;
|
||||
QLabel *_currentCount;
|
||||
QPushButton *_resetCount;
|
||||
QHBoxLayout *_settingsLine1;
|
||||
QHBoxLayout *_settingsLine2;
|
||||
std::unique_ptr<QTimer> _timer;
|
||||
std::shared_ptr<MacroConditionCounter> _entryData;
|
||||
std::shared_ptr<MacroConditionMacro> _entryData;
|
||||
|
||||
private:
|
||||
void ClearLayouts();
|
||||
void SetupStateWidgets();
|
||||
void SetupCountWidgets();
|
||||
void ResetTimer();
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -90,6 +91,8 @@ private slots:
|
||||
void TimeRestrictionChanged(int index);
|
||||
void TimeChanged(double seconds);
|
||||
void TimeUnitChanged(DurationUnit unit);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_mediaSources;
|
||||
|
||||
@@ -8,6 +8,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -41,6 +42,8 @@ public:
|
||||
private slots:
|
||||
void ProcessChanged(const QString &text);
|
||||
void FocusChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_processSelection;
|
||||
|
||||
56
src/headers/macro-condition-replay-buffer.hpp
Normal file
56
src/headers/macro-condition-replay-buffer.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class ReplayBufferState {
|
||||
STOP,
|
||||
START,
|
||||
SAVE,
|
||||
};
|
||||
|
||||
class MacroConditionReplayBuffer : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionReplayBuffer>();
|
||||
}
|
||||
|
||||
ReplayBufferState _state;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionReplayBufferEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionReplayBufferEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionReplayBuffer> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionReplayBufferEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionReplayBuffer>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void StateChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_state;
|
||||
std::shared_ptr<MacroConditionReplayBuffer> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
76
src/headers/macro-condition-scene-order.hpp
Normal file
76
src/headers/macro-condition-scene-order.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class SceneOrderCondition {
|
||||
ABOVE,
|
||||
BELOW,
|
||||
POSITION,
|
||||
};
|
||||
|
||||
class MacroConditionSceneOrder : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionSceneOrder>();
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _source;
|
||||
OBSWeakSource _source2;
|
||||
int _position = 0;
|
||||
SceneOrderCondition _condition = SceneOrderCondition::ABOVE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSceneOrderEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSceneOrderEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSceneOrder> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSceneOrderEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionSceneOrder>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const QString &text);
|
||||
void Source2Changed(const QString &text);
|
||||
void ConditionChanged(int cond);
|
||||
void PositionChanged(int cond);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_conditions;
|
||||
QComboBox *_sources;
|
||||
QComboBox *_sources2;
|
||||
QSpinBox *_position;
|
||||
QLabel *_posInfo;
|
||||
|
||||
std::shared_ptr<MacroConditionSceneOrder> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool showPos);
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
@@ -13,13 +15,14 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionScene>();
|
||||
}
|
||||
|
||||
OBSWeakSource _scene;
|
||||
SceneSelection _scene;
|
||||
SceneType _type;
|
||||
|
||||
private:
|
||||
@@ -44,11 +47,13 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const QString &text);
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void TypeChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sceneSelection;
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sceneType;
|
||||
std::shared_ptr<MacroConditionScene> _entryData;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -52,6 +53,8 @@ private slots:
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_sources;
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QTimer>
|
||||
#include "duration-control.hpp"
|
||||
|
||||
class MacroConditionInterval : public MacroCondition {
|
||||
class MacroConditionTimer : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
@@ -12,41 +13,48 @@ public:
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionInterval>();
|
||||
return std::make_shared<MacroConditionTimer>();
|
||||
}
|
||||
|
||||
Duration _duration;
|
||||
bool _oneshot = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionIntervalEdit : public QWidget {
|
||||
class MacroConditionTimerEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionIntervalEdit(
|
||||
MacroConditionTimerEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionInterval> cond = nullptr);
|
||||
std::shared_ptr<MacroConditionTimer> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionIntervalEdit(
|
||||
return new MacroConditionTimerEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionInterval>(
|
||||
cond));
|
||||
std::dynamic_pointer_cast<MacroConditionTimer>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DurationChanged(double seconds);
|
||||
void DurationUnitChanged(DurationUnit unit);
|
||||
void AutoResetChanged(int state);
|
||||
void ResetClicked();
|
||||
void UpdateTimeRemaining();
|
||||
|
||||
protected:
|
||||
DurationSelection *_duration;
|
||||
std::shared_ptr<MacroConditionInterval> _entryData;
|
||||
QCheckBox *_autoReset;
|
||||
QPushButton *_reset;
|
||||
QLabel *_remaining;
|
||||
std::shared_ptr<MacroConditionTimer> _entryData;
|
||||
|
||||
private:
|
||||
QTimer timer;
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
QImage GetMatchImage() { return _matchImage; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
@@ -65,6 +66,8 @@ private slots:
|
||||
void ConditionChanged(int cond);
|
||||
void FilePathChanged();
|
||||
void BrowseButtonClicked();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_videoSelection;
|
||||
|
||||
54
src/headers/macro-condition-virtual-cam.hpp
Normal file
54
src/headers/macro-condition-virtual-cam.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "macro.hpp"
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
enum class VCamState {
|
||||
STOP,
|
||||
START,
|
||||
};
|
||||
|
||||
class MacroConditionVCam : public MacroCondition {
|
||||
public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
return std::make_shared<MacroConditionVCam>();
|
||||
}
|
||||
|
||||
VCamState _state;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionVCamEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionVCamEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionVCam> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionVCamEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionVCam>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void StateChanged(int value);
|
||||
|
||||
protected:
|
||||
QComboBox *_states;
|
||||
std::shared_ptr<MacroConditionVCam> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
@@ -8,6 +8,7 @@ public:
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj);
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc();
|
||||
std::string GetId() { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create()
|
||||
{
|
||||
@@ -24,6 +25,7 @@ public:
|
||||
bool _fullscreen = false;
|
||||
bool _maximized = false;
|
||||
bool _focus = true;
|
||||
bool _windowFocusChanged = false;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -50,13 +52,17 @@ private slots:
|
||||
void WindowChanged(const QString &text);
|
||||
void FullscreenChanged(int state);
|
||||
void MaximizedChanged(int state);
|
||||
void FocusChanged(int state);
|
||||
void FocusedChanged(int state);
|
||||
void WindowFocusChanged(int state);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
QComboBox *_windowSelection;
|
||||
QCheckBox *_fullscreen;
|
||||
QCheckBox *_maximized;
|
||||
QCheckBox *_focused;
|
||||
QCheckBox *_windowFocusChanged;
|
||||
std::shared_ptr<MacroConditionWindow> _entryData;
|
||||
|
||||
private:
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
virtual bool CheckCondition() = 0;
|
||||
virtual bool Save(obs_data_t *obj) = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual std::string GetShortDesc();
|
||||
virtual std::string GetId() = 0;
|
||||
|
||||
LogicType GetLogicType() { return _logic; }
|
||||
@@ -65,6 +66,7 @@ public:
|
||||
virtual bool PerformAction() = 0;
|
||||
virtual bool Save(obs_data_t *obj) = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual std::string GetShortDesc();
|
||||
virtual std::string GetId() = 0;
|
||||
virtual void LogAction();
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
static bool AskForName(QWidget *parent, const QString &title,
|
||||
const QString &text, std::string &userTextInput,
|
||||
const QString &placeHolder = QString(""),
|
||||
int maxSize = 170);
|
||||
int maxSize = 170, bool clean = true);
|
||||
|
||||
private:
|
||||
QLabel *label;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "hotkey.hpp"
|
||||
|
||||
void GetWindowList(std::vector<std::string> &windows);
|
||||
void GetWindowList(QStringList &windows);
|
||||
@@ -9,3 +10,6 @@ std::pair<int, int> getCursorPos();
|
||||
int secondsSinceLastInput();
|
||||
void GetProcessList(QStringList &processes);
|
||||
bool isInFocus(const QString &executable);
|
||||
void PressKeys(const std::vector<HotkeyType> keys);
|
||||
void PlatformInit();
|
||||
void PlatformCleanup();
|
||||
|
||||
@@ -82,3 +82,6 @@ private:
|
||||
|
||||
SceneGroup *sceneGroup = nullptr;
|
||||
};
|
||||
|
||||
SceneGroup *GetSceneGroupByName(const char *name);
|
||||
SceneGroup *GetSceneGroupByQString(const QString &name);
|
||||
|
||||
51
src/headers/scene-selection.hpp
Normal file
51
src/headers/scene-selection.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include "scene-group.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
enum class SceneSelectionType {
|
||||
SCENE,
|
||||
GROUP,
|
||||
PREVIOUS,
|
||||
CURRENT,
|
||||
};
|
||||
|
||||
class SceneSelection {
|
||||
public:
|
||||
void Save(obs_data_t *obj, const char *name = "scene",
|
||||
const char *typeName = "sceneType");
|
||||
void Load(obs_data_t *obj, const char *name = "scene",
|
||||
const char *typeName = "sceneType");
|
||||
|
||||
SceneSelectionType GetType() { return _type; }
|
||||
OBSWeakSource GetScene(bool advance = true);
|
||||
std::string ToString();
|
||||
|
||||
private:
|
||||
OBSWeakSource _scene;
|
||||
SceneGroup *_group = nullptr;
|
||||
SceneSelectionType _type = SceneSelectionType::SCENE;
|
||||
friend class SceneSelectionWidget;
|
||||
};
|
||||
|
||||
class SceneSelectionWidget : public QComboBox {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SceneSelectionWidget(QWidget *parent, bool sceneGroups = false,
|
||||
bool previous = false, bool current = false);
|
||||
void SetScene(SceneSelection &);
|
||||
signals:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
|
||||
private slots:
|
||||
void SelectionChanged(const QString &name);
|
||||
void SceneGroupAdd(const QString &name);
|
||||
void SceneGroupRemove(const QString &name);
|
||||
void SceneGroupRename(const QString &oldName, const QString &newName);
|
||||
|
||||
private:
|
||||
bool IsCurrentSceneSelected(const QString &name);
|
||||
bool IsPreviousSceneSelected(const QString &name);
|
||||
};
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "switch-generic.hpp"
|
||||
@@ -27,6 +34,9 @@ enum class sceneTriggerAction {
|
||||
|
||||
START_SWITCHER,
|
||||
STOP_SWITCHER,
|
||||
|
||||
START_VCAM,
|
||||
STOP_VCAM,
|
||||
};
|
||||
|
||||
struct SceneTrigger : SceneSwitcherEntry {
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include <limits>
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QCheckBox>
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QVBoxLayout>
|
||||
|
||||
@@ -31,8 +38,7 @@ struct SceneSequenceSwitch : SceneSwitcherEntry {
|
||||
bool checkMatch(OBSWeakSource currentScene, int &linger,
|
||||
SceneSequenceSwitch *root = nullptr);
|
||||
bool checkDurationMatchInterruptible();
|
||||
void prepareUninterruptibleMatch(OBSWeakSource currentScene,
|
||||
int &linger);
|
||||
void prepareUninterruptibleMatch(int &linger);
|
||||
void advanceActiveSequence();
|
||||
void logAdvanceSequence();
|
||||
void logSequenceCanceled();
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QTimeEdit>
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <QSpinBox>
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/******************************************************************************
|
||||
Note: Long-term goal is to remove this tab / file.
|
||||
Most functionality shall be moved to the Macro tab instead.
|
||||
|
||||
So if you plan to make changes here, please consider applying them to the
|
||||
corresponding macro tab functionality instead.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "switch-generic.hpp"
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@ struct SwitcherData {
|
||||
int interval = default_interval;
|
||||
|
||||
obs_source_t *waitScene = nullptr;
|
||||
OBSWeakSource currentScene = nullptr;
|
||||
OBSWeakSource previousScene = nullptr;
|
||||
OBSWeakSource previousSceneHelper = nullptr;
|
||||
OBSWeakSource lastRandomScene;
|
||||
SceneGroup *lastRandomSceneGroup;
|
||||
OBSWeakSource nonMatchingScene;
|
||||
@@ -92,13 +92,13 @@ struct SwitcherData {
|
||||
std::chrono::high_resolution_clock::time_point lastMatchTime;
|
||||
|
||||
std::deque<Macro> macros;
|
||||
// Allow only one macro scene change per scene switcher interval
|
||||
// with the top macro having the highest priority
|
||||
bool macroSceneSwitched = false;
|
||||
bool replayBufferSaved = false;
|
||||
|
||||
std::deque<WindowSwitch> windowSwitches;
|
||||
std::vector<std::string> ignoreIdleWindows;
|
||||
std::string lastTitle;
|
||||
std::string currentTitle;
|
||||
|
||||
std::deque<ScreenRegionSwitch> screenRegionSwitches;
|
||||
|
||||
@@ -178,9 +178,9 @@ struct SwitcherData {
|
||||
std::vector<int> tabOrder = std::vector<int>(tab_count);
|
||||
|
||||
bool hotkeysRegistered = false;
|
||||
obs_hotkey_id startHotkey = 0;
|
||||
obs_hotkey_id stopHotkey = 0;
|
||||
obs_hotkey_id toggleHotkey = 0;
|
||||
obs_hotkey_id startHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
obs_hotkey_id stopHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
obs_hotkey_id toggleHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
bool saveWindowGeo = false;
|
||||
QPoint windowPos = {};
|
||||
@@ -203,6 +203,7 @@ struct SwitcherData {
|
||||
void writeSceneInfoToFile();
|
||||
void writeToStatusFile(const QString &msg);
|
||||
|
||||
void setPreconditions();
|
||||
bool checkForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||
int &linger, bool &setPreviousSceneAsMatch,
|
||||
bool ¯oMatch);
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <unordered_map>
|
||||
#include "scene-group.hpp"
|
||||
|
||||
class SceneSelection;
|
||||
|
||||
bool WeakSourceValid(obs_weak_source_t *ws);
|
||||
std::string GetWeakSourceName(obs_weak_source_t *weak_source);
|
||||
OBSWeakSource GetWeakSourceByName(const char *name);
|
||||
@@ -22,7 +24,14 @@ OBSWeakSource GetWeakFilterByName(OBSWeakSource source, const char *name);
|
||||
OBSWeakSource GetWeakFilterByQString(OBSWeakSource source, const QString &name);
|
||||
bool compareIgnoringLineEnding(QString &s1, QString &s2);
|
||||
std::string getSourceSettings(OBSWeakSource ws);
|
||||
void setSourceSettings(obs_source_t *s, const std::string &settings);
|
||||
bool compareSourceSettings(const OBSWeakSource &source,
|
||||
const std::string &settings, bool regex);
|
||||
std::vector<obs_scene_item *> getSceneItemsWithName(OBSScene scene,
|
||||
std::string &name);
|
||||
std::string getDataFilePath(const std::string &file);
|
||||
QString fromatJsonString(std::string);
|
||||
QString fromatJsonString(const char *);
|
||||
|
||||
/**
|
||||
* Populate layout with labels and widgets based on provided text
|
||||
@@ -57,7 +66,14 @@ void populateMediaSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateProcessSelection(QComboBox *sel, bool addSelect = true);
|
||||
void populateSourceSelection(QComboBox *list, bool addSelect = true);
|
||||
void populateSceneSelection(QComboBox *sel, bool addPrevious = false,
|
||||
bool addCurrent = false, bool addAny = false,
|
||||
bool addSceneGroup = false,
|
||||
std::deque<SceneGroup> *sceneGroups = nullptr,
|
||||
bool addSelect = true, std::string selectText = "",
|
||||
bool selectable = false);
|
||||
void populateSourcesWithFilterSelection(QComboBox *list);
|
||||
void populateFilterSelection(QComboBox *list,
|
||||
OBSWeakSource weakSource = nullptr);
|
||||
void populateSceneItemSelection(QComboBox *list,
|
||||
OBSWeakSource sceneWeakSource = nullptr);
|
||||
void populateSceneItemSelection(QComboBox *list, SceneSelection &s);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "headers/hotkey.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include <obs-module.h>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
void startHotkeyFunc(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
||||
bool pressed)
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include "../headers/hotkey.hpp"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
#undef Bool
|
||||
#undef CursorShape
|
||||
#undef Expose
|
||||
@@ -15,11 +19,18 @@
|
||||
#undef Unsorted
|
||||
#include <util/platform.h>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
#include <QLibrary>
|
||||
|
||||
static Display *xdisplay = 0;
|
||||
|
||||
static QLibrary *libXtstHandle = nullptr;
|
||||
typedef int (*keyPressFunc)(Display *, unsigned int, bool, unsigned long);
|
||||
static keyPressFunc pressFunc = nullptr;
|
||||
bool canSimulateKeyPresses = false;
|
||||
|
||||
Display *disp()
|
||||
{
|
||||
if (!xdisplay)
|
||||
@@ -242,14 +253,13 @@ std::pair<int, int> getCursorPos()
|
||||
int win_y;
|
||||
unsigned int mask;
|
||||
|
||||
dpy = XOpenDisplay(NULL);
|
||||
dpy = disp();
|
||||
root = XDefaultRootWindow(dpy);
|
||||
|
||||
if (XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y,
|
||||
&win_x, &win_y, &mask)) {
|
||||
pos = std::pair<int, int>(root_x, root_y);
|
||||
}
|
||||
XCloseDisplay(dpy);
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -382,14 +392,186 @@ int secondsSinceLastInput()
|
||||
|
||||
mit_info = XScreenSaverAllocInfo();
|
||||
|
||||
if ((display = XOpenDisplay(NULL)) == NULL) {
|
||||
return (-1);
|
||||
if ((display = disp()) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
screen = DefaultScreen(display);
|
||||
XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info);
|
||||
idle_time = (mit_info->idle) / 1000;
|
||||
XFree(mit_info);
|
||||
XCloseDisplay(display);
|
||||
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
static std::unordered_map<HotkeyType, long> keyTable = {
|
||||
// Chars
|
||||
{HotkeyType::Key_A, XK_A},
|
||||
{HotkeyType::Key_B, XK_B},
|
||||
{HotkeyType::Key_C, XK_C},
|
||||
{HotkeyType::Key_D, XK_D},
|
||||
{HotkeyType::Key_E, XK_E},
|
||||
{HotkeyType::Key_F, XK_F},
|
||||
{HotkeyType::Key_G, XK_G},
|
||||
{HotkeyType::Key_H, XK_H},
|
||||
{HotkeyType::Key_I, XK_I},
|
||||
{HotkeyType::Key_J, XK_J},
|
||||
{HotkeyType::Key_K, XK_K},
|
||||
{HotkeyType::Key_L, XK_L},
|
||||
{HotkeyType::Key_M, XK_M},
|
||||
{HotkeyType::Key_N, XK_N},
|
||||
{HotkeyType::Key_O, XK_O},
|
||||
{HotkeyType::Key_P, XK_P},
|
||||
{HotkeyType::Key_Q, XK_Q},
|
||||
{HotkeyType::Key_R, XK_R},
|
||||
{HotkeyType::Key_S, XK_S},
|
||||
{HotkeyType::Key_T, XK_T},
|
||||
{HotkeyType::Key_U, XK_U},
|
||||
{HotkeyType::Key_V, XK_V},
|
||||
{HotkeyType::Key_W, XK_W},
|
||||
{HotkeyType::Key_X, XK_X},
|
||||
{HotkeyType::Key_Y, XK_Y},
|
||||
{HotkeyType::Key_Z, XK_Z},
|
||||
|
||||
// Numbers
|
||||
{HotkeyType::Key_0, XK_0},
|
||||
{HotkeyType::Key_1, XK_1},
|
||||
{HotkeyType::Key_2, XK_2},
|
||||
{HotkeyType::Key_3, XK_3},
|
||||
{HotkeyType::Key_4, XK_4},
|
||||
{HotkeyType::Key_5, XK_5},
|
||||
{HotkeyType::Key_6, XK_6},
|
||||
{HotkeyType::Key_7, XK_7},
|
||||
{HotkeyType::Key_8, XK_8},
|
||||
{HotkeyType::Key_9, XK_9},
|
||||
|
||||
{HotkeyType::Key_F1, XK_F1},
|
||||
{HotkeyType::Key_F2, XK_F2},
|
||||
{HotkeyType::Key_F3, XK_F3},
|
||||
{HotkeyType::Key_F4, XK_F4},
|
||||
{HotkeyType::Key_F5, XK_F5},
|
||||
{HotkeyType::Key_F6, XK_F6},
|
||||
{HotkeyType::Key_F7, XK_F7},
|
||||
{HotkeyType::Key_F8, XK_F8},
|
||||
{HotkeyType::Key_F9, XK_F9},
|
||||
{HotkeyType::Key_F10, XK_F10},
|
||||
{HotkeyType::Key_F11, XK_F11},
|
||||
{HotkeyType::Key_F12, XK_F12},
|
||||
{HotkeyType::Key_F13, XK_F13},
|
||||
{HotkeyType::Key_F14, XK_F14},
|
||||
{HotkeyType::Key_F15, XK_F15},
|
||||
{HotkeyType::Key_F16, XK_F16},
|
||||
{HotkeyType::Key_F17, XK_F17},
|
||||
{HotkeyType::Key_F18, XK_F18},
|
||||
{HotkeyType::Key_F19, XK_F19},
|
||||
{HotkeyType::Key_F20, XK_F20},
|
||||
{HotkeyType::Key_F21, XK_F21},
|
||||
{HotkeyType::Key_F22, XK_F22},
|
||||
{HotkeyType::Key_F23, XK_F23},
|
||||
{HotkeyType::Key_F24, XK_F24},
|
||||
|
||||
{HotkeyType::Key_Escape, XK_Escape},
|
||||
{HotkeyType::Key_Space, XK_space},
|
||||
{HotkeyType::Key_Return, XK_Return},
|
||||
{HotkeyType::Key_Backspace, XK_BackSpace},
|
||||
{HotkeyType::Key_Tab, XK_Tab},
|
||||
|
||||
{HotkeyType::Key_Shift_L, XK_Shift_L},
|
||||
{HotkeyType::Key_Shift_R, XK_Shift_R},
|
||||
{HotkeyType::Key_Control_L, XK_Control_L},
|
||||
{HotkeyType::Key_Control_R, XK_Control_R},
|
||||
{HotkeyType::Key_Alt_L, XK_Alt_L},
|
||||
{HotkeyType::Key_Alt_R, XK_Alt_R},
|
||||
{HotkeyType::Key_Win_L, XK_Super_L},
|
||||
{HotkeyType::Key_Win_R, XK_Super_R},
|
||||
{HotkeyType::Key_Apps, XK_Hyper_L},
|
||||
|
||||
{HotkeyType::Key_CapsLock, XK_Caps_Lock},
|
||||
{HotkeyType::Key_NumLock, XK_Num_Lock},
|
||||
{HotkeyType::Key_ScrollLock, XK_Scroll_Lock},
|
||||
|
||||
{HotkeyType::Key_PrintScreen, XK_Print},
|
||||
{HotkeyType::Key_Pause, XK_Pause},
|
||||
|
||||
{HotkeyType::Key_Insert, XK_Insert},
|
||||
{HotkeyType::Key_Delete, XK_Delete},
|
||||
{HotkeyType::Key_PageUP, XK_Page_Up},
|
||||
{HotkeyType::Key_PageDown, XK_Page_Down},
|
||||
{HotkeyType::Key_Home, XK_Home},
|
||||
{HotkeyType::Key_End, XK_End},
|
||||
|
||||
{HotkeyType::Key_Left, XK_Left},
|
||||
{HotkeyType::Key_Up, XK_Up},
|
||||
{HotkeyType::Key_Right, XK_Right},
|
||||
{HotkeyType::Key_Down, XK_Down},
|
||||
|
||||
{HotkeyType::Key_Numpad0, XK_KP_0},
|
||||
{HotkeyType::Key_Numpad1, XK_KP_1},
|
||||
{HotkeyType::Key_Numpad2, XK_KP_2},
|
||||
{HotkeyType::Key_Numpad3, XK_KP_3},
|
||||
{HotkeyType::Key_Numpad4, XK_KP_4},
|
||||
{HotkeyType::Key_Numpad5, XK_KP_5},
|
||||
{HotkeyType::Key_Numpad6, XK_KP_6},
|
||||
{HotkeyType::Key_Numpad7, XK_KP_7},
|
||||
{HotkeyType::Key_Numpad8, XK_KP_8},
|
||||
{HotkeyType::Key_Numpad9, XK_KP_9},
|
||||
|
||||
{HotkeyType::Key_NumpadAdd, XK_KP_Add},
|
||||
{HotkeyType::Key_NumpadSubtract, XK_KP_Subtract},
|
||||
{HotkeyType::Key_NumpadMultiply, XK_KP_Multiply},
|
||||
{HotkeyType::Key_NumpadDivide, XK_KP_Divide},
|
||||
{HotkeyType::Key_NumpadDecimal, XK_KP_Decimal},
|
||||
{HotkeyType::Key_NumpadEnter, XK_KP_Enter},
|
||||
};
|
||||
|
||||
void PressKeys(const std::vector<HotkeyType> keys)
|
||||
{
|
||||
if (!canSimulateKeyPresses) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display *display = disp();
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
// Press keys
|
||||
for (auto &key : keys) {
|
||||
auto it = keyTable.find(key);
|
||||
if (it == keyTable.end()) {
|
||||
continue;
|
||||
}
|
||||
pressFunc(display, XKeysymToKeycode(display, it->second), true,
|
||||
CurrentTime);
|
||||
}
|
||||
XFlush(display);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
|
||||
// Release keys
|
||||
for (auto &key : keys) {
|
||||
auto it = keyTable.find(key);
|
||||
if (it == keyTable.end()) {
|
||||
continue;
|
||||
}
|
||||
pressFunc(display, XKeysymToKeycode(display, it->second), false,
|
||||
CurrentTime);
|
||||
}
|
||||
|
||||
XFlush(display);
|
||||
}
|
||||
|
||||
void PlatformInit()
|
||||
{
|
||||
libXtstHandle = new QLibrary("libXtst.so", nullptr);
|
||||
pressFunc = (keyPressFunc)libXtstHandle->resolve("XTestFakeKeyEvent");
|
||||
int _;
|
||||
canSimulateKeyPresses = pressFunc &&
|
||||
!XQueryExtension(disp(), "XTEST", &_, &_, &_);
|
||||
}
|
||||
|
||||
void PlatformCleanup()
|
||||
{
|
||||
delete libXtstHandle;
|
||||
libXtstHandle = nullptr;
|
||||
|
||||
cleanupDisplay();
|
||||
}
|
||||
|
||||
@@ -75,6 +75,14 @@ bool MacroActionAudio::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionAudio::GetShortDesc()
|
||||
{
|
||||
if (_audioSource) {
|
||||
return GetWeakSourceName(_audioSource);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -167,6 +175,8 @@ void MacroActionAudioEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_audioSource = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionAudioEdit::ActionChanged(int value)
|
||||
|
||||
@@ -64,14 +64,32 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||
{
|
||||
_actionSelection = new QComboBox();
|
||||
_section = new Section(300);
|
||||
_headerInfo = new QLabel();
|
||||
|
||||
QWidget::connect(_actionSelection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(ActionSelectionChanged(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this,
|
||||
SIGNAL(MacroAdded(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
||||
SIGNAL(MacroRemoved(const QString &)));
|
||||
QWidget::connect(parent,
|
||||
SIGNAL(MacroRenamed(const QString &, const QString)),
|
||||
this,
|
||||
SIGNAL(MacroRenamed(const QString &, const QString)));
|
||||
QWidget::connect(parent, SIGNAL(SceneGroupAdded(const QString &)), this,
|
||||
SIGNAL(SceneGroupAdded(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(SceneGroupRemoved(const QString &)),
|
||||
this, SIGNAL(SceneGroupRemoved(const QString &)));
|
||||
QWidget::connect(
|
||||
parent,
|
||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)), this,
|
||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)));
|
||||
|
||||
populateActionSelection(_actionSelection);
|
||||
|
||||
_section->AddHeaderWidget(_actionSelection);
|
||||
_section->AddHeaderWidget(_headerInfo);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(_section);
|
||||
@@ -90,12 +108,14 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
||||
}
|
||||
|
||||
std::string id = MacroActionFactory::GetIdByName(text);
|
||||
HeaderInfoChanged("");
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->reset();
|
||||
*_entryData = MacroActionFactory::Create(id);
|
||||
auto widget =
|
||||
MacroActionFactory::CreateWidget(id, window(), *_entryData);
|
||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
_section->SetContent(widget, false);
|
||||
}
|
||||
|
||||
@@ -103,11 +123,20 @@ void MacroActionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
||||
{
|
||||
_actionSelection->setCurrentText(
|
||||
obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
|
||||
auto widget =
|
||||
MacroActionFactory::CreateWidget(id, window(), *_entryData);
|
||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
HeaderInfoChanged(
|
||||
QString::fromStdString((*_entryData)->GetShortDesc()));
|
||||
_section->SetContent(widget, collapse);
|
||||
}
|
||||
|
||||
void MacroActionEdit::HeaderInfoChanged(const QString &text)
|
||||
{
|
||||
_headerInfo->setVisible(!text.isEmpty());
|
||||
_headerInfo->setText(text);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
|
||||
187
src/macro-action-file.cpp
Normal file
187
src/macro-action-file.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
#include "headers/macro-action-file.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QFileDialog>
|
||||
|
||||
const std::string MacroActionFile::id = "file";
|
||||
|
||||
bool MacroActionFile::_registered = MacroActionFactory::Register(
|
||||
MacroActionFile::id,
|
||||
{MacroActionFile::Create, MacroActionFileEdit::Create,
|
||||
"AdvSceneSwitcher.action.file"});
|
||||
|
||||
const static std::map<FileAction, std::string> actionTypes = {
|
||||
{FileAction::WRITE, "AdvSceneSwitcher.action.file.type.write"},
|
||||
{FileAction::APPEND, "AdvSceneSwitcher.action.file.type.append"},
|
||||
};
|
||||
|
||||
bool MacroActionFile::PerformAction()
|
||||
{
|
||||
QString path = QString::fromStdString(_file);
|
||||
QFile file(path);
|
||||
bool open = false;
|
||||
switch (_action) {
|
||||
case FileAction::WRITE:
|
||||
open = file.open(QIODevice::WriteOnly);
|
||||
break;
|
||||
case FileAction::APPEND:
|
||||
open = file.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (open) {
|
||||
QTextStream out(&file);
|
||||
out << QString::fromStdString(_text);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionFile::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO, "performed action \"%s\" for file \"%s\"",
|
||||
it->second.c_str(), _file.c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown file action %d",
|
||||
static_cast<int>(_action));
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionFile::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_string(obj, "file", _file.c_str());
|
||||
obs_data_set_string(obj, "text", _text.c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionFile::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_file = obs_data_get_string(obj, "file");
|
||||
_text = obs_data_get_string(obj, "text");
|
||||
_action = static_cast<FileAction>(obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionFile::GetShortDesc()
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionFileEdit::MacroActionFileEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionFile> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_filePath = new QLineEdit();
|
||||
_browseButton =
|
||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
||||
_text = new QPlainTextEdit();
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
||||
SLOT(FilePathChanged()));
|
||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
||||
SLOT(BrowseButtonClicked()));
|
||||
QWidget::connect(_text, SIGNAL(textChanged()), this,
|
||||
SLOT(TextChanged()));
|
||||
;
|
||||
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{filePath}}", _filePath},
|
||||
{"{{browseButton}}", _browseButton},
|
||||
{"{{matchText}}", _text},
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.file.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_text);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_filePath->setText(QString::fromStdString(_entryData->_file));
|
||||
_text->setPlainText(QString::fromStdString(_entryData->_text));
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::FilePathChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_file = _filePath->text().toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::BrowseButtonClicked()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.selectWrite")),
|
||||
QDir::currentPath(),
|
||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.anyFileType")));
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_filePath->setText(path);
|
||||
FilePathChanged();
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::TextChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_text = _text->toPlainText().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionFileEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<FileAction>(value);
|
||||
}
|
||||
@@ -12,6 +12,8 @@ bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
||||
const static std::map<FilterAction, std::string> actionTypes = {
|
||||
{FilterAction::ENABLE, "AdvSceneSwitcher.action.filter.type.enable"},
|
||||
{FilterAction::DISABLE, "AdvSceneSwitcher.action.filter.type.disable"},
|
||||
{FilterAction::SETTINGS,
|
||||
"AdvSceneSwitcher.action.filter.type.settings"},
|
||||
};
|
||||
|
||||
bool MacroActionFilter::PerformAction()
|
||||
@@ -24,6 +26,9 @@ bool MacroActionFilter::PerformAction()
|
||||
case FilterAction::DISABLE:
|
||||
obs_source_set_enabled(s, false);
|
||||
break;
|
||||
case FilterAction::SETTINGS:
|
||||
setSourceSettings(s, _settings);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -51,6 +56,7 @@ bool MacroActionFilter::Save(obs_data_t *obj)
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_string(obj, "filter", GetWeakSourceName(_filter).c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_string(obj, "settings", _settings.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,9 +68,19 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
const char *filterName = obs_data_get_string(obj, "filter");
|
||||
_filter = GetWeakFilterByQString(_source, filterName);
|
||||
_action = static_cast<FilterAction>(obs_data_get_int(obj, "action"));
|
||||
_settings = obs_data_get_string(obj, "settings");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionFilter::GetShortDesc()
|
||||
{
|
||||
if (_filter && _source) {
|
||||
return GetWeakSourceName(_source) + " - " +
|
||||
GetWeakSourceName(_filter);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -72,56 +88,6 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateFilters(QComboBox *list,
|
||||
OBSWeakSource weakSource = nullptr)
|
||||
{
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *ptr) {
|
||||
QComboBox *list = reinterpret_cast<QComboBox *>(ptr);
|
||||
auto name = obs_source_get_name(filter);
|
||||
list->addItem(name);
|
||||
};
|
||||
|
||||
auto s = obs_weak_source_get_source(weakSource);
|
||||
obs_source_enum_filters(s, enumFilters, list);
|
||||
list->model()->sort(0);
|
||||
addSelectionEntry(list,
|
||||
obs_module_text("AdvSceneSwitcher.selectFilter"));
|
||||
obs_source_release(s);
|
||||
list->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
static inline void hasFilterEnum(obs_source_t *, obs_source_t *filter,
|
||||
void *ptr)
|
||||
{
|
||||
if (!filter) {
|
||||
return;
|
||||
}
|
||||
bool *hasFilter = reinterpret_cast<bool *>(ptr);
|
||||
*hasFilter = true;
|
||||
}
|
||||
|
||||
static inline void populateSourcesWithFilter(QComboBox *list)
|
||||
{
|
||||
auto enumSourcesWithFilters = [](void *param, obs_source_t *source) {
|
||||
if (!source) {
|
||||
return true;
|
||||
}
|
||||
QComboBox *list = reinterpret_cast<QComboBox *>(param);
|
||||
bool hasFilter = false;
|
||||
obs_source_enum_filters(source, hasFilterEnum, &hasFilter);
|
||||
if (hasFilter) {
|
||||
list->addItem(obs_source_get_name(source));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
obs_enum_sources(enumSourcesWithFilters, list);
|
||||
obs_enum_scenes(enumSourcesWithFilters, list);
|
||||
list->model()->sort(0);
|
||||
addSelectionEntry(list,
|
||||
obs_module_text("AdvSceneSwitcher.selectSource"));
|
||||
list->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -129,9 +95,12 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
_sources = new QComboBox();
|
||||
_filters = new QComboBox();
|
||||
_actions = new QComboBox();
|
||||
_getSettings = new QPushButton(
|
||||
obs_module_text("AdvSceneSwitcher.action.filter.getSettings"));
|
||||
_settings = new QPlainTextEdit();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
populateSourcesWithFilter(_sources);
|
||||
populateSourcesWithFilterSelection(_sources);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
@@ -139,15 +108,29 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(FilterChanged(const QString &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sources}}", _sources},
|
||||
{"{{filters}}", _filters},
|
||||
{"{{actions}}", _actions},
|
||||
{"{{sources}}", _sources}, {"{{filters}}", _filters},
|
||||
{"{{actions}}", _actions}, {"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_settings);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -164,9 +147,11 @@ void MacroActionFilterEdit::UpdateEntryData()
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
populateFilters(_filters, _entryData->_source);
|
||||
populateFilterSelection(_filters, _entryData->_source);
|
||||
_filters->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_filter).c_str());
|
||||
_settings->setPlainText(QString::fromStdString(_entryData->_settings));
|
||||
SetWidgetVisibility(_entryData->_action == FilterAction::SETTINGS);
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SourceChanged(const QString &text)
|
||||
@@ -179,7 +164,7 @@ void MacroActionFilterEdit::SourceChanged(const QString &text)
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
}
|
||||
_filters->clear();
|
||||
populateFilters(_filters, _entryData->_source);
|
||||
populateFilterSelection(_filters, _entryData->_source);
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::FilterChanged(const QString &text)
|
||||
@@ -190,6 +175,8 @@ void MacroActionFilterEdit::FilterChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_filter = GetWeakFilterByQString(_entryData->_source, text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::ActionChanged(int value)
|
||||
@@ -200,4 +187,33 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<FilterAction>(value);
|
||||
SetWidgetVisibility(_entryData->_action == FilterAction::SETTINGS);
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_source ||
|
||||
!_entryData->_filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
_settings->setPlainText(
|
||||
fromatJsonString(getSourceSettings(_entryData->_filter)));
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SettingsChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_settings = _settings->toPlainText().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SetWidgetVisibility(bool showSettings)
|
||||
{
|
||||
_settings->setVisible(showSettings);
|
||||
_getSettings->setVisible(showSettings);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
377
src/macro-action-hotkey.cpp
Normal file
377
src/macro-action-hotkey.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
#include "headers/macro-action-hotkey.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionHotkey::id = "hotkey";
|
||||
|
||||
// TODO:
|
||||
// I can't seem to get this to work so drop support for this functionality
|
||||
// on MacOS
|
||||
#if !__APPLE__
|
||||
bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
||||
MacroActionHotkey::id,
|
||||
{MacroActionHotkey::Create, MacroActionHotkeyEdit::Create,
|
||||
"AdvSceneSwitcher.action.hotkey"});
|
||||
#endif
|
||||
|
||||
bool MacroActionHotkey::PerformAction()
|
||||
{
|
||||
std::vector<HotkeyType> keys;
|
||||
if (_leftShift) {
|
||||
keys.push_back(HotkeyType::Key_Shift_L);
|
||||
}
|
||||
if (_rightShift) {
|
||||
keys.push_back(HotkeyType::Key_Shift_R);
|
||||
}
|
||||
if (_leftCtrl) {
|
||||
keys.push_back(HotkeyType::Key_Control_L);
|
||||
}
|
||||
if (_rightCtrl) {
|
||||
keys.push_back(HotkeyType::Key_Control_R);
|
||||
}
|
||||
if (_leftAlt) {
|
||||
keys.push_back(HotkeyType::Key_Alt_L);
|
||||
}
|
||||
if (_rightAlt) {
|
||||
keys.push_back(HotkeyType::Key_Alt_R);
|
||||
}
|
||||
if (_key != HotkeyType::Key_NoKey) {
|
||||
keys.push_back(_key);
|
||||
}
|
||||
|
||||
if (!keys.empty()) {
|
||||
std::thread t([keys]() { PressKeys(keys); });
|
||||
t.detach();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionHotkey::LogAction()
|
||||
{
|
||||
vblog(LOG_INFO, "sent hotkey");
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "key", static_cast<int>(_key));
|
||||
obs_data_set_bool(obj, "left_shift", _leftShift);
|
||||
obs_data_set_bool(obj, "right_shift", _rightShift);
|
||||
obs_data_set_bool(obj, "left_ctrl", _leftCtrl);
|
||||
obs_data_set_bool(obj, "right_ctrl", _rightCtrl);
|
||||
obs_data_set_bool(obj, "left_alt", _leftAlt);
|
||||
obs_data_set_bool(obj, "right_alt", _rightAlt);
|
||||
obs_data_set_bool(obj, "left_meta", _leftMeta);
|
||||
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_key = static_cast<HotkeyType>(obs_data_get_int(obj, "key"));
|
||||
_leftShift = obs_data_get_bool(obj, "left_shift");
|
||||
_rightShift = obs_data_get_bool(obj, "right_shift");
|
||||
_leftCtrl = obs_data_get_bool(obj, "left_ctrl");
|
||||
_rightCtrl = obs_data_get_bool(obj, "right_ctrl");
|
||||
_leftAlt = obs_data_get_bool(obj, "left_alt");
|
||||
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
||||
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
||||
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateKeySelection(QComboBox *list)
|
||||
{
|
||||
list->addItem("No key");
|
||||
list->addItem("A");
|
||||
list->addItem("B");
|
||||
list->addItem("C");
|
||||
list->addItem("D");
|
||||
list->addItem("E");
|
||||
list->addItem("F");
|
||||
list->addItem("G");
|
||||
list->addItem("H");
|
||||
list->addItem("I");
|
||||
list->addItem("J");
|
||||
list->addItem("K");
|
||||
list->addItem("L");
|
||||
list->addItem("M");
|
||||
list->addItem("N");
|
||||
list->addItem("O");
|
||||
list->addItem("P");
|
||||
list->addItem("Q");
|
||||
list->addItem("R");
|
||||
list->addItem("S");
|
||||
list->addItem("T");
|
||||
list->addItem("U");
|
||||
list->addItem("V");
|
||||
list->addItem("W");
|
||||
list->addItem("X");
|
||||
list->addItem("Y");
|
||||
list->addItem("Z");
|
||||
list->addItem("0");
|
||||
list->addItem("1");
|
||||
list->addItem("2");
|
||||
list->addItem("3");
|
||||
list->addItem("4");
|
||||
list->addItem("5");
|
||||
list->addItem("6");
|
||||
list->addItem("7");
|
||||
list->addItem("8");
|
||||
list->addItem("9");
|
||||
list->addItem("F1");
|
||||
list->addItem("F2");
|
||||
list->addItem("F3");
|
||||
list->addItem("F4");
|
||||
list->addItem("F5");
|
||||
list->addItem("F6");
|
||||
list->addItem("F7");
|
||||
list->addItem("F8");
|
||||
list->addItem("F9");
|
||||
list->addItem("F10");
|
||||
list->addItem("F11");
|
||||
list->addItem("F12");
|
||||
list->addItem("F13");
|
||||
list->addItem("F14");
|
||||
list->addItem("F15");
|
||||
list->addItem("F16");
|
||||
list->addItem("F17");
|
||||
list->addItem("F18");
|
||||
list->addItem("F19");
|
||||
list->addItem("F20");
|
||||
list->addItem("F21");
|
||||
list->addItem("F22");
|
||||
list->addItem("F23");
|
||||
list->addItem("F24");
|
||||
list->addItem("Escape");
|
||||
list->addItem("Space");
|
||||
list->addItem("Return");
|
||||
list->addItem("Backspace");
|
||||
list->addItem("Tab");
|
||||
list->addItem("Shift_L");
|
||||
list->addItem("Shift_R");
|
||||
list->addItem("Control_L");
|
||||
list->addItem("Control_R");
|
||||
list->addItem("Alt_L");
|
||||
list->addItem("Alt_R");
|
||||
list->addItem("Win_L");
|
||||
list->addItem("Win_R");
|
||||
list->addItem("Apps");
|
||||
list->addItem("CapsLock");
|
||||
list->addItem("NumLock");
|
||||
list->addItem("ScrollLock");
|
||||
list->addItem("PrintScreen");
|
||||
list->addItem("Pause");
|
||||
list->addItem("Insert");
|
||||
list->addItem("Delete");
|
||||
list->addItem("PageUP");
|
||||
list->addItem("PageDown");
|
||||
list->addItem("Home");
|
||||
list->addItem("End");
|
||||
list->addItem("Left");
|
||||
list->addItem("Right");
|
||||
list->addItem("Up");
|
||||
list->addItem("Down");
|
||||
list->addItem("Numpad0");
|
||||
list->addItem("Numpad1");
|
||||
list->addItem("Numpad2");
|
||||
list->addItem("Numpad3");
|
||||
list->addItem("Numpad4");
|
||||
list->addItem("Numpad5");
|
||||
list->addItem("Numpad6");
|
||||
list->addItem("Numpad7");
|
||||
list->addItem("Numpad8");
|
||||
list->addItem("Numpad9");
|
||||
list->addItem("NumpadAdd");
|
||||
list->addItem("NumpadSubtract");
|
||||
list->addItem("NumpadMultiply");
|
||||
list->addItem("NumpadDivide");
|
||||
list->addItem("NumpadDecimal");
|
||||
list->addItem("NumpadEnter");
|
||||
}
|
||||
|
||||
MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionHotkey> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_keys = new QComboBox();
|
||||
_leftShift = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"));
|
||||
_rightShift = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightShift"));
|
||||
_leftCtrl = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftCtrl"));
|
||||
_rightCtrl = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightCtrl"));
|
||||
_leftAlt = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftAlt"));
|
||||
_rightAlt = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightAlt"));
|
||||
_leftMeta = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"));
|
||||
_rightMeta = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"));
|
||||
|
||||
populateKeySelection(_keys);
|
||||
|
||||
QWidget::connect(_keys, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(KeyChanged(int)));
|
||||
QWidget::connect(_leftShift, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LShiftChanged(int)));
|
||||
QWidget::connect(_rightShift, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RShiftChanged(int)));
|
||||
QWidget::connect(_leftCtrl, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LCtrlChanged(int)));
|
||||
QWidget::connect(_rightCtrl, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RCtrlChanged(int)));
|
||||
QWidget::connect(_leftAlt, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LAltChanged(int)));
|
||||
QWidget::connect(_rightAlt, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RAltChanged(int)));
|
||||
QWidget::connect(_leftMeta, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(LMetaChanged(int)));
|
||||
QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RMetaChanged(int)));
|
||||
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{keys}}", _keys},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
line2Layout->addWidget(_leftShift);
|
||||
line2Layout->addWidget(_rightShift);
|
||||
line2Layout->addWidget(_leftCtrl);
|
||||
line2Layout->addWidget(_rightCtrl);
|
||||
line2Layout->addWidget(_leftAlt);
|
||||
line2Layout->addWidget(_rightAlt);
|
||||
line2Layout->addWidget(_leftMeta);
|
||||
line2Layout->addWidget(_rightMeta);
|
||||
line2Layout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
|
||||
if (!canSimulateKeyPresses) {
|
||||
mainLayout->addWidget(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.hotkey.disabled")));
|
||||
}
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_keys->setCurrentIndex(static_cast<int>(_entryData->_key));
|
||||
_leftShift->setChecked(_entryData->_leftShift);
|
||||
_rightShift->setChecked(_entryData->_rightShift);
|
||||
_leftCtrl->setChecked(_entryData->_leftCtrl);
|
||||
_rightCtrl->setChecked(_entryData->_rightCtrl);
|
||||
_leftAlt->setChecked(_entryData->_leftAlt);
|
||||
_rightAlt->setChecked(_entryData->_rightAlt);
|
||||
_leftMeta->setChecked(_entryData->_leftMeta);
|
||||
_rightMeta->setChecked(_entryData->_rightMeta);
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LShiftChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftShift = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RShiftChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightShift = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LCtrlChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftCtrl = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RCtrlChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightCtrl = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LAltChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftAlt = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RAltChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightAlt = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LMetaChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_leftMeta = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::RMetaChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_rightMeta = state;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::KeyChanged(int key)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_key = static_cast<HotkeyType>(key);
|
||||
}
|
||||
@@ -77,6 +77,14 @@ bool MacroActionMacro::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionMacro::GetShortDesc()
|
||||
{
|
||||
if (_macro.get()) {
|
||||
return _macro->Name();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -131,6 +139,8 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macro.UpdateRef(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ActionChanged(int value)
|
||||
|
||||
@@ -84,6 +84,14 @@ bool MacroActionMedia::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionMedia::GetShortDesc()
|
||||
{
|
||||
if (_mediaSource) {
|
||||
return GetWeakSourceName(_mediaSource);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -140,6 +148,8 @@ void MacroActionMediaEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_mediaSource = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::ActionChanged(int value)
|
||||
|
||||
@@ -14,6 +14,17 @@ bool MacroActionPluginState::_registered = MacroActionFactory::Register(
|
||||
const static std::map<PluginStateAction, std::string> actionTypes = {
|
||||
{PluginStateAction::STOP,
|
||||
"AdvSceneSwitcher.action.pluginState.type.stop"},
|
||||
{PluginStateAction::NO_MATCH_BEHAVIOUR,
|
||||
"AdvSceneSwitcher.action.pluginState.type.noMatch"},
|
||||
};
|
||||
|
||||
const static std::map<NoMatch, std::string> noMatchValues = {
|
||||
{NO_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.dontSwitch"},
|
||||
{SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchTo"},
|
||||
{RANDOM_SWITCH,
|
||||
"AdvSceneSwitcher.generalTab.generalBehavior.onNoMet.switchToRandom"},
|
||||
};
|
||||
|
||||
void stopPlugin()
|
||||
@@ -22,12 +33,23 @@ void stopPlugin()
|
||||
t.detach();
|
||||
}
|
||||
|
||||
void setNoMatchBehaviour(int value, OBSWeakSource &scene)
|
||||
{
|
||||
switcher->switchIfNotMatching = static_cast<NoMatch>(value);
|
||||
if (switcher->switchIfNotMatching == SWITCH) {
|
||||
switcher->nonMatchingScene = scene;
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionPluginState::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
case PluginStateAction::STOP:
|
||||
stopPlugin();
|
||||
break;
|
||||
case PluginStateAction::NO_MATCH_BEHAVIOUR:
|
||||
setNoMatchBehaviour(_value, _scene);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -36,10 +58,9 @@ bool MacroActionPluginState::PerformAction()
|
||||
|
||||
void MacroActionPluginState::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
switch (_action) {
|
||||
case PluginStateAction::STOP:
|
||||
blog(LOG_INFO, "stop() called by macro", it->second.c_str());
|
||||
blog(LOG_INFO, "stop() called by macro");
|
||||
break;
|
||||
default:
|
||||
blog(LOG_WARNING, "ignored unknown pluginState action %d",
|
||||
@@ -52,6 +73,8 @@ bool MacroActionPluginState::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "value", _value);
|
||||
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -60,6 +83,9 @@ bool MacroActionPluginState::Load(obs_data_t *obj)
|
||||
MacroAction::Load(obj);
|
||||
_action =
|
||||
static_cast<PluginStateAction>(obs_data_get_int(obj, "action"));
|
||||
_value = obs_data_get_int(obj, "value");
|
||||
const char *sceneName = obs_data_get_string(obj, "scene");
|
||||
_scene = GetWeakSourceByName(sceneName);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -70,20 +96,39 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateValueSelection(QComboBox *list,
|
||||
PluginStateAction action)
|
||||
{
|
||||
if (action == PluginStateAction::NO_MATCH_BEHAVIOUR) {
|
||||
for (auto entry : noMatchValues) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionPluginStateEdit::MacroActionPluginStateEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionPluginState> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_actions = new QComboBox();
|
||||
_values = new QComboBox();
|
||||
_scenes = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
populateSceneSelection(_scenes);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_values, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ValueChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SceneChanged(const QString &)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
{"{{values}}", _values},
|
||||
{"{{scenes}}", _scenes},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.pluginState.entry"),
|
||||
@@ -101,6 +146,10 @@ void MacroActionPluginStateEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
populateValueSelection(_values, _entryData->_action);
|
||||
_values->setCurrentIndex(_entryData->_value);
|
||||
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
|
||||
SetWidgetVisibility(_entryData->_action, _entryData->_value);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::ActionChanged(int value)
|
||||
@@ -109,6 +158,46 @@ void MacroActionPluginStateEdit::ActionChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<PluginStateAction>(value);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<PluginStateAction>(value);
|
||||
SetWidgetVisibility(_entryData->_action, _entryData->_value);
|
||||
}
|
||||
|
||||
_values->clear();
|
||||
populateValueSelection(_values, _entryData->_action);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::ValueChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_value = value;
|
||||
SetWidgetVisibility(_entryData->_action, _entryData->_value);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::SceneChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = GetWeakSourceByQString(text);
|
||||
}
|
||||
|
||||
void MacroActionPluginStateEdit::SetWidgetVisibility(PluginStateAction action,
|
||||
int value)
|
||||
{
|
||||
_values->hide();
|
||||
_scenes->hide();
|
||||
if (action == PluginStateAction::NO_MATCH_BEHAVIOUR) {
|
||||
_values->show();
|
||||
if ((NoMatch)value == SWITCH) {
|
||||
_scenes->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "headers/macro-action-run.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/name-dialog.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
#include <QProcess>
|
||||
@@ -13,7 +14,7 @@ bool MacroActionRun::_registered = MacroActionFactory::Register(
|
||||
|
||||
bool MacroActionRun::PerformAction()
|
||||
{
|
||||
QProcess::startDetached(QString::fromStdString(_path), QStringList());
|
||||
QProcess::startDetached(QString::fromStdString(_path), _args);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,6 +27,16 @@ bool MacroActionRun::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_string(obj, "path", _path.c_str());
|
||||
obs_data_array_t *args = obs_data_array_create();
|
||||
for (auto &arg : _args) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
obs_data_set_string(array_obj, "arg",
|
||||
arg.toStdString().c_str());
|
||||
obs_data_array_push_back(args, array_obj);
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, "args", args);
|
||||
obs_data_array_release(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,9 +44,23 @@ bool MacroActionRun::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_path = obs_data_get_string(obj, "path");
|
||||
obs_data_array_t *args = obs_data_get_array(obj, "args");
|
||||
size_t count = obs_data_array_count(args);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(args, i);
|
||||
_args << QString::fromStdString(
|
||||
obs_data_get_string(array_obj, "arg"));
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionRun::GetShortDesc()
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
MacroActionRunEdit::MacroActionRunEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -43,20 +68,59 @@ MacroActionRunEdit::MacroActionRunEdit(
|
||||
_filePath = new QLineEdit();
|
||||
_browseButton =
|
||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
||||
_browseButton->setStyleSheet("border:1px solid gray;");
|
||||
_argList = new QListWidget();
|
||||
_addArg = new QPushButton();
|
||||
_addArg->setMaximumSize(QSize(22, 22));
|
||||
_addArg->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("addIconSmall")));
|
||||
_removeArg = new QPushButton();
|
||||
_removeArg->setMaximumSize(QSize(22, 22));
|
||||
_removeArg->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||
_argUp = new QPushButton();
|
||||
_argUp->setMaximumSize(QSize(22, 22));
|
||||
_argUp->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
||||
_argDown = new QPushButton();
|
||||
_argDown->setMaximumSize(QSize(22, 22));
|
||||
_argDown->setProperty(
|
||||
"themeID", QVariant(QString::fromUtf8("downArrowIconSmall")));
|
||||
|
||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
||||
SLOT(FilePathChanged()));
|
||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
||||
SLOT(BrowseButtonClicked()));
|
||||
QWidget::connect(_addArg, SIGNAL(clicked()), this, SLOT(AddArg()));
|
||||
QWidget::connect(_removeArg, SIGNAL(clicked()), this,
|
||||
SLOT(RemoveArg()));
|
||||
QWidget::connect(_argUp, SIGNAL(clicked()), this, SLOT(ArgUp()));
|
||||
QWidget::connect(_argDown, SIGNAL(clicked()), this, SLOT(ArgDown()));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
auto *entryLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{filePath}}", _filePath},
|
||||
{"{{browseButton}}", _browseButton},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
auto *argButtonLayout = new QHBoxLayout;
|
||||
argButtonLayout->addWidget(_addArg);
|
||||
argButtonLayout->addWidget(_removeArg);
|
||||
QFrame *line = new QFrame();
|
||||
line->setFrameShape(QFrame::VLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
argButtonLayout->addWidget(line);
|
||||
argButtonLayout->addWidget(_argUp);
|
||||
argButtonLayout->addWidget(_argDown);
|
||||
argButtonLayout->addStretch();
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.run.arguments")));
|
||||
mainLayout->addWidget(_argList);
|
||||
mainLayout->addLayout(argButtonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -70,6 +134,10 @@ void MacroActionRunEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
_filePath->setText(QString::fromStdString(_entryData->_path));
|
||||
for (auto &arg : _entryData->_args) {
|
||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
||||
item->setData(Qt::UserRole, arg);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::FilePathChanged()
|
||||
@@ -80,6 +148,8 @@ void MacroActionRunEdit::FilePathChanged()
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_path = _filePath->text().toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::BrowseButtonClicked()
|
||||
@@ -96,3 +166,77 @@ void MacroActionRunEdit::BrowseButtonClicked()
|
||||
_filePath->setText(path);
|
||||
FilePathChanged();
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::AddArg()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
this,
|
||||
obs_module_text("AdvSceneSwitcher.action.run.addArgument"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.run.addArgumentDescription"),
|
||||
name, "", 170, false);
|
||||
|
||||
if (!accepted || name.empty()) {
|
||||
return;
|
||||
}
|
||||
auto arg = QString::fromStdString(name);
|
||||
QVariant v = QVariant::fromValue(arg);
|
||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
||||
item->setData(Qt::UserRole, arg);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args << arg;
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::RemoveArg()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
int idx = _argList->currentRow();
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
_entryData->_args.removeAt(idx);
|
||||
|
||||
QListWidgetItem *item = _argList->currentItem();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ArgUp()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = _argList->currentRow();
|
||||
if (idx != -1 && idx != 0) {
|
||||
_argList->insertItem(idx - 1, _argList->takeItem(idx));
|
||||
_argList->setCurrentRow(idx - 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args.move(idx, idx - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionRunEdit::ArgDown()
|
||||
{
|
||||
int idx = _argList->currentRow();
|
||||
if (idx != -1 && idx != _argList->count() - 1) {
|
||||
_argList->insertItem(idx + 1, _argList->takeItem(idx));
|
||||
_argList->setCurrentRow(idx + 1);
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_args.move(idx, idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
208
src/macro-action-scene-order.cpp
Normal file
208
src/macro-action-scene-order.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "headers/macro-action-scene-order.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionSceneOrder::id = "scene_order";
|
||||
|
||||
bool MacroActionSceneOrder::_registered = MacroActionFactory::Register(
|
||||
MacroActionSceneOrder::id,
|
||||
{MacroActionSceneOrder::Create, MacroActionSceneOrderEdit::Create,
|
||||
"AdvSceneSwitcher.action.sceneOrder"});
|
||||
|
||||
const static std::map<SceneOrderAction, std::string> actionTypes = {
|
||||
{SceneOrderAction::MOVE_UP,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveUp"},
|
||||
{SceneOrderAction::MOVE_DOWN,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveDown"},
|
||||
{SceneOrderAction::MOVE_TOP,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveTop"},
|
||||
{SceneOrderAction::MOVE_BOTTOM,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.moveBottom"},
|
||||
{SceneOrderAction::POSITION,
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.movePosition"},
|
||||
};
|
||||
|
||||
bool MacroActionSceneOrder::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name = GetWeakSourceName(_source);
|
||||
auto items = getSceneItemsWithName(scene, name);
|
||||
|
||||
for (auto &i : items) {
|
||||
switch (_action) {
|
||||
case SceneOrderAction::MOVE_UP:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_UP);
|
||||
break;
|
||||
case SceneOrderAction::MOVE_DOWN:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_DOWN);
|
||||
break;
|
||||
case SceneOrderAction::MOVE_TOP:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_TOP);
|
||||
break;
|
||||
case SceneOrderAction::MOVE_BOTTOM:
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_BOTTOM);
|
||||
break;
|
||||
case SceneOrderAction::POSITION:
|
||||
obs_sceneitem_set_order_position(i, _position);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
|
||||
obs_source_release(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionSceneOrder::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO,
|
||||
"performed order action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), GetWeakSourceName(_source).c_str(),
|
||||
_scene.ToString().c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown scene order action %d",
|
||||
static_cast<int>(_action));
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionSceneOrder::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_scene.Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "position", _position);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneOrder::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_scene.Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
_action =
|
||||
static_cast<SceneOrderAction>(obs_data_get_int(obj, "action"));
|
||||
_position = obs_data_get_int(obj, "position");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneOrder::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSceneOrderEdit::MacroActionSceneOrderEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneOrder> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
||||
_sources = new QComboBox();
|
||||
_actions = new QComboBox();
|
||||
_position = new QSpinBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_position, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(PositionChanged(int)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{actions}}", _actions},
|
||||
{"{{position}}", _position},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.sceneOrder.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
_position->setValue(_entryData->_position);
|
||||
_position->setVisible(_entryData->_action ==
|
||||
SceneOrderAction::POSITION);
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
_sources->clear();
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::SourceChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<SceneOrderAction>(value);
|
||||
_position->setVisible(_entryData->_action ==
|
||||
SceneOrderAction::POSITION);
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::PositionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_position = value;
|
||||
}
|
||||
@@ -39,6 +39,17 @@ bool MacroActionSwitchScene::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSwitchScene::GetShortDesc()
|
||||
{
|
||||
if (targetType == SwitchTargetType::Scene && scene) {
|
||||
return GetWeakSourceName(scene);
|
||||
}
|
||||
if (targetType == SwitchTargetType::SceneGroup && group) {
|
||||
return group->name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSwitchScene> entryData)
|
||||
: SwitchWidget(parent, entryData.get(), true, true)
|
||||
@@ -46,6 +57,8 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
||||
_duration = new DurationSelection(parent, false);
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(ChangeHeaderInfo(const QString &)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
@@ -71,3 +84,9 @@ void MacroActionSwitchSceneEdit::DurationChanged(double seconds)
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroActionSwitchSceneEdit::ChangeHeaderInfo(const QString &)
|
||||
{
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
271
src/macro-action-scene-transform.cpp
Normal file
271
src/macro-action-scene-transform.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
#include "headers/macro-action-scene-transform.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionSceneTransform::id = "scene_transform";
|
||||
|
||||
bool MacroActionSceneTransform::_registered = MacroActionFactory::Register(
|
||||
MacroActionSceneTransform::id,
|
||||
{MacroActionSceneTransform::Create,
|
||||
MacroActionSceneTransformEdit::Create,
|
||||
"AdvSceneSwitcher.action.sceneTransform"});
|
||||
|
||||
static void load_transform_state(obs_data_t *obj,
|
||||
struct obs_transform_info &info,
|
||||
struct obs_sceneitem_crop &crop)
|
||||
{
|
||||
obs_data_get_vec2(obj, "pos", &info.pos);
|
||||
obs_data_get_vec2(obj, "scale", &info.scale);
|
||||
info.rot = (float)obs_data_get_double(obj, "rot");
|
||||
info.alignment = (uint32_t)obs_data_get_int(obj, "alignment");
|
||||
info.bounds_type =
|
||||
(enum obs_bounds_type)obs_data_get_int(obj, "bounds_type");
|
||||
info.bounds_alignment =
|
||||
(uint32_t)obs_data_get_int(obj, "bounds_alignment");
|
||||
obs_data_get_vec2(obj, "bounds", &info.bounds);
|
||||
crop.top = (int)obs_data_get_int(obj, "top");
|
||||
crop.bottom = (int)obs_data_get_int(obj, "bottom");
|
||||
crop.left = (int)obs_data_get_int(obj, "left");
|
||||
crop.right = (int)obs_data_get_int(obj, "right");
|
||||
}
|
||||
|
||||
bool save_transform_state(obs_data_t *obj, struct obs_transform_info &info,
|
||||
struct obs_sceneitem_crop &crop)
|
||||
{
|
||||
struct vec2 pos = info.pos;
|
||||
struct vec2 scale = info.scale;
|
||||
float rot = info.rot;
|
||||
uint32_t alignment = info.alignment;
|
||||
uint32_t bounds_type = info.bounds_type;
|
||||
uint32_t bounds_alignment = info.bounds_alignment;
|
||||
struct vec2 bounds = info.bounds;
|
||||
|
||||
obs_data_set_vec2(obj, "pos", &pos);
|
||||
obs_data_set_vec2(obj, "scale", &scale);
|
||||
obs_data_set_double(obj, "rot", rot);
|
||||
obs_data_set_int(obj, "alignment", alignment);
|
||||
obs_data_set_int(obj, "bounds_type", bounds_type);
|
||||
obs_data_set_vec2(obj, "bounds", &bounds);
|
||||
obs_data_set_int(obj, "bounds_alignment", bounds_alignment);
|
||||
obs_data_set_int(obj, "top", crop.top);
|
||||
obs_data_set_int(obj, "bottom", crop.bottom);
|
||||
obs_data_set_int(obj, "left", crop.left);
|
||||
obs_data_set_int(obj, "right", crop.right);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneTransform::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene(false));
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name = GetWeakSourceName(_source);
|
||||
auto items = getSceneItemsWithName(scene, name);
|
||||
|
||||
for (auto &item : items) {
|
||||
// Merge new settings with current settings
|
||||
struct obs_transform_info info;
|
||||
struct obs_sceneitem_crop crop;
|
||||
obs_sceneitem_get_info(item, &info);
|
||||
obs_sceneitem_get_crop(item, &crop);
|
||||
auto temp = obs_data_create();
|
||||
save_transform_state(temp, info, crop);
|
||||
auto temp2 = obs_data_create();
|
||||
save_transform_state(temp, _info, _crop);
|
||||
obs_data_apply(temp, temp2);
|
||||
load_transform_state(temp, info, crop);
|
||||
obs_data_release(temp);
|
||||
obs_data_release(temp2);
|
||||
|
||||
// Apply settings
|
||||
obs_sceneitem_defer_update_begin(item);
|
||||
obs_sceneitem_set_info(item, &info);
|
||||
obs_sceneitem_set_crop(item, &crop);
|
||||
obs_sceneitem_defer_update_end(item);
|
||||
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
|
||||
obs_source_release(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionSceneTransform::LogAction()
|
||||
{
|
||||
vblog(LOG_INFO,
|
||||
"performed transform action for source \"%s\" on scene \"%s\"",
|
||||
GetWeakSourceName(_source).c_str(), _scene.ToString().c_str());
|
||||
}
|
||||
|
||||
bool MacroActionSceneTransform::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_scene.Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
save_transform_state(obj, _info, _crop);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneTransform::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_scene.Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
load_transform_state(obj, _info, _crop);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneTransform::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MacroActionSceneTransform::GetSettings()
|
||||
{
|
||||
auto data = obs_data_create();
|
||||
save_transform_state(data, _info, _crop);
|
||||
std::string json = obs_data_get_json(data);
|
||||
obs_data_release(data);
|
||||
return json;
|
||||
}
|
||||
|
||||
void MacroActionSceneTransform::SetSettings(std::string &settings)
|
||||
{
|
||||
auto data = obs_data_create_from_json(settings.c_str());
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
load_transform_state(data, _info, _crop);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
MacroActionSceneTransformEdit::MacroActionSceneTransformEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneTransform> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
||||
_sources = new QComboBox();
|
||||
_getSettings = new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneTransform.getTransform"));
|
||||
_settings = new QPlainTextEdit();
|
||||
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.sceneTransform.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_settings);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
if (_entryData->_source) {
|
||||
_settings->setPlainText(
|
||||
fromatJsonString(_entryData->GetSettings()));
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
_sources->clear();
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SourceChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_scene.GetScene(false) ||
|
||||
!_entryData->_source) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto s = obs_weak_source_get_source(_entryData->_scene.GetScene(false));
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name = GetWeakSourceName(_entryData->_source);
|
||||
auto item = obs_scene_find_source_recursive(scene, name.c_str());
|
||||
obs_source_release(s);
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct obs_transform_info info;
|
||||
struct obs_sceneitem_crop crop;
|
||||
obs_sceneitem_get_info(item, &info);
|
||||
obs_sceneitem_get_crop(item, &crop);
|
||||
|
||||
auto data = obs_data_create();
|
||||
save_transform_state(data, info, crop);
|
||||
auto json = obs_data_get_json(data);
|
||||
_settings->setPlainText(fromatJsonString(json));
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SettingsChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
auto json = _settings->toPlainText().toStdString();
|
||||
_entryData->SetSettings(json);
|
||||
}
|
||||
@@ -40,7 +40,7 @@ static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||
|
||||
bool MacroActionSceneVisibility::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_scene);
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto sourceName = GetWeakSourceName(_source);
|
||||
VisInfo vInfo = {sourceName, _action == SceneVisibilityAction::SHOW};
|
||||
@@ -64,9 +64,9 @@ void MacroActionSceneVisibility::LogAction()
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO,
|
||||
"performed action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), GetWeakSourceName(_scene).c_str(),
|
||||
GetWeakSourceName(_scene).c_str());
|
||||
"performed visibility action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), GetWeakSourceName(_source).c_str(),
|
||||
_scene.ToString().c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown SceneVisibility action %d",
|
||||
static_cast<int>(_action));
|
||||
@@ -76,7 +76,7 @@ void MacroActionSceneVisibility::LogAction()
|
||||
bool MacroActionSceneVisibility::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
||||
_scene.Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
@@ -85,8 +85,7 @@ bool MacroActionSceneVisibility::Save(obs_data_t *obj)
|
||||
bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
const char *sceneName = obs_data_get_string(obj, "scene");
|
||||
_scene = GetWeakSourceByName(sceneName);
|
||||
_scene.Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
_action = static_cast<SceneVisibilityAction>(
|
||||
@@ -94,6 +93,14 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneVisibility::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return _scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -101,51 +108,20 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static bool enumItem(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||
{
|
||||
std::set<QString> *names = reinterpret_cast<std::set<QString> *>(ptr);
|
||||
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, enumItem, ptr);
|
||||
}
|
||||
auto name = obs_source_get_name(obs_sceneitem_get_source(item));
|
||||
names->emplace(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateSceneItems(QComboBox *list,
|
||||
OBSWeakSource sceneWeakSource = nullptr)
|
||||
{
|
||||
std::set<QString> names;
|
||||
auto s = obs_weak_source_get_source(sceneWeakSource);
|
||||
auto scene = obs_scene_from_source(s);
|
||||
obs_scene_enum_items(scene, enumItem, &names);
|
||||
obs_source_release(s);
|
||||
|
||||
for (auto &name : names) {
|
||||
list->addItem(name);
|
||||
}
|
||||
list->model()->sort(0);
|
||||
addSelectionEntry(list, obs_module_text("AdvSceneSwitcher.selectItem"));
|
||||
list->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneVisibility> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_scenes = new QComboBox();
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
||||
_sources = new QComboBox();
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
populateSceneSelection(_scenes);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SceneChanged(const QString &)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
|
||||
@@ -172,23 +148,23 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData()
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
|
||||
populateSceneItems(_sources, _entryData->_scene);
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SceneChanged(const QString &text)
|
||||
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = GetWeakSourceByQString(text);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
_sources->clear();
|
||||
populateSceneItems(_sources, _entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
|
||||
@@ -199,6 +175,8 @@ void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::ActionChanged(int value)
|
||||
|
||||
@@ -16,22 +16,6 @@ const static std::map<SourceAction, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.source.type.settings"},
|
||||
};
|
||||
|
||||
void setSourceSettings(obs_source_t *s, const std::string &settings)
|
||||
{
|
||||
if (settings.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_data_t *data = obs_data_create_from_json(settings.c_str());
|
||||
if (!data) {
|
||||
blog(LOG_WARNING, "invalid source settings provided: \n%s",
|
||||
settings.c_str());
|
||||
return;
|
||||
}
|
||||
obs_source_update(s, data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
bool MacroActionSource::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_source);
|
||||
@@ -83,6 +67,14 @@ bool MacroActionSource::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSource::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
@@ -159,6 +151,8 @@ void MacroActionSourceEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::ActionChanged(int value)
|
||||
@@ -179,7 +173,7 @@ void MacroActionSourceEdit::GetSettingsClicked()
|
||||
}
|
||||
|
||||
_settings->setPlainText(
|
||||
QString::fromStdString(getSourceSettings(_entryData->_source)));
|
||||
fromatJsonString(getSourceSettings(_entryData->_source)));
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SettingsChanged()
|
||||
|
||||
109
src/macro-action-virtual-cam.cpp
Normal file
109
src/macro-action-virtual-cam.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "headers/macro-action-virtual-cam.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
|
||||
const std::string MacroActionVCam::id = "virtual_cam";
|
||||
|
||||
bool MacroActionVCam::_registered = MacroActionFactory::Register(
|
||||
MacroActionVCam::id,
|
||||
{MacroActionVCam::Create, MacroActionVCamEdit::Create,
|
||||
"AdvSceneSwitcher.action.virtualCamera"});
|
||||
|
||||
const static std::map<VCamAction, std::string> actionTypes = {
|
||||
{VCamAction::STOP, "AdvSceneSwitcher.action.virtualCamera.type.stop"},
|
||||
{VCamAction::START, "AdvSceneSwitcher.action.virtualCamera.type.start"},
|
||||
};
|
||||
|
||||
bool MacroActionVCam::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
case VCamAction::STOP:
|
||||
if (obs_frontend_virtualcam_active()) {
|
||||
obs_frontend_stop_virtualcam();
|
||||
}
|
||||
break;
|
||||
case VCamAction::START:
|
||||
if (!obs_frontend_virtualcam_active()) {
|
||||
obs_frontend_start_virtualcam();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionVCam::LogAction()
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO, "performed action \"%s\"", it->second.c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown virtual camera action %d",
|
||||
static_cast<int>(_action));
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionVCam::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionVCam::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_action = static_cast<VCamAction>(obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionVCamEdit::MacroActionVCamEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVCam> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.virtualCamera.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionVCamEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
}
|
||||
|
||||
void MacroActionVCamEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_action = static_cast<VCamAction>(value);
|
||||
}
|
||||
@@ -38,9 +38,10 @@ bool MacroActionWait::PerformAction()
|
||||
sleep_duration);
|
||||
|
||||
std::unique_lock<std::mutex> lock(switcher->m);
|
||||
switcher->cv.wait_for(lock, std::chrono::milliseconds((
|
||||
long long)(sleep_duration * 1000)));
|
||||
return !switcher->stop;
|
||||
auto r = switcher->cv.wait_for(
|
||||
lock,
|
||||
std::chrono::milliseconds((long long)(sleep_duration * 1000)));
|
||||
return r == std::cv_status::timeout;
|
||||
}
|
||||
|
||||
bool MacroActionWait::Save(obs_data_t *obj)
|
||||
|
||||
@@ -77,6 +77,14 @@ bool MacroConditionAudio::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionAudio::GetShortDesc()
|
||||
{
|
||||
if (_audioSource) {
|
||||
return GetWeakSourceName(_audioSource);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacroConditionAudio::SetVolumeLevel(
|
||||
void *data, const float magnitude[MAX_AUDIO_CHANNELS],
|
||||
const float peak[MAX_AUDIO_CHANNELS],
|
||||
@@ -181,6 +189,8 @@ void MacroConditionAudioEdit::SourceChanged(const QString &text)
|
||||
_entryData->_audioSource = GetWeakSourceByQString(text);
|
||||
_entryData->ResetVolmeter();
|
||||
UpdateVolmeterSource();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionAudioEdit::VolumeThresholdChanged(int vol)
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-counter.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionCounter::id = "counter";
|
||||
|
||||
bool MacroConditionCounter::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionCounter::id,
|
||||
{MacroConditionCounter::Create, MacroConditionCounterEdit::Create,
|
||||
"AdvSceneSwitcher.condition.counter"});
|
||||
|
||||
static std::map<CounterCondition, std::string> counterConditionTypes = {
|
||||
{CounterCondition::BELOW,
|
||||
"AdvSceneSwitcher.condition.counter.type.below"},
|
||||
{CounterCondition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.counter.type.above"},
|
||||
{CounterCondition::EQUAL,
|
||||
"AdvSceneSwitcher.condition.counter.type.equal"},
|
||||
};
|
||||
|
||||
bool MacroConditionCounter::CheckCondition()
|
||||
{
|
||||
if (!_macro.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_condition) {
|
||||
case CounterCondition::BELOW:
|
||||
return _macro->GetCount() < _count;
|
||||
case CounterCondition::ABOVE:
|
||||
return _macro->GetCount() > _count;
|
||||
case CounterCondition::EQUAL:
|
||||
return _macro->GetCount() == _count;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionCounter::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_macro.Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_int(obj, "count", _count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionCounter::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_macro.Load(obj);
|
||||
_condition = static_cast<CounterCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_count = obs_data_get_int(obj, "count");
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : counterConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionCounterEdit::MacroConditionCounterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionCounter> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_macros = new MacroSelection(parent);
|
||||
_conditions = new QComboBox();
|
||||
_count = new QSpinBox();
|
||||
_currentCount = new QLabel();
|
||||
_resetCount = new QPushButton(
|
||||
obs_module_text("AdvSceneSwitcher.condition.counter.reset"));
|
||||
|
||||
_count->setMaximum(10000000);
|
||||
populateConditionSelection(_conditions);
|
||||
|
||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(MacroChanged(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
||||
SLOT(MacroRemove(const QString &)));
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_count, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(CountChanged(int)));
|
||||
QWidget::connect(_resetCount, SIGNAL(clicked()), this,
|
||||
SLOT(ResetClicked()));
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{macros}}", _macros},
|
||||
{"{{conditions}}", _conditions},
|
||||
{"{{count}}", _count},
|
||||
{"{{currentCount}}", _currentCount},
|
||||
{"{{resetCount}}", _resetCount},
|
||||
};
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.counter.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.counter.entry.line2"),
|
||||
line2Layout, widgetPlaceholders);
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_macros->SetCurrentMacro(_entryData->_macro.get());
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_count->setValue(_entryData->_count);
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::MacroChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macro.UpdateRef(text);
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::CountChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_count = value;
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::ConditionChanged(int cond)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_condition = static_cast<CounterCondition>(cond);
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::MacroRemove(const QString &name)
|
||||
{
|
||||
UNUSED_PARAMETER(name);
|
||||
if (_entryData) {
|
||||
_entryData->_macro.UpdateRef();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::ResetClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_macro.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_entryData->_macro->ResetCount();
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::UpdateCount()
|
||||
{
|
||||
if (_entryData && _entryData->_macro.get()) {
|
||||
_currentCount->setText(
|
||||
QString::number(_entryData->_macro->GetCount()));
|
||||
} else {
|
||||
_currentCount->setText("-");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionCounterEdit::ResetTimer()
|
||||
{
|
||||
_timer.reset(new QTimer(this));
|
||||
connect(_timer.get(), SIGNAL(timeout()), this, SLOT(UpdateCount()));
|
||||
_timer->start(1000);
|
||||
}
|
||||
189
src/macro-condition-date.cpp
Normal file
189
src/macro-condition-date.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-date.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionDate::id = "date";
|
||||
|
||||
bool MacroConditionDate::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionDate::id,
|
||||
{MacroConditionDate::Create, MacroConditionDateEdit::Create,
|
||||
"AdvSceneSwitcher.condition.date", false});
|
||||
|
||||
bool MacroConditionDate::CheckCondition()
|
||||
{
|
||||
bool match = false;
|
||||
QDateTime cur = QDateTime::currentDateTime();
|
||||
if (_ignoreDate) {
|
||||
_dateTime.setDate(cur.date());
|
||||
}
|
||||
if (_ignoreTime) {
|
||||
_dateTime.setTime(cur.time());
|
||||
}
|
||||
|
||||
match = _dateTime >= cur &&
|
||||
_dateTime <= cur.addMSecs(switcher->interval);
|
||||
if (match && _repeat) {
|
||||
_dateTime = _dateTime.addSecs(_duration.seconds);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
bool MacroConditionDate::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_string(obj, "dateTime",
|
||||
_dateTime.toString().toStdString().c_str());
|
||||
obs_data_set_bool(obj, "ignoreDate", _ignoreDate);
|
||||
obs_data_set_bool(obj, "ignoreTime", _ignoreTime);
|
||||
obs_data_set_bool(obj, "repeat", _repeat);
|
||||
_duration.Save(obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionDate::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_dateTime = QDateTime::fromString(
|
||||
QString::fromStdString(obs_data_get_string(obj, "dateTime")));
|
||||
_ignoreDate = obs_data_get_bool(obj, "ignoreDate");
|
||||
_ignoreTime = obs_data_get_bool(obj, "ignoreTime");
|
||||
_repeat = obs_data_get_bool(obj, "repeat");
|
||||
_duration.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionDate::GetShortDesc()
|
||||
{
|
||||
return _dateTime.toString().toStdString();
|
||||
}
|
||||
|
||||
MacroConditionDateEdit::MacroConditionDateEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionDate> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_dateTime = new QDateTimeEdit();
|
||||
_dateTime->setCalendarPopup(true);
|
||||
_dateTime->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
|
||||
_ignoreDate = new QCheckBox();
|
||||
_ignoreTime = new QCheckBox();
|
||||
_repeat = new QCheckBox();
|
||||
_duration = new DurationSelection();
|
||||
|
||||
QWidget::connect(_dateTime, SIGNAL(dateTimeChanged(const QDateTime &)),
|
||||
this, SLOT(DateTimeChanged(const QDateTime &)));
|
||||
QWidget::connect(_ignoreDate, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(IgnoreDateChanged(int)));
|
||||
QWidget::connect(_ignoreTime, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(IgnoreTimeChanged(int)));
|
||||
QWidget::connect(_repeat, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RepeatChanged(int)));
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(DurationUnitChanged(DurationUnit)));
|
||||
|
||||
auto line1Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{dateTime}}", _dateTime},
|
||||
{"{{ignoreDate}}", _ignoreDate},
|
||||
{"{{ignoreTime}}", _ignoreTime},
|
||||
{"{{repeat}}", _repeat},
|
||||
{"{{duration}}", _duration},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.date.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
auto line2Layout = new QHBoxLayout;
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.date.entry.line2"),
|
||||
line2Layout, widgetPlaceholders);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_dateTime = datetime;
|
||||
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::IgnoreDateChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_ignoreDate = state;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::IgnoreTimeChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_ignoreTime = state;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::RepeatChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_repeat = state;
|
||||
_duration->setDisabled(!state);
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::DurationChanged(double seconds)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::DurationUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.displayUnit = unit;
|
||||
}
|
||||
|
||||
void MacroConditionDateEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
_dateTime->setDateTime(_entryData->_dateTime);
|
||||
_ignoreDate->setChecked(_entryData->_ignoreDate);
|
||||
_ignoreTime->setChecked(_entryData->_ignoreTime);
|
||||
_repeat->setChecked(_entryData->_repeat);
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
_duration->setDisabled(!_entryData->_repeat);
|
||||
}
|
||||
@@ -93,6 +93,7 @@ MacroConditionEdit::MacroConditionEdit(
|
||||
_logicSelection = new QComboBox();
|
||||
_conditionSelection = new QComboBox();
|
||||
_section = new Section(300);
|
||||
_headerInfo = new QLabel();
|
||||
_dur = new DurationConstraintEdit();
|
||||
|
||||
QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)),
|
||||
@@ -107,12 +108,29 @@ MacroConditionEdit::MacroConditionEdit(
|
||||
QWidget::connect(_dur, SIGNAL(ConditionChanged(DurationCondition)),
|
||||
this,
|
||||
SLOT(DurationConditionChanged(DurationCondition)));
|
||||
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this,
|
||||
SIGNAL(MacroAdded(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
||||
SIGNAL(MacroRemoved(const QString &)));
|
||||
QWidget::connect(parent,
|
||||
SIGNAL(MacroRenamed(const QString &, const QString)),
|
||||
this,
|
||||
SIGNAL(MacroRenamed(const QString &, const QString)));
|
||||
QWidget::connect(parent, SIGNAL(SceneGroupAdded(const QString &)), this,
|
||||
SIGNAL(SceneGroupAdded(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(SceneGroupRemoved(const QString &)),
|
||||
this, SIGNAL(SceneGroupRemoved(const QString &)));
|
||||
QWidget::connect(
|
||||
parent,
|
||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)), this,
|
||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)));
|
||||
|
||||
populateLogicSelection(_logicSelection, root);
|
||||
populateConditionSelection(_conditionSelection);
|
||||
|
||||
_section->AddHeaderWidget(_logicSelection);
|
||||
_section->AddHeaderWidget(_conditionSelection);
|
||||
_section->AddHeaderWidget(_headerInfo);
|
||||
_section->AddHeaderWidget(_dur);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
@@ -152,7 +170,11 @@ void MacroConditionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
||||
_conditionSelection->setCurrentText(obs_module_text(
|
||||
MacroConditionFactory::GetConditionName(id).c_str()));
|
||||
auto widget =
|
||||
MacroConditionFactory::CreateWidget(id, window(), *_entryData);
|
||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
HeaderInfoChanged(
|
||||
QString::fromStdString((*_entryData)->GetShortDesc()));
|
||||
auto logic = (*_entryData)->GetLogicType();
|
||||
if (IsRootNode()) {
|
||||
_logicSelection->setCurrentIndex(static_cast<int>(logic));
|
||||
@@ -177,6 +199,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||
|
||||
auto temp = DurationConstraint();
|
||||
_dur->SetValue(temp);
|
||||
HeaderInfoChanged("");
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
auto logic = (*_entryData)->GetLogicType();
|
||||
@@ -184,7 +207,9 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||
*_entryData = MacroConditionFactory::Create(id);
|
||||
(*_entryData)->SetLogicType(logic);
|
||||
auto widget =
|
||||
MacroConditionFactory::CreateWidget(id, window(), *_entryData);
|
||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
_section->SetContent(widget, false);
|
||||
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
|
||||
}
|
||||
@@ -219,6 +244,12 @@ void MacroConditionEdit::DurationUnitChanged(DurationUnit unit)
|
||||
(*_entryData)->SetDurationUnit(unit);
|
||||
}
|
||||
|
||||
void MacroConditionEdit::HeaderInfoChanged(const QString &text)
|
||||
{
|
||||
_headerInfo->setVisible(!text.isEmpty());
|
||||
_headerInfo->setText(text);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_conditionAdd_clicked()
|
||||
{
|
||||
auto macro = getSelectedMacro();
|
||||
|
||||
@@ -32,6 +32,14 @@ static std::string getRemoteData(std::string &url)
|
||||
f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION,
|
||||
WriteCallback);
|
||||
f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
|
||||
// Set timeout to at least one second
|
||||
int timeout = switcher->interval / 1000;
|
||||
if (timeout == 0) {
|
||||
timeout = 1;
|
||||
}
|
||||
f_curl_setopt(switcher->curl, CURLOPT_TIMEOUT, 1);
|
||||
|
||||
f_curl_perform(switcher->curl);
|
||||
}
|
||||
return readBuffer;
|
||||
@@ -67,7 +75,7 @@ bool MacroConditionFile::checkLocalFileContent()
|
||||
{
|
||||
QString t = QString::fromStdString(_text);
|
||||
QFile file(QString::fromStdString(_file));
|
||||
if (_file.empty() || !file.open(QIODevice::ReadOnly)) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -119,6 +127,11 @@ bool MacroConditionFile::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionFile::GetShortDesc()
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
MacroConditionFileEdit::MacroConditionFileEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionFile> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -231,6 +244,8 @@ void MacroConditionFileEdit::FilePathChanged()
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_file = _filePath->text().toUtf8().constData();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionFileEdit::BrowseButtonClicked()
|
||||
|
||||
242
src/macro-condition-filter.cpp
Normal file
242
src/macro-condition-filter.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-filter.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
const std::string MacroConditionFilter::id = "filter";
|
||||
|
||||
bool MacroConditionFilter::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionFilter::id,
|
||||
{MacroConditionFilter::Create, MacroConditionFilterEdit::Create,
|
||||
"AdvSceneSwitcher.condition.filter"});
|
||||
|
||||
static std::map<FilterCondition, std::string> filterConditionTypes = {
|
||||
{FilterCondition::ENABLED,
|
||||
"AdvSceneSwitcher.condition.filter.type.active"},
|
||||
{FilterCondition::DISABLED,
|
||||
"AdvSceneSwitcher.condition.filter.type.showing"},
|
||||
{FilterCondition::SETTINGS,
|
||||
"AdvSceneSwitcher.condition.filter.type.settings"},
|
||||
};
|
||||
|
||||
bool MacroConditionFilter::CheckCondition()
|
||||
{
|
||||
if (!_source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
auto s = obs_weak_source_get_source(_filter);
|
||||
|
||||
switch (_condition) {
|
||||
case FilterCondition::ENABLED:
|
||||
ret = obs_source_enabled(s);
|
||||
break;
|
||||
case FilterCondition::DISABLED:
|
||||
ret = !obs_source_enabled(s);
|
||||
break;
|
||||
case FilterCondition::SETTINGS:
|
||||
ret = compareSourceSettings(_filter, _settings, _regex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
obs_source_release(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MacroConditionFilter::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_string(obj, "filter", GetWeakSourceName(_filter).c_str());
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_string(obj, "settings", _settings.c_str());
|
||||
obs_data_set_bool(obj, "regex", _regex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionFilter::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
const char *filterName = obs_data_get_string(obj, "filter");
|
||||
_filter = GetWeakFilterByQString(_source, filterName);
|
||||
_condition = static_cast<FilterCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_settings = obs_data_get_string(obj, "settings");
|
||||
_regex = obs_data_get_bool(obj, "regex");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionFilter::GetShortDesc()
|
||||
{
|
||||
if (_filter && _source) {
|
||||
return GetWeakSourceName(_source) + " - " +
|
||||
GetWeakSourceName(_filter);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : filterConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionFilterEdit::MacroConditionFilterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionFilter> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_sources = new QComboBox();
|
||||
_filters = new QComboBox();
|
||||
_conditions = new QComboBox();
|
||||
_getSettings = new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.getSettings"));
|
||||
_settings = new QPlainTextEdit();
|
||||
_regex = new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.condition.filter.regex"));
|
||||
|
||||
populateConditionSelection(_conditions);
|
||||
populateSourcesWithFilterSelection(_sources);
|
||||
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(FilterChanged(const QString &)));
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
QWidget::connect(_regex, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(RegexChanged(int)));
|
||||
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line3Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sources}}", _sources}, {"{{filters}}", _filters},
|
||||
{"{{conditions}}", _conditions}, {"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings}, {"{{regex}}", _regex},
|
||||
};
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.entry.line2"),
|
||||
line2Layout, widgetPlaceholders, false);
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.entry.line3"),
|
||||
line3Layout, widgetPlaceholders);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
mainLayout->addLayout(line3Layout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::SourceChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
}
|
||||
_filters->clear();
|
||||
populateFilterSelection(_filters, _entryData->_source);
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::FilterChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_filter = GetWeakFilterByQString(_entryData->_source, text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::ConditionChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_condition = static_cast<FilterCondition>(index);
|
||||
SetSettingsSelectionVisible(_entryData->_condition ==
|
||||
FilterCondition::SETTINGS);
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_source) {
|
||||
return;
|
||||
}
|
||||
|
||||
_settings->setPlainText(
|
||||
fromatJsonString(getSourceSettings(_entryData->_filter)));
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::SettingsChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_settings = _settings->toPlainText().toStdString();
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::RegexChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_regex = state;
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::SetSettingsSelectionVisible(bool visible)
|
||||
{
|
||||
_settings->setVisible(visible);
|
||||
_getSettings->setVisible(visible);
|
||||
_regex->setVisible(visible);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
populateFilterSelection(_filters, _entryData->_source);
|
||||
_filters->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_filter).c_str());
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_settings->setPlainText(QString::fromStdString(_entryData->_settings));
|
||||
_regex->setChecked(_entryData->_regex);
|
||||
SetSettingsSelectionVisible(_entryData->_condition ==
|
||||
FilterCondition::SETTINGS);
|
||||
}
|
||||
124
src/macro-condition-hotkey.cpp
Normal file
124
src/macro-condition-hotkey.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-hotkey.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionHotkey::id = "hotkey";
|
||||
|
||||
bool MacroConditionHotkey::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionHotkey::id,
|
||||
{MacroConditionHotkey::Create, MacroConditionHotkeyEdit::Create,
|
||||
"AdvSceneSwitcher.condition.hotkey", false});
|
||||
|
||||
static void hotkeyCB(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
||||
bool pressed)
|
||||
{
|
||||
UNUSED_PARAMETER(id);
|
||||
UNUSED_PARAMETER(data);
|
||||
UNUSED_PARAMETER(hotkey);
|
||||
if (pressed) {
|
||||
auto c = static_cast<MacroConditionHotkey *>(data);
|
||||
c->SetPressed();
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t count = 1;
|
||||
|
||||
MacroConditionHotkey::MacroConditionHotkey()
|
||||
{
|
||||
if (_hotkeyID != OBS_INVALID_HOTKEY_ID) {
|
||||
obs_hotkey_unregister(_hotkeyID);
|
||||
}
|
||||
|
||||
std::string hotkeyName =
|
||||
"macro_condition_hotkey_" + std::to_string(count);
|
||||
|
||||
_name = obs_module_text("AdvSceneSwitcher.condition.hotkey.name") +
|
||||
std::string(" ") + std::to_string(count);
|
||||
_hotkeyID = obs_hotkey_register_frontend(hotkeyName.c_str(),
|
||||
_name.c_str(), hotkeyCB, this);
|
||||
count++;
|
||||
}
|
||||
|
||||
MacroConditionHotkey::~MacroConditionHotkey()
|
||||
{
|
||||
obs_hotkey_unregister(_hotkeyID);
|
||||
}
|
||||
|
||||
bool MacroConditionHotkey::CheckCondition()
|
||||
{
|
||||
if (_pressed) {
|
||||
_pressed = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionHotkey::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_string(obj, "desc", _name.c_str());
|
||||
obs_data_array_t *pauseHotkey = obs_hotkey_save(_hotkeyID);
|
||||
obs_data_set_array(obj, "keyBind", pauseHotkey);
|
||||
obs_data_array_release(pauseHotkey);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionHotkey::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_name = obs_data_get_string(obj, "desc");
|
||||
obs_data_array_t *pauseHotkey = obs_data_get_array(obj, "keyBind");
|
||||
obs_hotkey_load(_hotkeyID, pauseHotkey);
|
||||
obs_data_array_release(pauseHotkey);
|
||||
obs_hotkey_set_description(_hotkeyID, _name.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
MacroConditionHotkeyEdit::MacroConditionHotkeyEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionHotkey> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_name = new QLineEdit();
|
||||
QLabel *hint = new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.condition.hotkey.tip"));
|
||||
QWidget::connect(_name, SIGNAL(editingFinished()), this,
|
||||
SLOT(NameChanged()));
|
||||
|
||||
QHBoxLayout *switchLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{name}}", _name},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.condition.hotkey.entry"),
|
||||
switchLayout, widgetPlaceholders);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(switchLayout);
|
||||
mainLayout->addWidget(hint);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionHotkeyEdit::NameChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_name = _name->text().toStdString();
|
||||
obs_hotkey_set_description(_entryData->_hotkeyID,
|
||||
_entryData->_name.c_str());
|
||||
}
|
||||
|
||||
void MacroConditionHotkeyEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_name->setText(QString::fromStdString(_entryData->_name));
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-interval.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionInterval::id = "interval";
|
||||
|
||||
bool MacroConditionInterval::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionInterval::id,
|
||||
{MacroConditionInterval::Create, MacroConditionIntervalEdit::Create,
|
||||
"AdvSceneSwitcher.condition.interval", false});
|
||||
|
||||
bool MacroConditionInterval::CheckCondition()
|
||||
{
|
||||
if (_duration.DurationReached()) {
|
||||
_duration.Reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionInterval::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_duration.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionInterval::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_duration.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
MacroConditionIntervalEdit::MacroConditionIntervalEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionInterval> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_duration = new DurationSelection();
|
||||
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(DurationUnitChanged(DurationUnit)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{duration}}", _duration},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.interval.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionIntervalEdit::DurationChanged(double seconds)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroConditionIntervalEdit::DurationUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.displayUnit = unit;
|
||||
}
|
||||
|
||||
void MacroConditionIntervalEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
}
|
||||
330
src/macro-condition-macro.cpp
Normal file
330
src/macro-condition-macro.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-macro.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionMacro::id = "macro";
|
||||
|
||||
bool MacroConditionMacro::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionMacro::id,
|
||||
{MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
|
||||
"AdvSceneSwitcher.condition.macro"});
|
||||
|
||||
// TODO: Remove in future version - just added for backward compatibility
|
||||
static std::string idOld = "counter";
|
||||
static bool oldRegisterd = MacroConditionFactory::Register(
|
||||
idOld, {MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
|
||||
"AdvSceneSwitcher.condition.macro"});
|
||||
|
||||
static std::map<MacroConditionMacroType, std::string> macroConditionTypes = {
|
||||
{MacroConditionMacroType::COUNT,
|
||||
"AdvSceneSwitcher.condition.macro.type.count"},
|
||||
{MacroConditionMacroType::STATE,
|
||||
"AdvSceneSwitcher.condition.macro.type.state"},
|
||||
};
|
||||
|
||||
static std::map<CounterCondition, std::string> counterConditionTypes = {
|
||||
{CounterCondition::BELOW,
|
||||
"AdvSceneSwitcher.condition.macro.count.type.below"},
|
||||
{CounterCondition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.macro.count.type.above"},
|
||||
{CounterCondition::EQUAL,
|
||||
"AdvSceneSwitcher.condition.macro.count.type.equal"},
|
||||
};
|
||||
|
||||
bool MacroConditionMacro::CheckStateCondition()
|
||||
{
|
||||
// Note:
|
||||
// Depending on the order the macro conditions are checked Matched() might
|
||||
// still return the state of the previous interval
|
||||
return _macro->Matched();
|
||||
}
|
||||
|
||||
bool MacroConditionMacro::CheckCountCondition()
|
||||
{
|
||||
switch (_counterCondition) {
|
||||
case CounterCondition::BELOW:
|
||||
return _macro->GetCount() < _count;
|
||||
case CounterCondition::ABOVE:
|
||||
return _macro->GetCount() > _count;
|
||||
case CounterCondition::EQUAL:
|
||||
return _macro->GetCount() == _count;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionMacro::CheckCondition()
|
||||
{
|
||||
if (!_macro.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case MacroConditionMacroType::STATE:
|
||||
return CheckStateCondition();
|
||||
break;
|
||||
case MacroConditionMacroType::COUNT:
|
||||
return CheckCountCondition();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionMacro::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_macro.Save(obj);
|
||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_counterCondition));
|
||||
obs_data_set_int(obj, "count", _count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionMacro::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_macro.Load(obj);
|
||||
_type = static_cast<MacroConditionMacroType>(
|
||||
obs_data_get_int(obj, "type"));
|
||||
_counterCondition = static_cast<CounterCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_count = obs_data_get_int(obj, "count");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionMacro::GetShortDesc()
|
||||
{
|
||||
if (_macro.get()) {
|
||||
return _macro->Name();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : macroConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : counterConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionMacroEdit::MacroConditionMacroEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionMacro> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_macros = new MacroSelection(parent);
|
||||
_types = new QComboBox(parent);
|
||||
_counterConditions = new QComboBox(parent);
|
||||
_count = new QSpinBox(parent);
|
||||
_currentCount = new QLabel(parent);
|
||||
_resetCount = new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.macro.count.reset"));
|
||||
|
||||
_count->setMaximum(10000000);
|
||||
populateTypeSelection(_types);
|
||||
populateConditionSelection(_counterConditions);
|
||||
|
||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(MacroChanged(const QString &)));
|
||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
||||
SLOT(MacroRemove(const QString &)));
|
||||
QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(TypeChanged(int)));
|
||||
QWidget::connect(_counterConditions, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_count, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(CountChanged(int)));
|
||||
QWidget::connect(_resetCount, SIGNAL(clicked()), this,
|
||||
SLOT(ResetClicked()));
|
||||
|
||||
auto typesLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{types}}", _types},
|
||||
};
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.macro.type.selection"),
|
||||
typesLayout, widgetPlaceholders);
|
||||
_settingsLine1 = new QHBoxLayout;
|
||||
_settingsLine2 = new QHBoxLayout;
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(typesLayout);
|
||||
mainLayout->addLayout(_settingsLine1);
|
||||
mainLayout->addLayout(_settingsLine2);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::ClearLayouts()
|
||||
{
|
||||
_settingsLine1->removeWidget(_macros);
|
||||
_settingsLine1->removeWidget(_counterConditions);
|
||||
_settingsLine1->removeWidget(_count);
|
||||
_settingsLine2->removeWidget(_currentCount);
|
||||
_settingsLine2->removeWidget(_resetCount);
|
||||
clearLayout(_settingsLine1);
|
||||
clearLayout(_settingsLine2);
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::SetupStateWidgets()
|
||||
{
|
||||
ClearLayouts();
|
||||
|
||||
_counterConditions->hide();
|
||||
_count->hide();
|
||||
_currentCount->hide();
|
||||
_resetCount->hide();
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{macros}}", _macros},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.macro.state.entry"),
|
||||
_settingsLine1, widgetPlaceholders);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::SetupCountWidgets()
|
||||
{
|
||||
ClearLayouts();
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{macros}}", _macros},
|
||||
{"{{conditions}}", _counterConditions},
|
||||
{"{{count}}", _count},
|
||||
{"{{currentCount}}", _currentCount},
|
||||
{"{{resetCount}}", _resetCount},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.condition.macro.count.entry.line1"),
|
||||
_settingsLine1, widgetPlaceholders);
|
||||
placeWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.condition.macro.count.entry.line2"),
|
||||
_settingsLine2, widgetPlaceholders);
|
||||
|
||||
_counterConditions->show();
|
||||
_count->show();
|
||||
_currentCount->show();
|
||||
_resetCount->show();
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_entryData->_type == MacroConditionMacroType::STATE) {
|
||||
SetupStateWidgets();
|
||||
} else {
|
||||
SetupCountWidgets();
|
||||
}
|
||||
|
||||
_macros->SetCurrentMacro(_entryData->_macro.get());
|
||||
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_counterConditions->setCurrentIndex(
|
||||
static_cast<int>(_entryData->_counterCondition));
|
||||
_count->setValue(_entryData->_count);
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_macro.UpdateRef(text);
|
||||
ResetTimer();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::CountChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_count = value;
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::ConditionChanged(int cond)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_counterCondition = static_cast<CounterCondition>(cond);
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::MacroRemove(const QString &name)
|
||||
{
|
||||
UNUSED_PARAMETER(name);
|
||||
if (_entryData) {
|
||||
_entryData->_macro.UpdateRef();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::TypeChanged(int type)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_type = static_cast<MacroConditionMacroType>(type);
|
||||
if (_entryData->_type == MacroConditionMacroType::STATE) {
|
||||
SetupStateWidgets();
|
||||
} else {
|
||||
SetupCountWidgets();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::ResetClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_macro.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_entryData->_macro->ResetCount();
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::UpdateCount()
|
||||
{
|
||||
if (_entryData && _entryData->_macro.get()) {
|
||||
_currentCount->setText(
|
||||
QString::number(_entryData->_macro->GetCount()));
|
||||
} else {
|
||||
_currentCount->setText("-");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::ResetTimer()
|
||||
{
|
||||
_timer.reset(new QTimer(this));
|
||||
connect(_timer.get(), SIGNAL(timeout()), this, SLOT(UpdateCount()));
|
||||
_timer->start(1000);
|
||||
}
|
||||
@@ -189,6 +189,14 @@ bool MacroConditionMedia::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionMedia::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacroConditionMedia::ClearSignalHandler()
|
||||
{
|
||||
obs_source_t *mediasource = obs_weak_source_get_source(_source);
|
||||
@@ -286,6 +294,8 @@ void MacroConditionMediaEdit::SourceChanged(const QString &text)
|
||||
_entryData->ClearSignalHandler();
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
_entryData->ResetSignalHandler();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
MediaState getMediaStateFromIdx(int idx)
|
||||
|
||||
@@ -14,12 +14,8 @@ bool MacroConditionProcess::_registered = MacroConditionFactory::Register(
|
||||
|
||||
bool MacroConditionProcess::CheckCondition()
|
||||
{
|
||||
std::string title;
|
||||
QStringList runningProcesses;
|
||||
|
||||
QString proc = QString::fromStdString(_process);
|
||||
|
||||
GetCurrentWindowTitle(title);
|
||||
GetProcessList(runningProcesses);
|
||||
|
||||
bool equals = runningProcesses.contains(proc);
|
||||
@@ -45,6 +41,11 @@ bool MacroConditionProcess::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionProcess::GetShortDesc()
|
||||
{
|
||||
return _process;
|
||||
}
|
||||
|
||||
MacroConditionProcessEdit::MacroConditionProcessEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionProcess> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -87,6 +88,8 @@ void MacroConditionProcessEdit::ProcessChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_process = text.toStdString();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionProcessEdit::FocusChanged(int state)
|
||||
|
||||
108
src/macro-condition-replay-buffer.cpp
Normal file
108
src/macro-condition-replay-buffer.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-replay-buffer.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionReplayBuffer::id = "replay_buffer";
|
||||
|
||||
bool MacroConditionReplayBuffer::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionReplayBuffer::id, {MacroConditionReplayBuffer::Create,
|
||||
MacroConditionReplayBufferEdit::Create,
|
||||
"AdvSceneSwitcher.condition.replay"});
|
||||
|
||||
static std::map<ReplayBufferState, std::string> ReplayBufferStates = {
|
||||
{ReplayBufferState::STOP,
|
||||
"AdvSceneSwitcher.condition.replay.state.stopped"},
|
||||
{ReplayBufferState::START,
|
||||
"AdvSceneSwitcher.condition.replay.state.started"},
|
||||
{ReplayBufferState::SAVE,
|
||||
"AdvSceneSwitcher.condition.replay.state.saved"},
|
||||
};
|
||||
|
||||
bool MacroConditionReplayBuffer::CheckCondition()
|
||||
{
|
||||
bool stateMatch = false;
|
||||
switch (_state) {
|
||||
case ReplayBufferState::STOP:
|
||||
stateMatch = !obs_frontend_replay_buffer_active();
|
||||
break;
|
||||
case ReplayBufferState::START:
|
||||
stateMatch = obs_frontend_replay_buffer_active();
|
||||
break;
|
||||
case ReplayBufferState::SAVE:
|
||||
if (switcher->replayBufferSaved) {
|
||||
stateMatch = true;
|
||||
switcher->replayBufferSaved = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return stateMatch;
|
||||
}
|
||||
|
||||
bool MacroConditionReplayBuffer::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_int(obj, "state", static_cast<int>(_state));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionReplayBuffer::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_state = static_cast<ReplayBufferState>(obs_data_get_int(obj, "state"));
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateStateSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : ReplayBufferStates) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionReplayBufferEdit::MacroConditionReplayBufferEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionReplayBuffer> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_state = new QComboBox();
|
||||
|
||||
QWidget::connect(_state, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(StateChanged(int)));
|
||||
|
||||
populateStateSelection(_state);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{state}}", _state},
|
||||
};
|
||||
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.condition.replay.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionReplayBufferEdit::StateChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_state = static_cast<ReplayBufferState>(value);
|
||||
}
|
||||
|
||||
void MacroConditionReplayBufferEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_state->setCurrentIndex(static_cast<int>(_entryData->_state));
|
||||
}
|
||||
286
src/macro-condition-scene-order.cpp
Normal file
286
src/macro-condition-scene-order.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-scene-order.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
const std::string MacroConditionSceneOrder::id = "scene_order";
|
||||
|
||||
bool MacroConditionSceneOrder::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionSceneOrder::id,
|
||||
{MacroConditionSceneOrder::Create, MacroConditionSceneOrderEdit::Create,
|
||||
"AdvSceneSwitcher.condition.sceneOrder"});
|
||||
|
||||
static std::map<SceneOrderCondition, std::string> sceneOrderConditionTypes = {
|
||||
{SceneOrderCondition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.sceneOrder.type.above"},
|
||||
{SceneOrderCondition::BELOW,
|
||||
"AdvSceneSwitcher.condition.sceneOrder.type.below"},
|
||||
{SceneOrderCondition::POSITION,
|
||||
"AdvSceneSwitcher.condition.sceneOrder.type.position"},
|
||||
};
|
||||
|
||||
struct PosInfo {
|
||||
std::string name;
|
||||
std::vector<int> pos = {};
|
||||
int curPos = 0;
|
||||
};
|
||||
|
||||
static bool getSceneItemPositions(obs_scene_t *, obs_sceneitem_t *item,
|
||||
void *ptr)
|
||||
{
|
||||
PosInfo *posInfo = reinterpret_cast<PosInfo *>(ptr);
|
||||
auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item));
|
||||
if (posInfo->name == sourceName) {
|
||||
posInfo->pos.push_back(posInfo->curPos);
|
||||
}
|
||||
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, getSceneItemPositions, ptr);
|
||||
}
|
||||
posInfo->curPos += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isAbove(std::vector<int> &v1, std::vector<int> &v2)
|
||||
{
|
||||
for (int i : v1) {
|
||||
for (int j : v2) {
|
||||
if (i > j) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isBelow(std::vector<int> &v1, std::vector<int> &v2)
|
||||
{
|
||||
for (int i : v1) {
|
||||
for (int j : v2) {
|
||||
if (i < j) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionSceneOrder::CheckCondition()
|
||||
{
|
||||
if (!_source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene(false));
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name1 = GetWeakSourceName(_source);
|
||||
auto name2 = GetWeakSourceName(_source2);
|
||||
PosInfo pos1 = {name1};
|
||||
PosInfo pos2 = {name2};
|
||||
obs_scene_enum_items(scene, getSceneItemPositions, &pos1);
|
||||
obs_scene_enum_items(scene, getSceneItemPositions, &pos2);
|
||||
|
||||
switch (_condition) {
|
||||
case SceneOrderCondition::ABOVE:
|
||||
ret = isAbove(pos1.pos, pos2.pos);
|
||||
break;
|
||||
case SceneOrderCondition::BELOW:
|
||||
ret = isBelow(pos1.pos, pos2.pos);
|
||||
break;
|
||||
case SceneOrderCondition::POSITION:
|
||||
for (int p : pos1.pos) {
|
||||
if (p == _position)
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
obs_source_release(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MacroConditionSceneOrder::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_scene.Save(obj);
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_string(obj, "source2",
|
||||
GetWeakSourceName(_source2).c_str());
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_int(obj, "position", _position);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionSceneOrder::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_scene.Load(obj);
|
||||
const char *sourceName = obs_data_get_string(obj, "source");
|
||||
_source = GetWeakSourceByName(sourceName);
|
||||
const char *source2Name = obs_data_get_string(obj, "source2");
|
||||
_source2 = GetWeakSourceByName(source2Name);
|
||||
_condition = static_cast<SceneOrderCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_position = obs_data_get_int(obj, "position");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionSceneOrder::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
std::string header =
|
||||
_scene.ToString() + " - " + GetWeakSourceName(_source);
|
||||
if (_source2 && _condition != SceneOrderCondition::POSITION) {
|
||||
header += " - " + GetWeakSourceName(_source2);
|
||||
}
|
||||
return header;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : sceneOrderConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionSceneOrderEdit::MacroConditionSceneOrderEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionSceneOrder> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, true);
|
||||
_sources = new QComboBox();
|
||||
_sources2 = new QComboBox();
|
||||
_conditions = new QComboBox();
|
||||
_position = new QSpinBox();
|
||||
_posInfo = new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.sceneOrder.positionInfo"));
|
||||
|
||||
populateConditionSelection(_conditions);
|
||||
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SourceChanged(const QString &)));
|
||||
QWidget::connect(_sources2, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(Source2Changed(const QString &)));
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_position, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(PositionChanged(int)));
|
||||
|
||||
auto entryLayout = new QHBoxLayout();
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes}, {"{{sources}}", _sources},
|
||||
{"{{sources2}}", _sources2}, {"{{conditions}}", _conditions},
|
||||
{"{{position}}", _position},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.sceneOrder.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_posInfo);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
_sources->clear();
|
||||
_sources2->clear();
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
populateSceneItemSelection(_sources2, _entryData->_scene);
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::SourceChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::Source2Changed(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source2 = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::ConditionChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_condition = static_cast<SceneOrderCondition>(index);
|
||||
SetWidgetVisibility(_entryData->_condition ==
|
||||
SceneOrderCondition::POSITION);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::PositionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_position = value;
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::SetWidgetVisibility(bool showPos)
|
||||
{
|
||||
_sources2->setVisible(!showPos);
|
||||
_position->setVisible(showPos);
|
||||
_posInfo->setVisible(showPos);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
populateSceneItemSelection(_sources, _entryData->_scene);
|
||||
populateSceneItemSelection(_sources2, _entryData->_scene);
|
||||
_sources->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source).c_str());
|
||||
_sources2->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_source2).c_str());
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
SetWidgetVisibility(_entryData->_condition ==
|
||||
SceneOrderCondition::POSITION);
|
||||
}
|
||||
@@ -19,14 +19,9 @@ bool MacroConditionScene::CheckCondition()
|
||||
{
|
||||
bool sceneMatch = false;
|
||||
if (_type == SceneType::CURRENT) {
|
||||
obs_source_t *rawScene = obs_frontend_get_current_scene();
|
||||
OBSWeakSource currentScene =
|
||||
obs_source_get_weak_source(rawScene);
|
||||
sceneMatch = currentScene == _scene;
|
||||
obs_weak_source_release(currentScene);
|
||||
obs_source_release(rawScene);
|
||||
sceneMatch = switcher->currentScene == _scene.GetScene(false);
|
||||
} else {
|
||||
sceneMatch = switcher->previousScene == _scene;
|
||||
sceneMatch = switcher->previousScene == _scene.GetScene(false);
|
||||
}
|
||||
|
||||
return sceneMatch;
|
||||
@@ -35,7 +30,7 @@ bool MacroConditionScene::CheckCondition()
|
||||
bool MacroConditionScene::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
|
||||
_scene.Save(obj);
|
||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||
return true;
|
||||
}
|
||||
@@ -43,11 +38,16 @@ bool MacroConditionScene::Save(obs_data_t *obj)
|
||||
bool MacroConditionScene::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_scene = GetWeakSourceByName(obs_data_get_string(obj, "scene"));
|
||||
_scene.Load(obj);
|
||||
_type = static_cast<SceneType>(obs_data_get_int(obj, "type"));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionScene::GetShortDesc()
|
||||
{
|
||||
return _scene.ToString();
|
||||
}
|
||||
|
||||
static inline void populateTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : sceneTypes) {
|
||||
@@ -59,21 +59,19 @@ MacroConditionSceneEdit::MacroConditionSceneEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionScene> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_sceneSelection = new QComboBox();
|
||||
_scenes = new SceneSelectionWidget(window(), false, false, false);
|
||||
_sceneType = new QComboBox();
|
||||
|
||||
QWidget::connect(_sceneSelection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(SceneChanged(const QString &)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sceneType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(TypeChanged(int)));
|
||||
|
||||
populateSceneSelection(_sceneSelection);
|
||||
populateTypeSelection(_sceneType);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _sceneSelection},
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sceneType}}", _sceneType},
|
||||
};
|
||||
placeWidgets(obs_module_text("AdvSceneSwitcher.condition.scene.entry"),
|
||||
@@ -85,14 +83,16 @@ MacroConditionSceneEdit::MacroConditionSceneEdit(
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionSceneEdit::SceneChanged(const QString &text)
|
||||
void MacroConditionSceneEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_scene = GetWeakSourceByQString(text);
|
||||
_entryData->_scene = s;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionSceneEdit::TypeChanged(int value)
|
||||
@@ -111,7 +111,6 @@ void MacroConditionSceneEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
|
||||
_sceneSelection->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_scene).c_str());
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sceneType->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
}
|
||||
|
||||
@@ -21,23 +21,6 @@ static std::map<SourceCondition, std::string> sourceConditionTypes = {
|
||||
"AdvSceneSwitcher.condition.source.type.settings"},
|
||||
};
|
||||
|
||||
bool checkSettings(const OBSWeakSource &source, const std::string &settings,
|
||||
bool useRegex)
|
||||
{
|
||||
bool ret = false;
|
||||
std::string currentSettings = getSourceSettings(source);
|
||||
if (useRegex) {
|
||||
try {
|
||||
std::regex expr(settings);
|
||||
ret = std::regex_match(currentSettings, expr);
|
||||
} catch (const std::regex_error &) {
|
||||
}
|
||||
} else {
|
||||
ret = currentSettings == settings;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MacroConditionSource::CheckCondition()
|
||||
{
|
||||
if (!_source) {
|
||||
@@ -55,7 +38,7 @@ bool MacroConditionSource::CheckCondition()
|
||||
ret = obs_source_showing(s);
|
||||
break;
|
||||
case SourceCondition::SETTINGS:
|
||||
ret = checkSettings(_source, _settings, _regex);
|
||||
ret = compareSourceSettings(_source, _settings, _regex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -72,6 +55,7 @@ bool MacroConditionSource::Save(obs_data_t *obj)
|
||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
obs_data_set_string(obj, "settings", _settings.c_str());
|
||||
obs_data_set_bool(obj, "regex", _regex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -83,9 +67,18 @@ bool MacroConditionSource::Load(obs_data_t *obj)
|
||||
_condition = static_cast<SourceCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_settings = obs_data_get_string(obj, "settings");
|
||||
_regex = obs_data_get_bool(obj, "regex");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionSource::GetShortDesc()
|
||||
{
|
||||
if (_source) {
|
||||
return GetWeakSourceName(_source);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : sourceConditionTypes) {
|
||||
@@ -155,6 +148,8 @@ void MacroConditionSourceEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_source = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionSourceEdit::ConditionChanged(int index)
|
||||
@@ -176,7 +171,7 @@ void MacroConditionSourceEdit::GetSettingsClicked()
|
||||
}
|
||||
|
||||
_settings->setPlainText(
|
||||
QString::fromStdString(getSourceSettings(_entryData->_source)));
|
||||
fromatJsonString(getSourceSettings(_entryData->_source)));
|
||||
}
|
||||
|
||||
void MacroConditionSourceEdit::SettingsChanged()
|
||||
|
||||
159
src/macro-condition-timer.cpp
Normal file
159
src/macro-condition-timer.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-timer.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionTimer::id = "timer";
|
||||
|
||||
bool MacroConditionTimer::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionTimer::id,
|
||||
{MacroConditionTimer::Create, MacroConditionTimerEdit::Create,
|
||||
"AdvSceneSwitcher.condition.timer", false});
|
||||
|
||||
// TODO: Remove in future version - just added for backward compatibility
|
||||
static const std::string idOld = "interval";
|
||||
static bool oldRegisterd = MacroConditionFactory::Register(
|
||||
idOld, {MacroConditionTimer::Create, MacroConditionTimerEdit::Create,
|
||||
"AdvSceneSwitcher.condition.timer", false});
|
||||
|
||||
bool MacroConditionTimer::CheckCondition()
|
||||
{
|
||||
if (_duration.DurationReached()) {
|
||||
if (!_oneshot) {
|
||||
_duration.Reset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionTimer::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_duration.Save(obj);
|
||||
obs_data_set_bool(obj, "oneshot", _oneshot);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionTimer::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_duration.Load(obj);
|
||||
if (!obs_data_has_user_value(obj, "oneshot")) {
|
||||
_oneshot = false;
|
||||
} else {
|
||||
_oneshot = obs_data_get_bool(obj, "oneshot");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MacroConditionTimerEdit::MacroConditionTimerEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionTimer> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_duration = new DurationSelection();
|
||||
_autoReset = new QCheckBox();
|
||||
_reset = new QPushButton(
|
||||
obs_module_text("AdvSceneSwitcher.condition.timer.reset"));
|
||||
_remaining = new QLabel();
|
||||
|
||||
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||
SLOT(DurationChanged(double)));
|
||||
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||
SLOT(DurationUnitChanged(DurationUnit)));
|
||||
QWidget::connect(_reset, SIGNAL(clicked()), this, SLOT(ResetClicked()));
|
||||
QWidget::connect(_autoReset, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(AutoResetChanged(int)));
|
||||
|
||||
auto line1Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{duration}}", _duration},
|
||||
{"{{autoReset}}", _autoReset},
|
||||
{"{{remaining}}", _remaining},
|
||||
{"{{reset}}", _reset},
|
||||
};
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.timer.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
auto line2Layout = new QHBoxLayout;
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.timer.entry.line2"),
|
||||
line2Layout, widgetPlaceholders);
|
||||
auto line3Layout = new QHBoxLayout;
|
||||
placeWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.timer.entry.line3"),
|
||||
line3Layout, widgetPlaceholders);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
mainLayout->addLayout(line3Layout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
|
||||
connect(&timer, SIGNAL(timeout()), this, SLOT(UpdateTimeRemaining()));
|
||||
timer.start(1000);
|
||||
}
|
||||
|
||||
void MacroConditionTimerEdit::DurationChanged(double seconds)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.seconds = seconds;
|
||||
}
|
||||
|
||||
void MacroConditionTimerEdit::DurationUnitChanged(DurationUnit unit)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.displayUnit = unit;
|
||||
}
|
||||
|
||||
void MacroConditionTimerEdit::AutoResetChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_oneshot = !state;
|
||||
}
|
||||
|
||||
void MacroConditionTimerEdit::ResetClicked()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_duration.Reset();
|
||||
}
|
||||
|
||||
void MacroConditionTimerEdit::UpdateTimeRemaining()
|
||||
{
|
||||
if (!_entryData) {
|
||||
_remaining->setText("-");
|
||||
return;
|
||||
}
|
||||
_remaining->setText(
|
||||
QString::number(_entryData->_duration.TimeRemaining()));
|
||||
}
|
||||
|
||||
void MacroConditionTimerEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
_autoReset->setChecked(!_entryData->_oneshot);
|
||||
}
|
||||
@@ -76,6 +76,14 @@ bool MacroConditionVideo::Load(obs_data_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionVideo::GetShortDesc()
|
||||
{
|
||||
if (_videoSource) {
|
||||
return GetWeakSourceName(_videoSource);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacroConditionVideo::GetScreenshot()
|
||||
{
|
||||
auto source = obs_weak_source_get_source(_videoSource);
|
||||
@@ -204,6 +212,8 @@ void MacroConditionVideoEdit::SourceChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_videoSource = GetWeakSourceByQString(text);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionVideoEdit::ConditionChanged(int cond)
|
||||
|
||||
101
src/macro-condition-virtual-cam.cpp
Normal file
101
src/macro-condition-virtual-cam.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "headers/macro-condition-edit.hpp"
|
||||
#include "headers/macro-condition-virtual-cam.hpp"
|
||||
#include "headers/utility.hpp"
|
||||
#include "headers/advanced-scene-switcher.hpp"
|
||||
|
||||
const std::string MacroConditionVCam::id = "virtual_cam";
|
||||
|
||||
bool MacroConditionVCam::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionVCam::id,
|
||||
{MacroConditionVCam::Create, MacroConditionVCamEdit::Create,
|
||||
"AdvSceneSwitcher.condition.virtualCamera"});
|
||||
|
||||
static std::map<VCamState, std::string> VCamStates = {
|
||||
{VCamState::STOP,
|
||||
"AdvSceneSwitcher.condition.virtualCamera.state.stop"},
|
||||
{VCamState::START,
|
||||
"AdvSceneSwitcher.condition.virtualCamera.state.start"},
|
||||
};
|
||||
|
||||
bool MacroConditionVCam::CheckCondition()
|
||||
{
|
||||
bool stateMatch = false;
|
||||
switch (_state) {
|
||||
case VCamState::STOP:
|
||||
stateMatch = !obs_frontend_virtualcam_active();
|
||||
break;
|
||||
case VCamState::START:
|
||||
stateMatch = obs_frontend_virtualcam_active();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return stateMatch;
|
||||
}
|
||||
|
||||
bool MacroConditionVCam::Save(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_int(obj, "state", static_cast<int>(_state));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionVCam::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_state = static_cast<VCamState>(obs_data_get_int(obj, "state"));
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateStateSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : VCamStates) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionVCamEdit::MacroConditionVCamEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionVCam> entryData)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_states = new QComboBox();
|
||||
|
||||
QWidget::connect(_states, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(StateChanged(int)));
|
||||
|
||||
populateStateSelection(_states);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{states}}", _states},
|
||||
};
|
||||
|
||||
placeWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.virtualCamera.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionVCamEdit::StateChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_state = static_cast<VCamState>(value);
|
||||
}
|
||||
|
||||
void MacroConditionVCamEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_states->setCurrentIndex(static_cast<int>(_entryData->_state));
|
||||
}
|
||||
@@ -47,11 +47,14 @@ bool MacroConditionWindow::CheckWindowTitleSwitchRegex(
|
||||
return match;
|
||||
}
|
||||
|
||||
bool foregroundWindowChanged()
|
||||
{
|
||||
return switcher->currentTitle != switcher->lastTitle;
|
||||
}
|
||||
|
||||
bool MacroConditionWindow::CheckCondition()
|
||||
{
|
||||
std::string currentWindowTitle;
|
||||
GetCurrentWindowTitle(currentWindowTitle);
|
||||
|
||||
std::string currentWindowTitle = switcher->currentTitle;
|
||||
std::vector<std::string> windowList;
|
||||
GetWindowList(windowList);
|
||||
|
||||
@@ -64,6 +67,7 @@ bool MacroConditionWindow::CheckCondition()
|
||||
match = CheckWindowTitleSwitchRegex(currentWindowTitle,
|
||||
windowList);
|
||||
}
|
||||
match = match && (!_windowFocusChanged || foregroundWindowChanged());
|
||||
|
||||
return match;
|
||||
}
|
||||
@@ -75,6 +79,7 @@ bool MacroConditionWindow::Save(obs_data_t *obj)
|
||||
obs_data_set_bool(obj, "fullscreen", _fullscreen);
|
||||
obs_data_set_bool(obj, "maximized", _maximized);
|
||||
obs_data_set_bool(obj, "focus", _focus);
|
||||
obs_data_set_bool(obj, "windowFocusChanged", _windowFocusChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,9 +90,15 @@ bool MacroConditionWindow::Load(obs_data_t *obj)
|
||||
_fullscreen = obs_data_get_bool(obj, "fullscreen");
|
||||
_maximized = obs_data_get_bool(obj, "maximized");
|
||||
_focus = obs_data_get_bool(obj, "focus");
|
||||
_windowFocusChanged = obs_data_get_bool(obj, "windowFocusChanged");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionWindow::GetShortDesc()
|
||||
{
|
||||
return _window;
|
||||
}
|
||||
|
||||
MacroConditionWindowEdit::MacroConditionWindowEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionWindow> entryData)
|
||||
: QWidget(parent)
|
||||
@@ -99,6 +110,7 @@ MacroConditionWindowEdit::MacroConditionWindowEdit(
|
||||
_fullscreen = new QCheckBox();
|
||||
_maximized = new QCheckBox();
|
||||
_focused = new QCheckBox();
|
||||
_windowFocusChanged = new QCheckBox();
|
||||
|
||||
QWidget::connect(_windowSelection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
@@ -108,7 +120,9 @@ MacroConditionWindowEdit::MacroConditionWindowEdit(
|
||||
QWidget::connect(_maximized, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(MaximizedChanged(int)));
|
||||
QWidget::connect(_focused, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(FocusChanged(int)));
|
||||
SLOT(FocusedChanged(int)));
|
||||
QWidget::connect(_windowFocusChanged, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(WindowFocusChanged(int)));
|
||||
|
||||
populateWindowSelection(_windowSelection);
|
||||
|
||||
@@ -117,6 +131,7 @@ MacroConditionWindowEdit::MacroConditionWindowEdit(
|
||||
{"{{fullscreen}}", _fullscreen},
|
||||
{"{{maximized}}", _maximized},
|
||||
{"{{focused}}", _focused},
|
||||
{"{{windowFocusChanged}}", _windowFocusChanged},
|
||||
};
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
@@ -145,6 +160,8 @@ void MacroConditionWindowEdit::WindowChanged(const QString &text)
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_window = text.toStdString();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionWindowEdit::FullscreenChanged(int state)
|
||||
@@ -167,7 +184,7 @@ void MacroConditionWindowEdit::MaximizedChanged(int state)
|
||||
_entryData->_maximized = state;
|
||||
}
|
||||
|
||||
void MacroConditionWindowEdit::FocusChanged(int state)
|
||||
void MacroConditionWindowEdit::FocusedChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
@@ -177,6 +194,16 @@ void MacroConditionWindowEdit::FocusChanged(int state)
|
||||
_entryData->_focus = state;
|
||||
}
|
||||
|
||||
void MacroConditionWindowEdit::WindowFocusChanged(int state)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->_windowFocusChanged = state;
|
||||
}
|
||||
|
||||
void MacroConditionWindowEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
@@ -187,4 +214,5 @@ void MacroConditionWindowEdit::UpdateEntryData()
|
||||
_fullscreen->setChecked(_entryData->_fullscreen);
|
||||
_maximized->setChecked(_entryData->_maximized);
|
||||
_focused->setChecked(_entryData->_focus);
|
||||
_windowFocusChanged->setChecked(_entryData->_windowFocusChanged);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ void AdvSceneSwitcher::on_macroUp_clicked()
|
||||
|
||||
iter_swap(switcher->macros.begin() + index,
|
||||
switcher->macros.begin() + index - 1);
|
||||
|
||||
for (auto &m : switcher->macros) {
|
||||
m.ResolveMacroRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +122,10 @@ void AdvSceneSwitcher::on_macroDown_clicked()
|
||||
|
||||
iter_swap(switcher->macros.begin() + index,
|
||||
switcher->macros.begin() + index + 1);
|
||||
|
||||
for (auto &m : switcher->macros) {
|
||||
m.ResolveMacroRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user