mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 12:45:28 -05:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed75a221fe | ||
|
|
7b48cb2b8d | ||
|
|
9d4c8ab475 | ||
|
|
3d61ea7d25 | ||
|
|
99c8a46296 | ||
|
|
7e1d20031c | ||
|
|
0e4b000fb1 | ||
|
|
fc2451ae08 | ||
|
|
be44577967 | ||
|
|
3480ff238e | ||
|
|
ee68427036 | ||
|
|
37c32dd1ed | ||
|
|
c05a92d417 | ||
|
|
d72a0c0d38 | ||
|
|
235b31fccc | ||
|
|
286f781f4d | ||
|
|
b7516cac5b | ||
|
|
45967a090f | ||
|
|
687fb4623e | ||
|
|
4157ae4ed2 | ||
|
|
5e1469b0d8 | ||
|
|
b3bde6c59f | ||
|
|
032f5e2fe9 | ||
|
|
91c053dfd8 | ||
|
|
1f1ef4ca03 | ||
|
|
7cc44b4470 | ||
|
|
54356d9410 | ||
|
|
defbdf8b7a | ||
|
|
a01af6cfc3 | ||
|
|
4d9c7f1054 | ||
|
|
ced36e2b5b | ||
|
|
d2749f29b0 | ||
|
|
b78c8bc1de | ||
|
|
cc4a3560d8 | ||
|
|
3ab2ea9e66 | ||
|
|
69b82ee2a3 | ||
|
|
f14e6bf252 | ||
|
|
e51ae79b4c | ||
|
|
8f55856fd5 | ||
|
|
a360d53419 | ||
|
|
d28164d02f | ||
|
|
f723212394 | ||
|
|
a0cb08d18f | ||
|
|
d18044b764 | ||
|
|
406b5d61f5 | ||
|
|
9a4eef4a83 | ||
|
|
efaf9a2ef3 | ||
|
|
edb2952fd6 | ||
|
|
088828a351 | ||
|
|
e359b7fa00 | ||
|
|
44fc5177d6 | ||
|
|
604a27141f | ||
|
|
fd65a84d7d | ||
|
|
966b389807 | ||
|
|
a6bcce5a63 | ||
|
|
530fbdd282 | ||
|
|
54f1051456 | ||
|
|
d136bf5561 | ||
|
|
5cba948e02 | ||
|
|
ab922f6735 | ||
|
|
d71c87535f | ||
|
|
ce501bd972 | ||
|
|
ec5944f53c | ||
|
|
5e64e0bbaa | ||
|
|
e16f1d732d | ||
|
|
cdacfc946c | ||
|
|
26e854f0a3 | ||
|
|
2bc89364b2 | ||
|
|
e080d2de9b | ||
|
|
ca1262aeb7 | ||
|
|
cbc95e2095 | ||
|
|
9c5051cbf8 | ||
|
|
e6ca3390a2 | ||
|
|
e74b531905 |
@@ -120,14 +120,16 @@ target_sources(
|
||||
lib/macro/macro-export-import-dialog.hpp
|
||||
lib/macro/macro-helpers.cpp
|
||||
lib/macro/macro-helpers.hpp
|
||||
lib/macro/macro-input.cpp
|
||||
lib/macro/macro-input.hpp
|
||||
lib/macro/macro-list.cpp
|
||||
lib/macro/macro-list.hpp
|
||||
lib/macro/macro-properties.cpp
|
||||
lib/macro/macro-properties.hpp
|
||||
lib/macro/macro-ref.cpp
|
||||
lib/macro/macro-ref.hpp
|
||||
lib/macro/macro-run-button.cpp
|
||||
lib/macro/macro-run-button.hpp
|
||||
lib/macro/macro-segment-copy-paste.cpp
|
||||
lib/macro/macro-segment-copy-paste.hpp
|
||||
lib/macro/macro-segment-list.cpp
|
||||
lib/macro/macro-segment-list.hpp
|
||||
lib/macro/macro-segment-selection.cpp
|
||||
@@ -136,6 +138,8 @@ target_sources(
|
||||
lib/macro/macro-segment.hpp
|
||||
lib/macro/macro-selection.cpp
|
||||
lib/macro/macro-selection.hpp
|
||||
lib/macro/macro-settings.cpp
|
||||
lib/macro/macro-settings.hpp
|
||||
lib/macro/macro-tab.cpp
|
||||
lib/macro/macro-tree.cpp
|
||||
lib/macro/macro-tree.hpp
|
||||
@@ -145,8 +149,10 @@ target_sources(
|
||||
# Utility function sources
|
||||
target_sources(
|
||||
${LIB_NAME}
|
||||
PRIVATE lib/utils/action-queue.cpp
|
||||
lib/utils/action-queue.hpp
|
||||
PRIVATE lib/queue/action-queue.cpp
|
||||
lib/queue/action-queue.hpp
|
||||
lib/queue/action-queue-tab.cpp
|
||||
lib/queue/action-queue-tab.hpp
|
||||
lib/utils/backup.cpp
|
||||
lib/utils/backup.hpp
|
||||
lib/utils/curl-helper.cpp
|
||||
@@ -162,10 +168,14 @@ target_sources(
|
||||
lib/utils/file-selection.hpp
|
||||
lib/utils/filter-combo-box.cpp
|
||||
lib/utils/filter-combo-box.hpp
|
||||
lib/utils/help-icon.hpp
|
||||
lib/utils/help-icon.cpp
|
||||
lib/utils/item-selection-helpers.cpp
|
||||
lib/utils/item-selection-helpers.hpp
|
||||
lib/utils/layout-helpers.cpp
|
||||
lib/utils/layout-helpers.hpp
|
||||
lib/utils/list-editor.cpp
|
||||
lib/utils/list-editor.hpp
|
||||
lib/utils/log-helper.cpp
|
||||
lib/utils/log-helper.hpp
|
||||
lib/utils/math-helpers.cpp
|
||||
@@ -191,6 +201,10 @@ target_sources(
|
||||
lib/utils/regex-config.hpp
|
||||
lib/utils/resizing-text-edit.cpp
|
||||
lib/utils/resizing-text-edit.hpp
|
||||
lib/utils/resource-table.cpp
|
||||
lib/utils/resource-table.hpp
|
||||
lib/utils/resource-table-hotkey-handler.cpp
|
||||
lib/utils/resource-table-hotkey-handler.hpp
|
||||
lib/utils/scene-selection.cpp
|
||||
lib/utils/scene-selection.hpp
|
||||
lib/utils/scene-switch-helpers.cpp
|
||||
@@ -213,10 +227,14 @@ target_sources(
|
||||
lib/utils/splitter-helpers.hpp
|
||||
lib/utils/status-control.cpp
|
||||
lib/utils/status-control.hpp
|
||||
lib/utils/string-list.cpp
|
||||
lib/utils/string-list.hpp
|
||||
lib/utils/switch-button.cpp
|
||||
lib/utils/switch-button.hpp
|
||||
lib/utils/sync-helpers.cpp
|
||||
lib/utils/sync-helpers.hpp
|
||||
lib/utils/tab-helpers.cpp
|
||||
lib/utils/tab-helpers.hpp
|
||||
lib/utils/temp-variable.cpp
|
||||
lib/utils/temp-variable.hpp
|
||||
lib/utils/ui-helpers.cpp
|
||||
@@ -234,6 +252,7 @@ target_sources(
|
||||
lib/variables/variable-string.cpp
|
||||
lib/variables/variable-string.hpp
|
||||
lib/variables/variable-tab.cpp
|
||||
lib/variables/variable-tab.hpp
|
||||
lib/variables/variable-text-edit.cpp
|
||||
lib/variables/variable-text-edit.hpp
|
||||
lib/variables/variable.cpp
|
||||
@@ -268,6 +287,7 @@ target_include_directories(
|
||||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lib/legacy"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lib/macro"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lib/queue"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lib/utils"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lib/variables"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/forms")
|
||||
@@ -325,6 +345,9 @@ if(OS_WINDOWS)
|
||||
if(MSVC)
|
||||
target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267
|
||||
/bigobj)
|
||||
|
||||
# Workaround for MSVC incompatibility in CI environment
|
||||
add_compile_definitions(${target_name} _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
|
||||
endif()
|
||||
target_sources(${LIB_NAME} PRIVATE lib/win/advanced-scene-switcher-win.cpp)
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
|
||||
@@ -12,8 +12,14 @@ if(NOT DEFINED PLUGIN_BUILD_NUMBER AND EXISTS "${_BUILD_NUMBER_CACHE}")
|
||||
file(READ "${_BUILD_NUMBER_CACHE}" PLUGIN_BUILD_NUMBER)
|
||||
math(EXPR PLUGIN_BUILD_NUMBER "${PLUGIN_BUILD_NUMBER}+1")
|
||||
elseif(NOT DEFINED PLUGIN_BUILD_NUMBER)
|
||||
if($ENV{CI} AND $ENV{GITHUB_RUN_ID})
|
||||
set(PLUGIN_BUILD_NUMBER "$ENV{GITHUB_RUN_ID}")
|
||||
if($ENV{CI})
|
||||
if($ENV{GITHUB_RUN_ID})
|
||||
set(PLUGIN_BUILD_NUMBER "$ENV{GITHUB_RUN_ID}")
|
||||
elseif($ENV{GITLAB_RUN_ID})
|
||||
set(PLUGIN_BUILD_NUMBER "$ENV{GITLAB_RUN_ID}")
|
||||
else()
|
||||
set(PLUGIN_BUILD_NUMBER "1")
|
||||
endif()
|
||||
else()
|
||||
set(PLUGIN_BUILD_NUMBER "1")
|
||||
endif()
|
||||
|
||||
@@ -68,9 +68,14 @@ else()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)
|
||||
# Disable warning for https://github.com/WarmUpTill/SceneSwitcher/issues/1091
|
||||
add_compile_options(-Wno-error=psabi)
|
||||
|
||||
# Disable false-positive warning in GCC 12.1.0 and later
|
||||
add_compile_options(-Wno-error=maybe-uninitialized)
|
||||
add_compile_options(-Wno-error=stringop-overflow)
|
||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.1.0)
|
||||
add_compile_options(-Wno-error=maybe-uninitialized)
|
||||
add_compile_options(-Wno-error=stringop-overflow)
|
||||
endif()
|
||||
|
||||
# Add warning for infinite recursion (added in GCC 12)
|
||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0.0)
|
||||
|
||||
@@ -287,8 +287,8 @@ AdvSceneSwitcher.condition.sceneOrder.entry="Auf{{scenes}}{{sources}}{{condition
|
||||
AdvSceneSwitcher.condition.hotkey="Hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.name="Makro-Trigger-Hotkey"
|
||||
AdvSceneSwitcher.condition.hotkey.tip="Hinweis: Die Tastenkombinationen für diesen Hotkey können in den OBS-Einstellungen konfiguriert werden"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line1="Hotkey ist gedrückt"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line2="Name: {{name}}"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.keyState="Hotkey ist{{keyState}}"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.name="Name:{{name}}"
|
||||
AdvSceneSwitcher.condition.replay="Replay Buffer"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="Replay Buffer gestoppt"
|
||||
AdvSceneSwitcher.condition.replay.state.started="Replay Buffer gestartet"
|
||||
@@ -469,7 +469,6 @@ AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen"
|
||||
AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen"
|
||||
AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Plugin-Status"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"
|
||||
|
||||
@@ -88,6 +88,47 @@ AdvSceneSwitcher.variableTab.lastChanged.text="%1 seconds ago"
|
||||
AdvSceneSwitcher.variableTab.lastChanged.text.none="No change since launch"
|
||||
AdvSceneSwitcher.variableTab.lastChanged.tooltip="Times changed: %1\n\nPrevious value: %2"
|
||||
|
||||
; Action Queue Tab
|
||||
AdvSceneSwitcher.actionQueueTab.title="Action Queues"
|
||||
AdvSceneSwitcher.actionQueueTab.help="Action queues are executed sequentially but in parallel to the reset of the macro system.\nThe first action added to the queue will be the first one to be processed.\n\nClick on the highlighted plus symbol to add a new queue."
|
||||
AdvSceneSwitcher.actionQueueTab.queueAddButton.tooltip="Add new action queue"
|
||||
AdvSceneSwitcher.actionQueueTab.queueRemoveButton.tooltip="Remove selected action queues"
|
||||
AdvSceneSwitcher.actionQueueTab.name.header="Name"
|
||||
AdvSceneSwitcher.actionQueueTab.size.header="Size"
|
||||
AdvSceneSwitcher.actionQueueTab.isRunning.header="Is running"
|
||||
AdvSceneSwitcher.actionQueueTab.runOnStartup.header="Run on startup"
|
||||
AdvSceneSwitcher.actionQueueTab.yes="Yes"
|
||||
AdvSceneSwitcher.actionQueueTab.no="No"
|
||||
AdvSceneSwitcher.actionQueueTab.removeSingleQueuePopup.text="Are you sure you want to remove \"%1\"?"
|
||||
AdvSceneSwitcher.actionQueueTab.removeMultipleQueuesPopup.text="Are you sure you want to remove %1 action queues?"
|
||||
|
||||
; Websocket Connections Tab
|
||||
AdvSceneSwitcher.websocketConnectionTab.title="Websocket Connections"
|
||||
AdvSceneSwitcher.websocketConnectionTab.help="Websocket connections can be used to communicate with other OBS instances or programs.\n\nClick on the highlighted plus symbol to add a new connection."
|
||||
AdvSceneSwitcher.websocketConnectionTab.websocketConnectionAddButton.tooltip="Add new webscoket connection"
|
||||
AdvSceneSwitcher.websocketConnectionTab.websocketConnectionRemoveButton.tooltip="Remove selected websocket connections"
|
||||
AdvSceneSwitcher.websocketConnectionTab.name.header="Name"
|
||||
AdvSceneSwitcher.websocketConnectionTab.address.header="Address"
|
||||
AdvSceneSwitcher.websocketConnectionTab.port.header="Port"
|
||||
AdvSceneSwitcher.websocketConnectionTab.protocol.header="Is using OBS protocol?"
|
||||
AdvSceneSwitcher.websocketConnectionTab.protocol.yes="Yes"
|
||||
AdvSceneSwitcher.websocketConnectionTab.protocol.no="No"
|
||||
AdvSceneSwitcher.websocketConnectionTab.removeSingleConnectionPopup.text="Are you sure you want to remove \"%1\"?"
|
||||
AdvSceneSwitcher.websocketConnectionTab.removeMultipleConnectionsPopup.text="Are you sure you want to remove %1 connections?"
|
||||
|
||||
; Twitch Connections Tab
|
||||
AdvSceneSwitcher.twitchConnectionTab.title="Twitch Connections"
|
||||
AdvSceneSwitcher.twitchConnectionTab.help="Twitch connections can be used to use Twitch events as triggers to execute actions or perform actions on the linked Twitch account.\n\nClick on the highlighted plus symbol to add a new connection."
|
||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionAddButton.tooltip.tooltip="Add new Twitch connection"
|
||||
AdvSceneSwitcher.twitchConnectionTab.twitchConnectionRemoveButton.tooltip="Remove selected Twitch connections"
|
||||
AdvSceneSwitcher.twitchConnectionTab.name.header="Name"
|
||||
AdvSceneSwitcher.twitchConnectionTab.isValid.header="Is valid?"
|
||||
AdvSceneSwitcher.twitchConnectionTab.permissionCount.header="Number of permissions"
|
||||
AdvSceneSwitcher.twitchConnectionTab.yes="Yes"
|
||||
AdvSceneSwitcher.twitchConnectionTab.no="No"
|
||||
AdvSceneSwitcher.twitchConnectionTab.removeSingleConnectionPopup.text="Are you sure you want to remove \"%1\"?"
|
||||
AdvSceneSwitcher.twitchConnectionTab.removeMultipleConnectionsPopup.text="Are you sure you want to remove %1 Twitch connections?"
|
||||
|
||||
; Macro Tab
|
||||
AdvSceneSwitcher.macroTab.title="Macro"
|
||||
AdvSceneSwitcher.macroTab.macros="Macros"
|
||||
@@ -124,6 +165,7 @@ AdvSceneSwitcher.macroTab.rename="Rename"
|
||||
AdvSceneSwitcher.macroTab.remove="Remove"
|
||||
AdvSceneSwitcher.macroTab.export="Export"
|
||||
AdvSceneSwitcher.macroTab.export.info="Paste the string below into the import dialog to import the selected macros:"
|
||||
AdvSceneSwitcher.macroTab.export.usePlainText="Use plain text"
|
||||
AdvSceneSwitcher.macroTab.import="Import"
|
||||
AdvSceneSwitcher.macroTab.import.info="Paste the export string into the below text box to import macros:"
|
||||
AdvSceneSwitcher.macroTab.import.invalid="Invalid import data provided!"
|
||||
@@ -132,9 +174,18 @@ AdvSceneSwitcher.macroTab.expandAll="Expand all"
|
||||
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
|
||||
AdvSceneSwitcher.macroTab.maximize="Maximize"
|
||||
AdvSceneSwitcher.macroTab.minimize="Minimize"
|
||||
AdvSceneSwitcher.macroTab.segment.useCustomLabel="Use custom label"
|
||||
AdvSceneSwitcher.macroTab.segment.defaultCustomLabel="My label"
|
||||
AdvSceneSwitcher.macroTab.segment.setCustomLabel="Set label ..."
|
||||
AdvSceneSwitcher.macroTab.segment.copy="Copy"
|
||||
AdvSceneSwitcher.macroTab.segment.paste="Paste"
|
||||
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
|
||||
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
|
||||
AdvSceneSwitcher.macroTab.generalSettings="General settings"
|
||||
AdvSceneSwitcher.macroTab.inputSettings="Input settings"
|
||||
AdvSceneSwitcher.macroTab.inputSettings.description="This section will allow you to specify variables, which will be treated as input parameters for the selected macro.\nWhen executing the macro using the \"Macro\" action type, you will have the option to set the values for those variables."
|
||||
AdvSceneSwitcher.macroTab.inputSettings.invalid="<Invalid selection>"
|
||||
AdvSceneSwitcher.macroTab.inputSettings.noInputs="No inputs are defined for the selected macro!\nOpen the settings of the macro to define inputs.\nThe settings button is highlighted above."
|
||||
AdvSceneSwitcher.macroTab.dockSettings="Dock settings"
|
||||
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
|
||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
|
||||
@@ -179,7 +230,7 @@ AdvSceneSwitcher.macroTab.tooltip.elseActionTopButton="Move selected action to t
|
||||
AdvSceneSwitcher.macroTab.tooltip.elseActionUpButton="Move selected action up in the else section"
|
||||
AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton="Move selected action down in the else section"
|
||||
AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton="Move selected action to the bottom in the else section"
|
||||
AdvSceneSwitcher.macroTab.tooltip.openMacroPropertiesButton="Open macro properties"
|
||||
AdvSceneSwitcher.macroTab.tooltip.openMacroSettingsButton="Open macro settings"
|
||||
|
||||
AdvSceneSwitcher.macroDock.pause="Pause"
|
||||
AdvSceneSwitcher.macroDock.unpause="Unpause"
|
||||
@@ -406,11 +457,16 @@ AdvSceneSwitcher.condition.source.type.settingsMatch="Settings match"
|
||||
AdvSceneSwitcher.condition.source.type.settingsChanged="Settings changed"
|
||||
AdvSceneSwitcher.condition.source.type.individualSettingMatches="Setting value matches"
|
||||
AdvSceneSwitcher.condition.source.type.individualSettingChanged="Setting value changed"
|
||||
AdvSceneSwitcher.condition.source.type.width="Width"
|
||||
AdvSceneSwitcher.condition.source.type.height="Height"
|
||||
AdvSceneSwitcher.condition.source.sizeCompare.less="Smaller than"
|
||||
AdvSceneSwitcher.condition.source.sizeCompare.equal="Equals"
|
||||
AdvSceneSwitcher.condition.source.sizeCompare.more="Bigger than"
|
||||
AdvSceneSwitcher.condition.source.refresh="Refresh"
|
||||
AdvSceneSwitcher.condition.source.refreshTooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
||||
AdvSceneSwitcher.condition.source.sceneVisibilityHint="Scene specific visibility can be checked using the \"Scene item visibility\" condition"
|
||||
AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.source.entry.line3="{{regex}}{{getSettings}}"
|
||||
AdvSceneSwitcher.condition.virtualCamera="Virtual camera"
|
||||
@@ -437,10 +493,12 @@ 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.pressed="pressed"
|
||||
AdvSceneSwitcher.condition.hotkey.released="released"
|
||||
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.line1="Hotkey is pressed"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line2="Name:{{name}}"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.keyState="Hotkey is{{keyState}}"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.name="Name:{{name}}"
|
||||
AdvSceneSwitcher.condition.replay="Replay buffer"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="Replay buffer stopped"
|
||||
AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
|
||||
@@ -545,7 +603,7 @@ AdvSceneSwitcher.condition.run="Run"
|
||||
AdvSceneSwitcher.condition.run.entry="Process exits before timeout of{{timeout}}seconds"
|
||||
AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}Check for exit code{{exitCode}}"
|
||||
AdvSceneSwitcher.condition.midi="MIDI"
|
||||
AdvSceneSwitcher.condition.midi.entry="Mesasge was received from{{device}}which matches:"
|
||||
AdvSceneSwitcher.condition.midi.entry="Message was received from{{device}}which matches:"
|
||||
AdvSceneSwitcher.condition.midi.entry.listen="Set MIDI message selection to messages incoming on selected device:{{listenButton}}"
|
||||
AdvSceneSwitcher.condition.display="Display"
|
||||
AdvSceneSwitcher.condition.display.type.displayName="Name of connected displays matches"
|
||||
@@ -634,6 +692,17 @@ AdvSceneSwitcher.condition.clipboard.condition.isImage="Clipboard contains an im
|
||||
AdvSceneSwitcher.condition.clipboard.condition.isURL="Clipboard contains an URL"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.matches="Clipboard content matches"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.entry="{{conditions}}{{regex}}{{urlInfo}}"
|
||||
AdvSceneSwitcher.condition.folder="Folder watch"
|
||||
AdvSceneSwitcher.condition.folder.tooltip="This condition type will allow you to monitor the contents of a folder.\nNote that the monitoring will *not* recursively scan for changes in sub directories within directories of the selected folder!\nNote that if there are several changes during a short period of time, some of the changes might not emit this signal.\nHowever, the last change in the sequence of changes always will."
|
||||
AdvSceneSwitcher.condition.folder.condition.any="Any change happened"
|
||||
AdvSceneSwitcher.condition.folder.condition.fileAdd="A file was added"
|
||||
AdvSceneSwitcher.condition.folder.condition.fileChange="A file was modified"
|
||||
AdvSceneSwitcher.condition.folder.condition.fileRemove="A file was removed"
|
||||
AdvSceneSwitcher.condition.folder.condition.folderAdd="A directory was added"
|
||||
AdvSceneSwitcher.condition.folder.condition.folderRemove="A directory was removed"
|
||||
AdvSceneSwitcher.condition.folder.entry="{{conditions}}in{{folder}}{{tooltip}}"
|
||||
AdvSceneSwitcher.condition.folder.enableFilter="Only evaluate to true, if the changed path matches a patern"
|
||||
AdvSceneSwitcher.condition.folder.entry.filter="{{filter}}{{regex}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.scene="Switch scene"
|
||||
@@ -765,12 +834,24 @@ AdvSceneSwitcher.action.macro="Macro"
|
||||
AdvSceneSwitcher.action.macro.type.pause="Pause"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="Unpause"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
|
||||
AdvSceneSwitcher.action.macro.type.run="Run actions"
|
||||
AdvSceneSwitcher.action.macro.type.run="Run macro"
|
||||
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="Do not consider condition state"
|
||||
AdvSceneSwitcher.action.macro.type.run.conditions.true="Only if conditions evaluate to true"
|
||||
AdvSceneSwitcher.action.macro.type.run.conditions.false="Only if conditions evaluate to false"
|
||||
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState="Reevaluate the condition state before executing this action"
|
||||
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help="The plugin operates in phases:\n * The phase evaluating the macro conditions\n * The phase running macro actions\nMacros executed before this particular action might have side effects on the condition state of macros.\nCheck this option if you want those side effects to be taken into account when evaluating the condition state."
|
||||
AdvSceneSwitcher.action.macro.type.run.actionType.regular="actions"
|
||||
AdvSceneSwitcher.action.macro.type.run.actionType.else="else-actions"
|
||||
AdvSceneSwitcher.action.macro.type.run.skipWhenPaused="Skip execution when macro is paused"
|
||||
AdvSceneSwitcher.action.macro.type.run.setInputs="Set inputs"
|
||||
AdvSceneSwitcher.action.macro.type.run.setInputs.description="Input variables can be defined in the macro settings.\nDefining input variables will allow you to modify the values of variables before an action is executed."
|
||||
AdvSceneSwitcher.action.macro.type.stop="Stop actions"
|
||||
AdvSceneSwitcher.action.macro.type.disableAction="Disable action"
|
||||
AdvSceneSwitcher.action.macro.type.enableAction="Enable action"
|
||||
AdvSceneSwitcher.action.macro.type.toggleAction="Toggle action"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}of{{macros}}"
|
||||
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
|
||||
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Plugin state"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
||||
@@ -915,9 +996,11 @@ AdvSceneSwitcher.action.variable.type.sceneItemCount="Set to scene item count of
|
||||
AdvSceneSwitcher.action.variable.type.stringLength="Set to length of string"
|
||||
AdvSceneSwitcher.action.variable.type.extractJson="Extract json field with name"
|
||||
AdvSceneSwitcher.action.variable.type.setToTempvar="Set to macro property"
|
||||
AdvSceneSwitcher.action.variable.type.setToTempvar.help="This action type will allow you to extract values out of segments of the current macro and assign those values to the selected variable.\nFor example, you can get the current scene name from a scene condition and assign this name to a variable."
|
||||
AdvSceneSwitcher.action.variable.type.sceneItemName="Set to scene item name at index"
|
||||
AdvSceneSwitcher.action.variable.type.padValue="Pad current value"
|
||||
AdvSceneSwitcher.action.variable.type.truncateValue="Truncate current value"
|
||||
AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values"
|
||||
AdvSceneSwitcher.action.variable.truncateOrPadDirection.left="Left"
|
||||
AdvSceneSwitcher.action.variable.truncateOrPadDirection.right="Right"
|
||||
AdvSceneSwitcher.action.variable.askForValuePromptDefault="Assign value to variable \"%1\":"
|
||||
@@ -931,7 +1014,7 @@ AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
||||
AdvSceneSwitcher.action.variable.entry.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}"
|
||||
AdvSceneSwitcher.action.variable.entry.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}"
|
||||
AdvSceneSwitcher.action.variable.entry.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}"
|
||||
AdvSceneSwitcher.action.variable.entry.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}"
|
||||
@@ -997,6 +1080,8 @@ AdvSceneSwitcher.action.queue.entry.add="{{actions}}actions of macro{{macros}}to
|
||||
AdvSceneSwitcher.action.queue.entry.other="{{actions}}queue{{queues}}"
|
||||
AdvSceneSwitcher.action.window="Window"
|
||||
AdvSceneSwitcher.action.window.type.setFocusWindow="Focus window"
|
||||
AdvSceneSwitcher.action.window.type.setFocusWindow.limitation="The focus action can only be performed under certain circumstances"
|
||||
AdvSceneSwitcher.action.window.type.setFocusWindow.limitation.details="At least one of the following conditions must be true:\n OBS is the foreground process.\n There is currently no foreground window, and thus no foreground process.\n OBS received the last input event."
|
||||
AdvSceneSwitcher.action.window.type.maximizeWindow="Maximize window"
|
||||
AdvSceneSwitcher.action.window.type.minimizeWindow="Minimize window"
|
||||
AdvSceneSwitcher.action.window.type.closeWindow="Close window"
|
||||
@@ -1046,6 +1131,7 @@ AdvSceneSwitcher.variable.save="Save / load behavior"
|
||||
AdvSceneSwitcher.variable.save.dontSave="Don't save variable value"
|
||||
AdvSceneSwitcher.variable.save.save="Save variable value"
|
||||
AdvSceneSwitcher.variable.save.default="Set to value"
|
||||
AdvSceneSwitcher.variable.selectionDialog="Select variable:"
|
||||
|
||||
AdvSceneSwitcher.tooltip.availableVariables="Variables are supported, use ${VarName} to retrieve the value of VarName"
|
||||
|
||||
@@ -1672,6 +1758,23 @@ AdvSceneSwitcher.tempVar.streaming.durationSeconds.description="Seconds passed s
|
||||
AdvSceneSwitcher.tempVar.clipboard.text="Clipboard text"
|
||||
AdvSceneSwitcher.tempVar.clipboard.text.description="The text contained in the clipboard.\nWill be empty if the clipboard does not contain text."
|
||||
|
||||
AdvSceneSwitcher.tempVar.file.content="File content"
|
||||
AdvSceneSwitcher.tempVar.file.date="File modification date"
|
||||
|
||||
AdvSceneSwitcher.tempVar.folder.newFiles="New files"
|
||||
AdvSceneSwitcher.tempVar.folder.changedFiles="Changed files"
|
||||
AdvSceneSwitcher.tempVar.folder.removedFiles="Removed files"
|
||||
AdvSceneSwitcher.tempVar.folder.newDirs="New directories"
|
||||
AdvSceneSwitcher.tempVar.folder.removedDirs="Removed directories"
|
||||
|
||||
AdvSceneSwitcher.tempVar.source.width="Source width"
|
||||
AdvSceneSwitcher.tempVar.source.height="Source height"
|
||||
AdvSceneSwitcher.tempVar.source.setting="Setting value"
|
||||
AdvSceneSwitcher.tempVar.source.settings="Settings string"
|
||||
|
||||
AdvSceneSwitcher.tempVar.filter.setting="Setting value"
|
||||
AdvSceneSwitcher.tempVar.filter.settings="Settings string"
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
|
||||
@@ -238,8 +238,7 @@ AdvSceneSwitcher.condition.sceneOrder.entry="En{{scenes}}{{sources}}{{conditions
|
||||
AdvSceneSwitcher.condition.hotkey="Tecla de acceso rápido"
|
||||
AdvSceneSwitcher.condition.hotkey.name="Tecla de acceso directo de activación de macro"
|
||||
AdvSceneSwitcher.condition.hotkey.tip="Nota: puede configurar las combinaciones de teclas para esta tecla de acceso rápido en la ventana de configuración de OBS"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line1="Se presiona la tecla de acceso rápido"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line2="Nombre: {{name}}"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.name="Nombre:{{name}}"
|
||||
AdvSceneSwitcher.condition.replay="Búfer de reproducción"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="Búfer de reproducción detenido"
|
||||
AdvSceneSwitcher.condition.replay.state.started="Búfer de reproducción iniciado"
|
||||
@@ -387,7 +386,6 @@ AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
|
||||
AdvSceneSwitcher.action.macro.type.run="Ejecutar"
|
||||
AdvSceneSwitcher.action.macro.type.stop="Detener"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Estado del complemento"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:"
|
||||
|
||||
@@ -351,8 +351,7 @@ AdvSceneSwitcher.condition.sceneOrder.entry="Sur{{scenes}}{{sources}}{{condition
|
||||
AdvSceneSwitcher.condition.hotkey="Raccourci clavier"
|
||||
AdvSceneSwitcher.condition.hotkey.name="Raccourci clavier de déclenchement de macro"
|
||||
AdvSceneSwitcher.condition.hotkey.tip="Remarque : Vous pouvez configurer les raccourcis clavier pour ce raccourci dans la fenêtre de paramètres d'OBS"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line1="Raccourci clavier est enfoncé"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line2="Nom :{{name}}"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.name="Nom:{{name}}"
|
||||
AdvSceneSwitcher.condition.replay="Tampon de répétition"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="Tampon de répétition arrêté"
|
||||
AdvSceneSwitcher.condition.replay.state.started="Tampon de répétition démarré"
|
||||
|
||||
@@ -315,7 +315,6 @@ AdvSceneSwitcher.action.macro.type.pause="Duraklat"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="Duraklatma"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Sayacı sıfırla"
|
||||
AdvSceneSwitcher.action.macro.type.run="Çalıştır"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Eklenti durumu"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisini durdurun"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:"
|
||||
|
||||
@@ -332,8 +332,7 @@ AdvSceneSwitcher.condition.sceneOrder.entry="在 {{scenes}} {{sources}} {{condit
|
||||
AdvSceneSwitcher.condition.hotkey="热键"
|
||||
AdvSceneSwitcher.condition.hotkey.name="宏触发热键"
|
||||
AdvSceneSwitcher.condition.hotkey.tip="注意:您可以在OBS设置窗口中为此热键配置按键绑定"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line1="热键被按下"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.line2="名称: {{name}}"
|
||||
AdvSceneSwitcher.condition.hotkey.entry.name="名称:{{name}}"
|
||||
AdvSceneSwitcher.condition.replay="回放缓存"
|
||||
AdvSceneSwitcher.condition.replay.state.stopped="回放缓存已停止"
|
||||
AdvSceneSwitcher.condition.replay.state.started="回放缓存已启动"
|
||||
@@ -525,7 +524,6 @@ AdvSceneSwitcher.action.macro.type.unpause="取消暂停"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器"
|
||||
AdvSceneSwitcher.action.macro.type.run="运行操作"
|
||||
AdvSceneSwitcher.action.macro.type.stop="停止操作"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="插件状态"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:"
|
||||
|
||||
@@ -960,7 +960,7 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="macroProperties">
|
||||
<widget class="QPushButton" name="macroSettings">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
@@ -968,7 +968,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.openMacroPropertiesButton</string>
|
||||
<string>AdvSceneSwitcher.macroTab.tooltip.openMacroSettingsButton</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -1602,104 +1602,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="variableTab">
|
||||
<attribute name="title">
|
||||
<string>AdvSceneSwitcher.variableTab.title</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_33">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_25">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableWidget" name="variables">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="cornerButtonEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="variablesHelp">
|
||||
<property name="text">
|
||||
<string>AdvSceneSwitcher.variableTab.help</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_30">
|
||||
<item>
|
||||
<widget class="QPushButton" name="variableAdd">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.variableTab.variableAddButton.tooltip</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">addIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="variableRemove">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AdvSceneSwitcher.variableTab.variableRemoveButton.tooltip</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">removeIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_211">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="networkTab">
|
||||
<attribute name="title">
|
||||
<string>AdvSceneSwitcher.networkTab.title</string>
|
||||
@@ -5131,7 +5033,7 @@
|
||||
<tabstop>runMacro</tabstop>
|
||||
<tabstop>runMacroInParallel</tabstop>
|
||||
<tabstop>runMacroOnChange</tabstop>
|
||||
<tabstop>macroProperties</tabstop>
|
||||
<tabstop>macroSettings</tabstop>
|
||||
<tabstop>conditionsList</tabstop>
|
||||
<tabstop>conditionAdd</tabstop>
|
||||
<tabstop>conditionRemove</tabstop>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "status-control.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
#include "tab-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "version.h"
|
||||
|
||||
@@ -44,7 +45,7 @@ AdvSceneSwitcher::~AdvSceneSwitcher()
|
||||
{
|
||||
if (switcher) {
|
||||
switcher->settingsWindowOpened = false;
|
||||
switcher->lastOpenedTab = ui->tabWidget->currentIndex();
|
||||
SaveLastOpenedTab(ui->tabWidget);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,11 +113,11 @@ void AdvSceneSwitcher::LoadUI()
|
||||
SetupSceneGroupTab();
|
||||
SetupTriggerTab();
|
||||
SetupMacroTab();
|
||||
SetupVariableTab();
|
||||
SetupOtherTabs(ui->tabWidget);
|
||||
|
||||
SetDeprecationWarnings();
|
||||
SetTabOrder();
|
||||
SetCurrentTab();
|
||||
SetTabOrder(ui->tabWidget);
|
||||
SetCurrentTab(ui->tabWidget);
|
||||
RestoreWindowGeo();
|
||||
CheckFirstTimeSetup();
|
||||
|
||||
@@ -145,12 +146,6 @@ bool AdvSceneSwitcher::eventFilter(QObject *obj, QEvent *event)
|
||||
} else if (pressedKey == Qt::Key_Delete) {
|
||||
RemoveSelectedMacros();
|
||||
}
|
||||
} else if (obj == ui->variables && ui->variables->isVisible()) {
|
||||
if (pressedKey == Qt::Key_F2) {
|
||||
OpenSettingsForSelectedVariable();
|
||||
} else if (pressedKey == Qt::Key_Delete) {
|
||||
RemoveSelectedVariables();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +240,7 @@ void SwitcherData::Thread()
|
||||
if (duration.count() < 1) {
|
||||
blog(LOG_INFO,
|
||||
"detected busy loop - refusing to sleep less than 1ms");
|
||||
duration = std::chrono::milliseconds(50);
|
||||
duration = std::chrono::milliseconds(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,9 +522,7 @@ bool SwitcherData::AnySceneTransitionStarted()
|
||||
extern "C" EXPORT void FreeSceneSwitcher()
|
||||
{
|
||||
PlatformCleanup();
|
||||
for (const auto &cleanupStep : switcher->pluginCleanupSteps) {
|
||||
cleanupStep();
|
||||
}
|
||||
RunPluginCleanupSteps();
|
||||
|
||||
delete switcher;
|
||||
switcher = nullptr;
|
||||
@@ -757,15 +750,38 @@ QWidget *GetSettingsWindow()
|
||||
return SettingsWindowIsOpened() ? AdvSceneSwitcher::window : nullptr;
|
||||
}
|
||||
|
||||
void SetupActionQueues();
|
||||
|
||||
extern "C" EXPORT void RunPluginPostLoadSteps()
|
||||
void AdvSceneSwitcher::HighligthMacroSettingsButton(bool enable)
|
||||
{
|
||||
for (const auto &postLoadStep : switcher->pluginPostLoadSteps) {
|
||||
postLoadStep();
|
||||
static QObject *highlight = nullptr;
|
||||
if ((highlight && enable) || (!highlight && !enable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (highlight && !enable) {
|
||||
highlight->deleteLater();
|
||||
highlight = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HighlightUIElementsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
highlight = HighlightWidget(ui->macroSettings, Qt::green);
|
||||
}
|
||||
|
||||
void HighligthMacroSettingsButton(bool enable)
|
||||
{
|
||||
auto window = GetSettingsWindow();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
static_cast<AdvSceneSwitcher *>(window)->HighligthMacroSettingsButton(
|
||||
enable);
|
||||
}
|
||||
|
||||
void SetupActionQueues();
|
||||
|
||||
extern "C" EXPORT void InitSceneSwitcher(obs_module_t *module,
|
||||
translateFunc translate)
|
||||
{
|
||||
@@ -779,9 +795,7 @@ extern "C" EXPORT void InitSceneSwitcher(obs_module_t *module,
|
||||
SetupDock();
|
||||
SetupActionQueues();
|
||||
|
||||
for (const auto &initStep : switcher->pluginInitSteps) {
|
||||
initStep();
|
||||
}
|
||||
RunPluginInitSteps();
|
||||
|
||||
obs_frontend_add_save_callback(SaveSceneSwitcher, nullptr);
|
||||
obs_frontend_add_event_callback(OBSEvent, switcher);
|
||||
|
||||
@@ -12,6 +12,7 @@ class MacroActionEdit;
|
||||
class MacroConditionEdit;
|
||||
class Duration;
|
||||
class SequenceWidget;
|
||||
enum class LogicType;
|
||||
struct SceneGroup;
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -34,8 +35,6 @@ public:
|
||||
|
||||
void LoadUI();
|
||||
|
||||
void SetTabOrder();
|
||||
void SetCurrentTab();
|
||||
void RestoreWindowGeo();
|
||||
void CheckFirstTimeSetup();
|
||||
|
||||
@@ -59,7 +58,6 @@ public slots:
|
||||
void on_autoStartEvent_currentIndexChanged(int index);
|
||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
||||
void on_checkInterval_valueChanged(int value);
|
||||
void on_tabMoved(int from, int to);
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
void on_exportSettings_clicked();
|
||||
void on_importSettings_clicked();
|
||||
@@ -98,6 +96,7 @@ public:
|
||||
void SetConditionData(Macro &m);
|
||||
void SwapActions(Macro *m, int pos1, int pos2);
|
||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||
void HighligthMacroSettingsButton(bool enable = true);
|
||||
|
||||
public slots:
|
||||
void on_macroAdd_clicked();
|
||||
@@ -155,12 +154,16 @@ public slots:
|
||||
void SetElseActionsStateToVisible();
|
||||
void MacroActionSelectionChanged(int idx);
|
||||
void MacroActionReorder(int to, int target);
|
||||
void AddMacroAction(Macro *macro, int idx, const std::string &id,
|
||||
obs_data_t *data);
|
||||
void AddMacroAction(int idx);
|
||||
void RemoveMacroAction(int idx);
|
||||
void MoveMacroActionUp(int idx);
|
||||
void MoveMacroActionDown(int idx);
|
||||
void MacroElseActionSelectionChanged(int idx);
|
||||
void MacroElseActionReorder(int to, int target);
|
||||
void AddMacroElseAction(Macro *macro, int idx, const std::string &id,
|
||||
obs_data_t *data);
|
||||
void AddMacroElseAction(int idx);
|
||||
void RemoveMacroElseAction(int idx);
|
||||
void SwapElseActions(Macro *m, int pos1, int pos2);
|
||||
@@ -169,16 +172,16 @@ public slots:
|
||||
void MacroConditionSelectionChanged(int idx);
|
||||
void MacroConditionReorder(int to, int target);
|
||||
void AddMacroCondition(int idx);
|
||||
void AddMacroCondition(Macro *macro, int idx, const std::string &id,
|
||||
obs_data_t *data, LogicType logic);
|
||||
void RemoveMacroCondition(int idx);
|
||||
void MoveMacroConditionUp(int idx);
|
||||
void MoveMacroConditionDown(int idx);
|
||||
void FadeOutActionControls();
|
||||
void FadeOutConditionControls();
|
||||
void ResetOpacityActionControls();
|
||||
void ResetOpacityConditionControls();
|
||||
void HighlightControls();
|
||||
void HighlightOnChange();
|
||||
void on_macroProperties_clicked();
|
||||
void on_macroSettings_clicked();
|
||||
void CopyMacroSegment();
|
||||
void PasteMacroSegment();
|
||||
|
||||
signals:
|
||||
void MacroAdded(const QString &name);
|
||||
@@ -187,9 +190,6 @@ signals:
|
||||
void MacroSegmentOrderChanged();
|
||||
void SegmentTempVarsChanged();
|
||||
void HighlightMacrosChanged(bool value);
|
||||
void HighlightActionsChanged(bool value);
|
||||
void HighlightElseActionsChanged(bool value);
|
||||
void HighlightConditionsChanged(bool value);
|
||||
|
||||
void ConnectionAdded(const QString &);
|
||||
void ConnectionRenamed(const QString &oldName, const QString &newName);
|
||||
@@ -209,19 +209,6 @@ private:
|
||||
|
||||
/* --- End of macro tab section --- */
|
||||
|
||||
/* --- Begin of variable tab section --- */
|
||||
public:
|
||||
void SetupVariableTab();
|
||||
|
||||
public slots:
|
||||
void on_variableAdd_clicked();
|
||||
void on_variableRemove_clicked();
|
||||
|
||||
void OpenSettingsForSelectedVariable();
|
||||
void RemoveSelectedVariables();
|
||||
|
||||
/* --- End of variable tab section --- */
|
||||
|
||||
/* --- Begin of legacy tab section --- */
|
||||
public:
|
||||
void ClearFrames(QListWidget *list);
|
||||
@@ -424,5 +411,6 @@ public slots:
|
||||
|
||||
void OpenSettingsWindow();
|
||||
QWidget *GetSettingsWindow();
|
||||
void HighligthMacroSettingsButton(bool enable);
|
||||
|
||||
} // namespace advss
|
||||
|
||||
124
lib/general.cpp
124
lib/general.cpp
@@ -9,6 +9,7 @@
|
||||
#include "splitter-helpers.hpp"
|
||||
#include "status-control.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "tab-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "variable.hpp"
|
||||
@@ -19,17 +20,6 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static constexpr std::array<const char *, 19> tabNames = {
|
||||
"generalTab", "macroTab", "variableTab",
|
||||
"windowTitleTab", "executableTab", "screenRegionTab",
|
||||
"mediaTab", "fileTab", "randomTab",
|
||||
"timeTab", "idleTab", "sceneSequenceTab",
|
||||
"audioTab", "videoTab", "networkTab",
|
||||
"sceneGroupTab", "transitionsTab", "pauseTab",
|
||||
"sceneTriggerTab"};
|
||||
|
||||
static std::vector<int> tabOrder = std::vector<int>(tabNames.size());
|
||||
|
||||
void AdvSceneSwitcher::reject()
|
||||
{
|
||||
close();
|
||||
@@ -244,14 +234,7 @@ void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state)
|
||||
|
||||
for (int idx = 0; idx < ui->tabWidget->count(); idx++) {
|
||||
if (isLegacyTab(ui->tabWidget->tabText(idx))) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
// TODO: Switch to setTabVisible() once QT 5.15 is more wide spread
|
||||
ui->tabWidget->setTabEnabled(idx, !state);
|
||||
ui->tabWidget->setStyleSheet(
|
||||
"QTabBar::tab::disabled {width: 0; height: 0; margin: 0; padding: 0; border: none;} ");
|
||||
#else
|
||||
ui->tabWidget->setTabVisible(idx, !state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,67 +346,6 @@ void AdvSceneSwitcher::on_importSettings_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
static int findTabIndex(QTabWidget *tabWidget, int pos)
|
||||
{
|
||||
int at = -1;
|
||||
QString tabName = tabNames.at(pos);
|
||||
QWidget *page = tabWidget->findChild<QWidget *>(tabName);
|
||||
if (page) {
|
||||
at = tabWidget->indexOf(page);
|
||||
}
|
||||
if (at == -1) {
|
||||
blog(LOG_INFO, "failed to find tab %s",
|
||||
tabName.toUtf8().constData());
|
||||
}
|
||||
|
||||
return at;
|
||||
}
|
||||
|
||||
static bool tabWidgetOrderValid()
|
||||
{
|
||||
auto tmp = std::vector<int>(tabNames.size());
|
||||
std::iota(tmp.begin(), tmp.end(), 0);
|
||||
|
||||
for (auto &p : tmp) {
|
||||
auto it = std::find(tabOrder.begin(), tabOrder.end(), p);
|
||||
if (it == tabOrder.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void resetTabWidgetOrder()
|
||||
{
|
||||
tabOrder = std::vector<int>(tabNames.size());
|
||||
std::iota(tabOrder.begin(), tabOrder.end(), 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetTabOrder()
|
||||
{
|
||||
if (!tabWidgetOrderValid()) {
|
||||
resetTabWidgetOrder();
|
||||
}
|
||||
|
||||
QTabBar *bar = ui->tabWidget->tabBar();
|
||||
for (int i = 0; i < bar->count(); ++i) {
|
||||
int curPos = findTabIndex(ui->tabWidget, tabOrder[i]);
|
||||
|
||||
if (i != curPos && curPos != -1) {
|
||||
bar->moveTab(curPos, i);
|
||||
}
|
||||
}
|
||||
|
||||
connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetCurrentTab()
|
||||
{
|
||||
if (switcher->lastOpenedTab >= 0) {
|
||||
ui->tabWidget->setCurrentIndex(switcher->lastOpenedTab);
|
||||
}
|
||||
}
|
||||
|
||||
static bool windowPosValid(QPoint pos)
|
||||
{
|
||||
return !!QGuiApplication::screenAt(pos);
|
||||
@@ -446,17 +368,12 @@ void AdvSceneSwitcher::CheckFirstTimeSetup()
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_tabMoved(int from, int to)
|
||||
void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::swap(tabOrder[from], tabOrder[to]);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
|
||||
{
|
||||
switcher->showFrame = false;
|
||||
ClearFrames(ui->screenRegionSwitches);
|
||||
SetShowFrames();
|
||||
@@ -514,7 +431,7 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
}
|
||||
|
||||
LoadMacros(obj);
|
||||
LoadGlobalMacroProperties(obj);
|
||||
LoadGlobalMacroSettings(obj);
|
||||
loadWindowTitleSwitches(obj);
|
||||
loadScreenRegionSwitches(obj);
|
||||
loadPauseSwitches(obj);
|
||||
@@ -537,7 +454,7 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
RunPostLoadSteps();
|
||||
|
||||
// Reset on startup and scene collection change
|
||||
switcher->lastOpenedTab = -1;
|
||||
ResetLastOpenedTab();
|
||||
startupLoadDone = true;
|
||||
}
|
||||
|
||||
@@ -549,7 +466,7 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
|
||||
|
||||
saveSceneGroups(obj);
|
||||
SaveMacros(obj);
|
||||
SaveGlobalMacroProperties(obj);
|
||||
SaveGlobalMacroSettings(obj);
|
||||
SaveVariables(obj);
|
||||
saveWindowTitleSwitches(obj);
|
||||
saveScreenRegionSwitches(obj);
|
||||
@@ -685,13 +602,7 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
||||
|
||||
void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||
{
|
||||
OBSDataArrayAutoRelease tabWidgetOrder = obs_data_array_create();
|
||||
for (size_t i = 0; i < tabNames.size(); i++) {
|
||||
OBSDataAutoRelease entry = obs_data_create();
|
||||
obs_data_set_int(entry, tabNames[i], tabOrder[i]);
|
||||
obs_data_array_push_back(tabWidgetOrder, entry);
|
||||
}
|
||||
obs_data_set_array(obj, "tabWidgetOrder", tabWidgetOrder);
|
||||
SaveTabOrder(obj);
|
||||
|
||||
obs_data_set_bool(obj, "saveWindowGeo", saveWindowGeo);
|
||||
obs_data_set_int(obj, "windowPosX", windowPos.x());
|
||||
@@ -705,28 +616,7 @@ void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||
|
||||
void SwitcherData::LoadUISettings(obs_data_t *obj)
|
||||
{
|
||||
OBSDataArrayAutoRelease defaultTabWidgetOrder = obs_data_array_create();
|
||||
for (size_t i = 0; i < tabNames.size(); i++) {
|
||||
OBSDataAutoRelease entry = obs_data_create();
|
||||
obs_data_set_default_int(entry, tabNames[i], i);
|
||||
obs_data_array_push_back(defaultTabWidgetOrder, entry);
|
||||
}
|
||||
obs_data_set_default_array(obj, "tabWidgetOrder",
|
||||
defaultTabWidgetOrder);
|
||||
|
||||
tabOrder.clear();
|
||||
OBSDataArrayAutoRelease tabWidgetOrder =
|
||||
obs_data_get_array(obj, "tabWidgetOrder");
|
||||
for (size_t i = 0; i < tabNames.size(); i++) {
|
||||
OBSDataAutoRelease entry =
|
||||
obs_data_array_item(tabWidgetOrder, i);
|
||||
tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(entry, tabNames[i])));
|
||||
}
|
||||
|
||||
if (!tabWidgetOrderValid()) {
|
||||
resetTabWidgetOrder();
|
||||
}
|
||||
LoadTabOrder(obj);
|
||||
|
||||
saveWindowGeo = obs_data_get_bool(obj, "saveWindowGeo");
|
||||
windowPos = {(int)obs_data_get_int(obj, "windowPosX"),
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
SceneGroupEditWidget *typeEdit = nullptr;
|
||||
|
||||
std::deque<SceneGroup> &GetSceneGroups()
|
||||
@@ -141,7 +141,7 @@ void AdvSceneSwitcher::on_sceneGroupAdd_clicked()
|
||||
placeHolderText = format.arg(++i);
|
||||
}
|
||||
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
bool accepted = NameDialog::AskForName(
|
||||
this, obs_module_text("AdvSceneSwitcher.sceneGroupTab.add"),
|
||||
obs_module_text("AdvSceneSwitcher.sceneGroupTab.add"), name,
|
||||
placeHolderText);
|
||||
@@ -170,7 +170,8 @@ void AdvSceneSwitcher::on_sceneGroupAdd_clicked()
|
||||
item->setData(Qt::UserRole, text);
|
||||
ui->sceneGroups->setCurrentItem(item);
|
||||
|
||||
ui->sceneGroupAdd->disconnect(addPulse);
|
||||
addPulse->deleteLater();
|
||||
addPulse = nullptr;
|
||||
ui->sceneGroupHelp->setVisible(false);
|
||||
|
||||
emit SceneGroupAdded(QString::fromStdString(name));
|
||||
@@ -512,8 +513,8 @@ void AdvSceneSwitcher::SetupSceneGroupTab()
|
||||
|
||||
if (switcher->sceneGroups.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->sceneGroupAdd,
|
||||
QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->sceneGroupAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->sceneGroupHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool SceneTrigger::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_triggerAdd_clicked()
|
||||
{
|
||||
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_triggerAdd_clicked()
|
||||
listAddClicked(ui->sceneTriggers,
|
||||
new SceneTriggerWidget(this,
|
||||
&switcher->sceneTriggers.back()),
|
||||
ui->triggerAdd, &addPulse);
|
||||
ui->triggerAdd, addPulse);
|
||||
|
||||
ui->triggerHelp->setVisible(false);
|
||||
}
|
||||
@@ -370,8 +370,8 @@ void AdvSceneSwitcher::SetupTriggerTab()
|
||||
|
||||
if (switcher->sceneTriggers.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse =
|
||||
PulseWidget(ui->triggerAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->triggerAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->triggerHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool AudioSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_audioAdd_clicked()
|
||||
{
|
||||
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_audioAdd_clicked()
|
||||
AudioSwitchWidget *sw =
|
||||
new AudioSwitchWidget(this, &switcher->audioSwitches.back());
|
||||
|
||||
listAddClicked(ui->audioSwitches, sw, ui->audioAdd, &addPulse);
|
||||
listAddClicked(ui->audioSwitches, sw, ui->audioAdd, addPulse);
|
||||
|
||||
ui->audioHelp->setVisible(false);
|
||||
}
|
||||
@@ -232,7 +232,8 @@ void AdvSceneSwitcher::SetupAudioTab()
|
||||
|
||||
if (switcher->audioSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->audioAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->audioAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->audioHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool ExecutableSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_executableAdd_clicked()
|
||||
{
|
||||
@@ -19,7 +19,7 @@ void AdvSceneSwitcher::on_executableAdd_clicked()
|
||||
listAddClicked(ui->executables,
|
||||
new ExecutableSwitchWidget(
|
||||
this, &switcher->executableSwitches.back()),
|
||||
ui->executableAdd, &addPulse);
|
||||
ui->executableAdd, addPulse);
|
||||
|
||||
ui->exeHelp->setVisible(false);
|
||||
}
|
||||
@@ -177,8 +177,8 @@ void AdvSceneSwitcher::SetupExecutableTab()
|
||||
|
||||
if (switcher->executableSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->executableAdd,
|
||||
QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->executableAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->exeHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool FileSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
static std::hash<std::string> strHash;
|
||||
|
||||
void AdvSceneSwitcher::on_browseButton_clicked()
|
||||
@@ -291,7 +291,7 @@ void AdvSceneSwitcher::on_fileAdd_clicked()
|
||||
listAddClicked(ui->fileSwitches,
|
||||
new FileSwitchWidget(this,
|
||||
&switcher->fileSwitches.back()),
|
||||
ui->fileAdd, &addPulse);
|
||||
ui->fileAdd, addPulse);
|
||||
|
||||
ui->fileHelp->setVisible(false);
|
||||
}
|
||||
@@ -441,7 +441,8 @@ void AdvSceneSwitcher::SetupFileTab()
|
||||
|
||||
if (switcher->fileSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->fileAdd, QColor(Qt::green));
|
||||
addPulse =
|
||||
HighlightWidget(ui->fileAdd, QColor(Qt::green));
|
||||
}
|
||||
ui->fileHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool MediaSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
constexpr auto media_played_to_end_idx = 8;
|
||||
constexpr auto media_any_idx = 9;
|
||||
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_mediaAdd_clicked()
|
||||
listAddClicked(ui->mediaSwitches,
|
||||
new MediaSwitchWidget(this,
|
||||
&switcher->mediaSwitches.back()),
|
||||
ui->mediaAdd, &addPulse);
|
||||
ui->mediaAdd, addPulse);
|
||||
|
||||
ui->mediaHelp->setVisible(false);
|
||||
}
|
||||
@@ -252,7 +252,8 @@ void AdvSceneSwitcher::SetupMediaTab()
|
||||
|
||||
if (switcher->mediaSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->mediaAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->mediaAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->mediaHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_pauseAdd_clicked()
|
||||
{
|
||||
@@ -20,7 +20,7 @@ void AdvSceneSwitcher::on_pauseAdd_clicked()
|
||||
listAddClicked(ui->pauseEntries,
|
||||
new PauseEntryWidget(this,
|
||||
&switcher->pauseEntries.back()),
|
||||
ui->pauseAdd, &addPulse);
|
||||
ui->pauseAdd, addPulse);
|
||||
|
||||
ui->pauseHelp->setVisible(false);
|
||||
}
|
||||
@@ -264,7 +264,8 @@ void AdvSceneSwitcher::SetupPauseTab()
|
||||
|
||||
if (switcher->pauseEntries.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->pauseAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->pauseAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->pauseHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool RandomSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_randomAdd_clicked()
|
||||
{
|
||||
@@ -19,7 +19,7 @@ void AdvSceneSwitcher::on_randomAdd_clicked()
|
||||
listAddClicked(ui->randomSwitches,
|
||||
new RandomSwitchWidget(this,
|
||||
&switcher->randomSwitches.back()),
|
||||
ui->randomAdd, &addPulse);
|
||||
ui->randomAdd, addPulse);
|
||||
|
||||
ui->randomHelp->setVisible(false);
|
||||
}
|
||||
@@ -131,8 +131,8 @@ void AdvSceneSwitcher::SetupRandomTab()
|
||||
|
||||
if (switcher->randomSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse =
|
||||
PulseWidget(ui->randomAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->randomAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->randomHelp->setVisible(true);
|
||||
} else {
|
||||
@@ -147,8 +147,8 @@ void AdvSceneSwitcher::SetupRandomTab()
|
||||
}");
|
||||
if (switcher->switchIfNotMatching != NoMatchBehavior::RANDOM_SWITCH) {
|
||||
if (!switcher->disableHints) {
|
||||
PulseWidget(ui->randomDisabledWarning, QColor(Qt::red),
|
||||
QColor(0, 0, 0, 0));
|
||||
HighlightWidget(ui->randomDisabledWarning,
|
||||
QColor(Qt::red), QColor(0, 0, 0, 0));
|
||||
}
|
||||
} else {
|
||||
ui->randomDisabledWarning->setVisible(false);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool ScreenRegionSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::ClearFrames(QListWidget *list)
|
||||
{
|
||||
@@ -79,7 +79,7 @@ void AdvSceneSwitcher::on_screenRegionAdd_clicked()
|
||||
listAddClicked(ui->screenRegionSwitches,
|
||||
new ScreenRegionWidget(
|
||||
this, &switcher->screenRegionSwitches.back()),
|
||||
ui->screenRegionAdd, &addPulse);
|
||||
ui->screenRegionAdd, addPulse);
|
||||
|
||||
ui->regionHelp->setVisible(false);
|
||||
}
|
||||
@@ -248,8 +248,8 @@ void AdvSceneSwitcher::SetupRegionTab()
|
||||
|
||||
if (switcher->screenRegionSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->screenRegionAdd,
|
||||
QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->screenRegionAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->regionHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace advss {
|
||||
constexpr auto max_extend_text_size = 150;
|
||||
|
||||
bool SceneSequenceSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_sceneSequenceAdd_clicked()
|
||||
{
|
||||
@@ -26,7 +26,7 @@ void AdvSceneSwitcher::on_sceneSequenceAdd_clicked()
|
||||
listAddClicked(ui->sceneSequenceSwitches,
|
||||
new SequenceWidget(
|
||||
this, &switcher->sceneSequenceSwitches.back()),
|
||||
ui->sceneSequenceAdd, &addPulse);
|
||||
ui->sceneSequenceAdd, addPulse);
|
||||
|
||||
ui->sequenceHelp->setVisible(false);
|
||||
}
|
||||
@@ -299,8 +299,8 @@ void AdvSceneSwitcher::SetupSequenceTab()
|
||||
|
||||
if (switcher->sceneSequenceSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->sceneSequenceAdd,
|
||||
QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->sceneSequenceAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->sequenceHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool TimeSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_timeAdd_clicked()
|
||||
{
|
||||
@@ -17,7 +17,7 @@ void AdvSceneSwitcher::on_timeAdd_clicked()
|
||||
listAddClicked(ui->timeSwitches,
|
||||
new TimeSwitchWidget(this,
|
||||
&switcher->timeSwitches.back()),
|
||||
ui->timeAdd, &addPulse);
|
||||
ui->timeAdd, addPulse);
|
||||
|
||||
ui->timeHelp->setVisible(false);
|
||||
}
|
||||
@@ -197,7 +197,8 @@ void AdvSceneSwitcher::SetupTimeTab()
|
||||
|
||||
if (switcher->timeSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->timeAdd, QColor(Qt::green));
|
||||
addPulse =
|
||||
HighlightWidget(ui->timeAdd, QColor(Qt::green));
|
||||
}
|
||||
ui->timeHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool VideoSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_videoAdd_clicked()
|
||||
{
|
||||
@@ -24,7 +24,7 @@ void AdvSceneSwitcher::on_videoAdd_clicked()
|
||||
VideoSwitchWidget *sw =
|
||||
new VideoSwitchWidget(this, &switcher->videoSwitches.back());
|
||||
|
||||
listAddClicked(ui->videoSwitches, sw, ui->videoAdd, &addPulse);
|
||||
listAddClicked(ui->videoSwitches, sw, ui->videoAdd, addPulse);
|
||||
|
||||
ui->videoHelp->setVisible(false);
|
||||
}
|
||||
@@ -202,7 +202,8 @@ void AdvSceneSwitcher::SetupVideoTab()
|
||||
|
||||
if (switcher->videoSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->videoAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->videoAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->videoHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace advss {
|
||||
|
||||
bool WindowSwitch::pause = false;
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
|
||||
void AdvSceneSwitcher::on_windowAdd_clicked()
|
||||
{
|
||||
@@ -21,7 +21,7 @@ void AdvSceneSwitcher::on_windowAdd_clicked()
|
||||
listAddClicked(ui->windowSwitches,
|
||||
new WindowSwitchWidget(this,
|
||||
&switcher->windowSwitches.back()),
|
||||
ui->windowAdd, &addPulse);
|
||||
ui->windowAdd, addPulse);
|
||||
|
||||
ui->windowHelp->setVisible(false);
|
||||
}
|
||||
@@ -335,8 +335,8 @@ void AdvSceneSwitcher::SetupTitleTab()
|
||||
|
||||
if (switcher->windowSwitches.size() == 0) {
|
||||
if (!switcher->disableHints) {
|
||||
addPulse =
|
||||
PulseWidget(ui->windowAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->windowAdd,
|
||||
QColor(Qt::green));
|
||||
}
|
||||
ui->windowHelp->setVisible(true);
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "macro-helpers.hpp"
|
||||
#include "macro-properties.hpp"
|
||||
#include "macro-settings.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "section.hpp"
|
||||
@@ -29,8 +29,7 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> *entryData,
|
||||
const std::string &id)
|
||||
: MacroSegmentEdit(GetGlobalMacroProperties()._highlightActions,
|
||||
parent),
|
||||
: MacroSegmentEdit(parent),
|
||||
_actionSelection(new FilterComboBox()),
|
||||
_enable(new SwitchButton()),
|
||||
_entryData(entryData)
|
||||
@@ -40,8 +39,6 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||
SLOT(ActionSelectionChanged(const QString &)));
|
||||
QWidget::connect(_enable, SIGNAL(checked(bool)), this,
|
||||
SLOT(ActionEnableChanged(bool)));
|
||||
QWidget::connect(window(), SIGNAL(HighlightActionsChanged(bool)), this,
|
||||
SLOT(EnableHighlight(bool)));
|
||||
QWidget::connect(&_actionStateTimer, SIGNAL(timeout()), this,
|
||||
SLOT(UpdateActionState()));
|
||||
|
||||
@@ -161,33 +158,20 @@ std::shared_ptr<MacroSegment> MacroActionEdit::Data() const
|
||||
return *_entryData;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
void AdvSceneSwitcher::AddMacroAction(Macro *macro, int idx,
|
||||
const std::string &id, obs_data_t *data)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->Actions().size()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string id;
|
||||
if (idx - 1 >= 0) {
|
||||
id = macro->Actions().at(idx - 1)->GetId();
|
||||
} else {
|
||||
id = MacroAction::GetDefaultID();
|
||||
}
|
||||
{
|
||||
auto lock = LockContext();
|
||||
macro->Actions().emplace(
|
||||
macro->Actions().begin() + idx,
|
||||
MacroActionFactory::Create(id, macro.get()));
|
||||
if (idx - 1 >= 0) {
|
||||
auto data = obs_data_create();
|
||||
macro->Actions().at(idx - 1)->Save(data);
|
||||
macro->Actions().emplace(macro->Actions().begin() + idx,
|
||||
MacroActionFactory::Create(id, macro));
|
||||
if (data) {
|
||||
macro->Actions().at(idx)->Load(data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
macro->Actions().at(idx)->PostLoad();
|
||||
RunPostLoadSteps();
|
||||
@@ -198,9 +182,37 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
SetActionData(*macro);
|
||||
}
|
||||
HighlightAction(idx);
|
||||
ui->actionsList->SetHelpMsgVisible(false);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->Actions().size()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string id;
|
||||
if (idx - 1 >= 0) {
|
||||
id = macro->Actions().at(idx - 1)->GetId();
|
||||
} else {
|
||||
id = MacroAction::GetDefaultID();
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data;
|
||||
if (idx - 1 >= 0) {
|
||||
data = obs_data_create();
|
||||
macro->Actions().at(idx - 1)->Save(data);
|
||||
}
|
||||
AddMacroAction(macro.get(), idx, id, data);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
@@ -216,7 +228,6 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
if (currentActionIdx != -1) {
|
||||
MacroActionSelectionChanged(currentActionIdx + 1);
|
||||
}
|
||||
ui->actionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||
@@ -311,7 +322,6 @@ void AdvSceneSwitcher::on_elseActionAdd_clicked()
|
||||
if (currentElseActionIdx != -1) {
|
||||
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
|
||||
}
|
||||
ui->elseActionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionRemove_clicked()
|
||||
@@ -450,31 +460,21 @@ void AdvSceneSwitcher::MacroElseActionReorder(int to, int from)
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroElseAction(int idx)
|
||||
void AdvSceneSwitcher::AddMacroElseAction(Macro *macro, int idx,
|
||||
const std::string &id,
|
||||
obs_data_t *data)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string id;
|
||||
if (idx - 1 >= 0) {
|
||||
id = macro->ElseActions().at(idx - 1)->GetId();
|
||||
} else {
|
||||
id = MacroAction::GetDefaultID();
|
||||
}
|
||||
{
|
||||
auto lock = LockContext();
|
||||
macro->ElseActions().emplace(
|
||||
macro->ElseActions().begin() + idx,
|
||||
MacroActionFactory::Create(id, macro.get()));
|
||||
if (idx - 1 >= 0) {
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
macro->ElseActions().at(idx - 1)->Save(data);
|
||||
macro->ElseActions().emplace(macro->ElseActions().begin() + idx,
|
||||
MacroActionFactory::Create(id,
|
||||
macro));
|
||||
if (data) {
|
||||
macro->ElseActions().at(idx)->Load(data);
|
||||
}
|
||||
macro->ElseActions().at(idx)->PostLoad();
|
||||
@@ -486,9 +486,37 @@ void AdvSceneSwitcher::AddMacroElseAction(int idx)
|
||||
SetElseActionData(*macro);
|
||||
}
|
||||
HighlightElseAction(idx);
|
||||
ui->elseActionsList->SetHelpMsgVisible(false);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroElseAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string id;
|
||||
if (idx - 1 >= 0) {
|
||||
id = macro->ElseActions().at(idx - 1)->GetId();
|
||||
} else {
|
||||
id = MacroAction::GetDefaultID();
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data;
|
||||
if (idx - 1 >= 0) {
|
||||
data = obs_data_create();
|
||||
macro->ElseActions().at(idx - 1)->Save(data);
|
||||
}
|
||||
AddMacroElseAction(macro.get(), idx, id, data);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
@@ -507,7 +535,7 @@ void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
|
||||
SetMacroAbortWait(true);
|
||||
GetMacroWaitCV().notify_all();
|
||||
macro->UpdateElseActionIndices();
|
||||
SetActionData(*macro);
|
||||
SetElseActionData(*macro);
|
||||
}
|
||||
MacroElseActionSelectionChanged(-1);
|
||||
lastInteracted = MacroSection::ELSE_ACTIONS;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "macro-action-macro.hpp"
|
||||
#include "help-icon.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "macro.hpp"
|
||||
|
||||
@@ -48,9 +49,7 @@ bool MacroActionMacro::PerformAction()
|
||||
macro->ResetRunCount();
|
||||
break;
|
||||
case Action::RUN:
|
||||
if (!macro->Paused()) {
|
||||
macro->PerformActions(true, false, true);
|
||||
}
|
||||
RunActions(macro.get());
|
||||
break;
|
||||
case Action::STOP:
|
||||
macro->Stop();
|
||||
@@ -127,6 +126,7 @@ bool MacroActionMacro::Save(obs_data_t *obj) const
|
||||
_macro.Save(obj);
|
||||
_actionIndex.Save(obj, "actionIndex");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_runOptions.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,6 +137,15 @@ bool MacroActionMacro::Load(obs_data_t *obj)
|
||||
_actionIndex.Load(obj, "actionIndex");
|
||||
_action = static_cast<MacroActionMacro::Action>(
|
||||
obs_data_get_int(obj, "action"));
|
||||
_runOptions.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionMacro::PostLoad()
|
||||
{
|
||||
MacroRefAction::PostLoad();
|
||||
MacroAction::PostLoad();
|
||||
_runOptions.macro.PostLoad();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -160,11 +169,68 @@ void MacroActionMacro::ResolveVariablesToFixedValues()
|
||||
_actionIndex.ResolveVariables();
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
static void runActionsHelper(Macro *macro, bool runElseActions, bool setInputs,
|
||||
const StringList &inputs)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
if (setInputs) {
|
||||
macro->GetInputVariables().SetValues(inputs);
|
||||
}
|
||||
macro->PerformActions(!runElseActions, false, true);
|
||||
}
|
||||
|
||||
void MacroActionMacro::RunActions(Macro *actionMacro) const
|
||||
{
|
||||
if (_runOptions.skipWhenPaused && actionMacro->Paused()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_runOptions.logic == RunOptions::Logic::IGNORE_CONDITIONS) {
|
||||
runActionsHelper(actionMacro, _runOptions.runElseActions,
|
||||
_runOptions.setInputs, _runOptions.inputs);
|
||||
return;
|
||||
}
|
||||
|
||||
auto conditionMacro = _runOptions.macro.GetMacro();
|
||||
if (!conditionMacro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_runOptions.reevaluateConditionState) {
|
||||
conditionMacro->CeckMatch(true);
|
||||
}
|
||||
|
||||
if ((_runOptions.logic == RunOptions::Logic::CONDITIONS &&
|
||||
conditionMacro->Matched()) ||
|
||||
(_runOptions.logic == RunOptions::Logic::INVERT_CONDITIONS &&
|
||||
!conditionMacro->Matched())) {
|
||||
runActionsHelper(actionMacro, _runOptions.runElseActions,
|
||||
_runOptions.setInputs, _runOptions.inputs);
|
||||
}
|
||||
}
|
||||
|
||||
static void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, name] : actionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static void populateConditionBehaviorSelection(QComboBox *list)
|
||||
{
|
||||
list->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.conditions.ignore"));
|
||||
list->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.conditions.true"));
|
||||
list->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.conditions.false"));
|
||||
}
|
||||
|
||||
static void populateActionTypeSelection(QComboBox *list)
|
||||
{
|
||||
list->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.actionType.regular"));
|
||||
list->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.actionType.else"));
|
||||
}
|
||||
|
||||
MacroActionMacroEdit::MacroActionMacroEdit(
|
||||
@@ -173,9 +239,28 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
||||
_macros(new MacroSelection(parent)),
|
||||
_actionIndex(new MacroSegmentSelection(
|
||||
this, MacroSegmentSelection::Type::ACTION)),
|
||||
_actions(new QComboBox())
|
||||
_actions(new QComboBox()),
|
||||
_conditionMacros(new MacroSelection(parent)),
|
||||
_conditionBehaviors(new QComboBox()),
|
||||
_reevaluateConditionState(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.macro.type.run."
|
||||
"updateConditionMatchState"))),
|
||||
_actionTypes(new QComboBox()),
|
||||
_skipWhenPaused(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))),
|
||||
_setInputs(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.setInputs"))),
|
||||
_inputs(new MacroInputEdit()),
|
||||
_entryLayout(new QHBoxLayout()),
|
||||
_conditionLayout(new QHBoxLayout()),
|
||||
_reevaluateConditionStateLayout(new QHBoxLayout()),
|
||||
_setInputsLayout(new QHBoxLayout())
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
populateConditionBehaviorSelection(_conditionBehaviors);
|
||||
populateActionTypeSelection(_actionTypes);
|
||||
|
||||
_conditionMacros->HideSelectedMacro();
|
||||
|
||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(MacroChanged(const QString &)));
|
||||
@@ -184,20 +269,53 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
||||
QWidget::connect(_actionIndex,
|
||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||
SLOT(ActionIndexChanged(const IntVariable &)));
|
||||
QWidget::connect(_conditionMacros,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(ConditionMacroChanged(const QString &)));
|
||||
QWidget::connect(_conditionBehaviors, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(ConditionBehaviorChanged(int)));
|
||||
QWidget::connect(_actionTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionTypeChanged(int)));
|
||||
QWidget::connect(_skipWhenPaused, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(SkipWhenPausedChanged(int)));
|
||||
QWidget::connect(_setInputs, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(SetInputsChanged(int)));
|
||||
QWidget::connect(_inputs,
|
||||
SIGNAL(MacroInputValuesChanged(const StringList &)),
|
||||
this, SLOT(InputsChanged(const StringList &)));
|
||||
QWidget::connect(_reevaluateConditionState, SIGNAL(stateChanged(int)),
|
||||
this, SLOT(ReevaluateConditionStateChanged(int)));
|
||||
|
||||
auto mainLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.macro.entry"),
|
||||
mainLayout,
|
||||
{{"{{actions}}", _actions},
|
||||
{"{{actionIndex}}", _actionIndex},
|
||||
{"{{macros}}", _macros}});
|
||||
setLayout(mainLayout);
|
||||
_setInputsLayout->addWidget(_setInputs);
|
||||
_setInputsLayout->addWidget(new HelpIcon(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.setInputs.description")));
|
||||
_setInputsLayout->addStretch();
|
||||
|
||||
_reevaluateConditionStateLayout->addWidget(_reevaluateConditionState);
|
||||
_reevaluateConditionStateLayout->addWidget(new HelpIcon(obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help")));
|
||||
_reevaluateConditionStateLayout->addStretch();
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(_entryLayout);
|
||||
layout->addLayout(_conditionLayout);
|
||||
layout->addLayout(_reevaluateConditionStateLayout);
|
||||
layout->addLayout(_setInputsLayout);
|
||||
layout->addWidget(_inputs);
|
||||
layout->addWidget(_skipWhenPaused);
|
||||
setLayout(layout);
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void HighligthMacroSettingsButton(bool enable);
|
||||
|
||||
MacroActionMacroEdit::~MacroActionMacroEdit()
|
||||
{
|
||||
HighligthMacroSettingsButton(false);
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
@@ -207,45 +325,132 @@ void MacroActionMacroEdit::UpdateEntryData()
|
||||
_actionIndex->SetValue(_entryData->_actionIndex);
|
||||
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
||||
_macros->SetCurrentMacro(_entryData->_macro);
|
||||
_conditionMacros->SetCurrentMacro(_entryData->_runOptions.macro);
|
||||
_conditionBehaviors->setCurrentIndex(
|
||||
static_cast<int>(_entryData->_runOptions.logic));
|
||||
_reevaluateConditionState->setChecked(
|
||||
_entryData->_runOptions.reevaluateConditionState);
|
||||
_actionTypes->setCurrentIndex(
|
||||
_entryData->_runOptions.runElseActions ? 1 : 0);
|
||||
_skipWhenPaused->setChecked(_entryData->_runOptions.skipWhenPaused);
|
||||
_setInputs->setChecked(_entryData->_runOptions.setInputs);
|
||||
SetupMacroInput(_entryData->_macro.GetMacro().get());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::MacroChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_macro = text;
|
||||
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
||||
const auto ¯o = _entryData->_macro.GetMacro();
|
||||
_actionIndex->SetMacro(macro);
|
||||
SetupMacroInput(macro.get());
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_action = static_cast<MacroActionMacro::Action>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_actionIndex = value;
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ConditionMacroChanged(const QString &text)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_runOptions.macro = text;
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ConditionBehaviorChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_runOptions.logic =
|
||||
static_cast<MacroActionMacro::RunOptions::Logic>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ReevaluateConditionStateChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_runOptions.reevaluateConditionState = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::ActionTypeChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_runOptions.runElseActions = value;
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::SkipWhenPausedChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_runOptions.skipWhenPaused = value;
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::SetInputsChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_runOptions.setInputs = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::InputsChanged(const StringList &inputs)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_runOptions.inputs = inputs;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::SetWidgetVisibility()
|
||||
{
|
||||
_entryLayout->removeWidget(_actions);
|
||||
_entryLayout->removeWidget(_actionIndex);
|
||||
_entryLayout->removeWidget(_macros);
|
||||
_entryLayout->removeWidget(_actionTypes);
|
||||
_conditionLayout->removeWidget(_conditionBehaviors);
|
||||
_conditionLayout->removeWidget(_conditionMacros);
|
||||
|
||||
ClearLayout(_entryLayout);
|
||||
ClearLayout(_conditionLayout);
|
||||
|
||||
const std::unordered_map<std::string, QWidget *> placeholders = {
|
||||
{"{{actions}}", _actions},
|
||||
{"{{actionIndex}}", _actionIndex},
|
||||
{"{{macros}}", _macros},
|
||||
{"{{actionTypes}}", _actionTypes},
|
||||
{"{{conditionBehaviors}}", _conditionBehaviors},
|
||||
{"{{conditionMacros}}", _conditionMacros},
|
||||
|
||||
};
|
||||
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
_entryData->_action == MacroActionMacro::Action::RUN
|
||||
? "AdvSceneSwitcher.action.macro.entry.run"
|
||||
: "AdvSceneSwitcher.action.macro.entry.other"),
|
||||
_entryLayout, placeholders);
|
||||
|
||||
if (_entryData->_runOptions.logic ==
|
||||
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS) {
|
||||
_conditionLayout->addWidget(_conditionBehaviors);
|
||||
_conditionLayout->addStretch();
|
||||
} else {
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.macro.entry.run.condition"),
|
||||
_conditionLayout, placeholders);
|
||||
}
|
||||
|
||||
if (_entryData->_action == MacroActionMacro::Action::RUN ||
|
||||
_entryData->_action == MacroActionMacro::Action::STOP) {
|
||||
_macros->HideSelectedMacro();
|
||||
@@ -260,6 +465,73 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
||||
MacroActionMacro::Action::ENABLE_ACTION ||
|
||||
_entryData->_action == MacroActionMacro::Action::TOGGLE_ACTION;
|
||||
_actionIndex->setVisible(isModifyingActionState);
|
||||
|
||||
SetLayoutVisible(_conditionLayout,
|
||||
_entryData->_action == MacroActionMacro::Action::RUN);
|
||||
const bool needsAdditionalConditionWidgets =
|
||||
_entryData->_action == MacroActionMacro::Action::RUN &&
|
||||
_entryData->_runOptions.logic !=
|
||||
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS;
|
||||
_conditionMacros->setVisible(needsAdditionalConditionWidgets);
|
||||
SetLayoutVisible(_reevaluateConditionStateLayout,
|
||||
needsAdditionalConditionWidgets);
|
||||
SetLayoutVisible(_setInputsLayout,
|
||||
_entryData->_action == MacroActionMacro::Action::RUN);
|
||||
_inputs->setVisible(_entryData->_action ==
|
||||
MacroActionMacro::Action::RUN &&
|
||||
_entryData->_runOptions.setInputs);
|
||||
HighligthMacroSettingsButton(_entryData->_action ==
|
||||
MacroActionMacro::Action::RUN &&
|
||||
_entryData->_runOptions.setInputs &&
|
||||
!_inputs->HasInputsToSet());
|
||||
_actionTypes->setVisible(_entryData->_action ==
|
||||
MacroActionMacro::Action::RUN);
|
||||
_skipWhenPaused->setVisible(_entryData->_action ==
|
||||
MacroActionMacro::Action::RUN);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::SetupMacroInput(Macro *macro) const
|
||||
{
|
||||
if (macro) {
|
||||
_inputs->SetInputVariablesAndValues(
|
||||
macro->GetInputVariables(),
|
||||
_entryData->_runOptions.inputs);
|
||||
} else {
|
||||
_inputs->SetInputVariablesAndValues({}, {});
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionMacro::RunOptions::Save(obs_data_t *obj) const
|
||||
{
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_int(data, "logic", static_cast<int>(logic));
|
||||
obs_data_set_bool(data, "reevaluateConditionState",
|
||||
reevaluateConditionState);
|
||||
obs_data_set_bool(data, "runElseActions", runElseActions);
|
||||
obs_data_set_bool(data, "skipWhenPaused", skipWhenPaused);
|
||||
obs_data_set_bool(data, "setInputs", setInputs);
|
||||
inputs.Save(data, "inputs");
|
||||
macro.Save(data);
|
||||
obs_data_set_obj(obj, "runOptions", data);
|
||||
}
|
||||
|
||||
void MacroActionMacro::RunOptions::Load(obs_data_t *obj)
|
||||
{
|
||||
if (!obs_data_has_user_value(obj, "runOptions")) {
|
||||
return;
|
||||
}
|
||||
OBSDataAutoRelease data = obs_data_get_obj(obj, "runOptions");
|
||||
logic = static_cast<Logic>(obs_data_get_int(data, "logic"));
|
||||
reevaluateConditionState =
|
||||
obs_data_get_bool(data, "reevaluateConditionState");
|
||||
runElseActions = obs_data_get_bool(data, "runElseActions");
|
||||
skipWhenPaused = obs_data_get_bool(data, "skipWhenPaused");
|
||||
setInputs = obs_data_get_bool(data, "setInputs");
|
||||
inputs.Load(data, "inputs");
|
||||
macro.Load(data);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,25 +1,45 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-input.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
#include "macro-segment-selection.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionMacro : public MacroRefAction {
|
||||
class MacroActionMacro final : public MacroRefAction {
|
||||
public:
|
||||
MacroActionMacro(Macro *m) : MacroAction(m), MacroRefAction(m) {}
|
||||
bool PerformAction();
|
||||
void LogAction() const;
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
bool PostLoad();
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
static std::shared_ptr<MacroAction> Create(Macro *m);
|
||||
std::shared_ptr<MacroAction> Copy() const;
|
||||
void ResolveVariablesToFixedValues();
|
||||
|
||||
struct RunOptions {
|
||||
void Save(obs_data_t *obj) const;
|
||||
void Load(obs_data_t *obj);
|
||||
enum class Logic {
|
||||
IGNORE_CONDITIONS,
|
||||
CONDITIONS,
|
||||
INVERT_CONDITIONS,
|
||||
};
|
||||
Logic logic;
|
||||
bool reevaluateConditionState = false;
|
||||
bool runElseActions = false;
|
||||
bool skipWhenPaused = true;
|
||||
bool setInputs = false;
|
||||
StringList inputs;
|
||||
MacroRef macro;
|
||||
};
|
||||
|
||||
enum class Action {
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
@@ -30,21 +50,25 @@ public:
|
||||
ENABLE_ACTION,
|
||||
TOGGLE_ACTION,
|
||||
};
|
||||
Action _action = Action::PAUSE;
|
||||
Action _action = Action::RUN;
|
||||
IntVariable _actionIndex = 1;
|
||||
RunOptions _runOptions = {};
|
||||
|
||||
private:
|
||||
void RunActions(Macro *actionMacro) const;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionMacroEdit : public QWidget {
|
||||
class MacroActionMacroEdit final : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionMacroEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionMacro> entryData = nullptr);
|
||||
~MacroActionMacroEdit();
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
@@ -58,18 +82,37 @@ private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void ActionIndexChanged(const IntVariable &value);
|
||||
void ConditionMacroChanged(const QString &text);
|
||||
void ConditionBehaviorChanged(int value);
|
||||
void ReevaluateConditionStateChanged(int value);
|
||||
void ActionTypeChanged(int value);
|
||||
void SkipWhenPausedChanged(int value);
|
||||
void SetInputsChanged(int value);
|
||||
void InputsChanged(const StringList &);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
void SetupMacroInput(Macro *) const;
|
||||
|
||||
MacroSelection *_macros;
|
||||
MacroSegmentSelection *_actionIndex;
|
||||
QComboBox *_actions;
|
||||
MacroSelection *_conditionMacros;
|
||||
QComboBox *_conditionBehaviors;
|
||||
QCheckBox *_reevaluateConditionState;
|
||||
QComboBox *_actionTypes;
|
||||
QCheckBox *_skipWhenPaused;
|
||||
QCheckBox *_setInputs;
|
||||
MacroInputEdit *_inputs;
|
||||
QHBoxLayout *_entryLayout;
|
||||
QHBoxLayout *_conditionLayout;
|
||||
QHBoxLayout *_reevaluateConditionStateLayout;
|
||||
QHBoxLayout *_setInputsLayout;
|
||||
|
||||
std::shared_ptr<MacroActionMacro> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ const static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.variable.type.padValue"},
|
||||
{MacroActionVariable::Type::TRUNCATE,
|
||||
"AdvSceneSwitcher.action.variable.type.truncateValue"},
|
||||
{MacroActionVariable::Type::SWAP_VALUES,
|
||||
"AdvSceneSwitcher.action.variable.type.swapValues"},
|
||||
};
|
||||
|
||||
static void apppend(Variable &var, const std::string &value)
|
||||
@@ -392,6 +394,17 @@ bool MacroActionVariable::PerformAction()
|
||||
var->SetValue(
|
||||
truncate(var->Value(), _direction, _stringLength));
|
||||
return true;
|
||||
case Type::SWAP_VALUES: {
|
||||
auto var2 = _variable2.lock();
|
||||
if (!var2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto tempValue = var->Value();
|
||||
var->SetValue(var2->Value());
|
||||
var2->SetValue(tempValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -630,6 +643,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
_scenes(new SceneSelectionWidget(this, true, false, true, true,
|
||||
true)),
|
||||
_tempVars(new TempVariableSelection(this)),
|
||||
_tempVarsHelp(new HelpIcon(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.type.setToTempvar.help"))),
|
||||
_sceneItemIndex(new VariableSpinBox()),
|
||||
_direction(new QComboBox()),
|
||||
_stringLength(new VariableSpinBox()),
|
||||
@@ -742,6 +757,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
{"{{envVariableName}}", _envVariable},
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{tempVars}}", _tempVars},
|
||||
{"{{tempVarsHelp}}", _tempVarsHelp},
|
||||
{"{{sceneItemIndex}}", _sceneItemIndex},
|
||||
{"{{direction}}", _direction},
|
||||
{"{{stringLength}}", _stringLength},
|
||||
@@ -1202,6 +1218,7 @@ void MacroActionVariableEdit::SelectionChanged(const TempVariableRef &var)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_tempVar = var;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::SceneItemIndexChanged(
|
||||
@@ -1268,6 +1285,7 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
{"{{envVariableName}}", _envVariable},
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{tempVars}}", _tempVars},
|
||||
{"{{tempVarsHelp}}", _tempVarsHelp},
|
||||
{"{{sceneItemIndex}}", _sceneItemIndex},
|
||||
{"{{direction}}", _direction},
|
||||
{"{{stringLength}}", _stringLength},
|
||||
@@ -1304,8 +1322,9 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
AddStretchIfNecessary(_entryLayout);
|
||||
}
|
||||
|
||||
_variables2->setVisible(_entryData->_type ==
|
||||
MacroActionVariable::Type::APPEND_VAR);
|
||||
_variables2->setVisible(
|
||||
_entryData->_type == MacroActionVariable::Type::APPEND_VAR ||
|
||||
_entryData->_type == MacroActionVariable::Type::SWAP_VALUES);
|
||||
_strValue->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_FIXED_VALUE ||
|
||||
@@ -1381,6 +1400,10 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
MacroActionVariable::Type::SCENE_ITEM_NAME);
|
||||
_tempVars->setVisible(_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_TO_TEMPVAR);
|
||||
_tempVarsHelp->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_TO_TEMPVAR &&
|
||||
!_entryData->_tempVar.HasValidID());
|
||||
_sceneItemIndex->setVisible(_entryData->_type ==
|
||||
MacroActionVariable::Type::SCENE_ITEM_NAME);
|
||||
_direction->setVisible(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "help-icon.hpp"
|
||||
#include "macro-segment-selection.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "resizing-text-edit.hpp"
|
||||
@@ -48,6 +49,7 @@ public:
|
||||
SCENE_ITEM_NAME,
|
||||
PAD,
|
||||
TRUNCATE,
|
||||
SWAP_VALUES,
|
||||
};
|
||||
|
||||
Type _type = Type::SET_FIXED_VALUE;
|
||||
@@ -185,6 +187,7 @@ private:
|
||||
VariableLineEdit *_envVariable;
|
||||
SceneSelectionWidget *_scenes;
|
||||
TempVariableSelection *_tempVars;
|
||||
HelpIcon *_tempVarsHelp;
|
||||
VariableSpinBox *_sceneItemIndex;
|
||||
QComboBox *_direction;
|
||||
VariableSpinBox *_stringLength;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "macro-properties.hpp"
|
||||
#include "macro-settings.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "path-helpers.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
@@ -121,8 +121,7 @@ void DurationModifierEdit::Collapse(bool collapse)
|
||||
MacroConditionEdit::MacroConditionEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
||||
const std::string &id, bool root)
|
||||
: MacroSegmentEdit(GetGlobalMacroProperties()._highlightConditions,
|
||||
parent),
|
||||
: MacroSegmentEdit(parent),
|
||||
_logicSelection(new QComboBox()),
|
||||
_conditionSelection(new FilterComboBox()),
|
||||
_dur(new DurationModifierEdit()),
|
||||
@@ -139,8 +138,6 @@ MacroConditionEdit::MacroConditionEdit(
|
||||
QWidget::connect(_dur, SIGNAL(ModifierChanged(DurationModifier::Type)),
|
||||
this,
|
||||
SLOT(DurationModifierChanged(DurationModifier::Type)));
|
||||
QWidget::connect(window(), SIGNAL(HighlightConditionsChanged(bool)),
|
||||
this, SLOT(EnableHighlight(bool)));
|
||||
|
||||
populateLogicSelection(_logicSelection, root);
|
||||
populateConditionSelection(_conditionSelection);
|
||||
@@ -299,6 +296,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->Conditions().size()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -315,16 +313,31 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
|
||||
id = MacroCondition::GetDefaultID();
|
||||
logic = LogicType::ROOT_NONE;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data;
|
||||
if (idx - 1 >= 0) {
|
||||
data = obs_data_create();
|
||||
macro->Conditions().at(idx - 1)->Save(data);
|
||||
}
|
||||
AddMacroCondition(macro.get(), idx, id, data.Get(), logic);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroCondition(Macro *macro, int idx,
|
||||
const std::string &id,
|
||||
obs_data_t *data, LogicType logic)
|
||||
{
|
||||
if (idx < 0 || idx > (int)macro->Conditions().size()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
auto cond = macro->Conditions().emplace(
|
||||
macro->Conditions().begin() + idx,
|
||||
MacroConditionFactory::Create(id, macro.get()));
|
||||
if (idx - 1 >= 0) {
|
||||
auto data = obs_data_create();
|
||||
macro->Conditions().at(idx - 1)->Save(data);
|
||||
MacroConditionFactory::Create(id, macro));
|
||||
if (data) {
|
||||
macro->Conditions().at(idx)->Load(data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
macro->Conditions().at(idx)->PostLoad();
|
||||
RunPostLoadSteps();
|
||||
@@ -337,6 +350,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
|
||||
SetConditionData(*macro);
|
||||
}
|
||||
HighlightCondition(idx);
|
||||
ui->conditionsList->SetHelpMsgVisible(false);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
@@ -355,7 +369,6 @@ void AdvSceneSwitcher::on_conditionAdd_clicked()
|
||||
if (currentConditionIdx != -1) {
|
||||
MacroConditionSelectionChanged(currentConditionIdx + 1);
|
||||
}
|
||||
ui->conditionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroCondition(int idx)
|
||||
|
||||
@@ -167,7 +167,7 @@ void MacroDock::Highlight()
|
||||
}
|
||||
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
||||
macro->WasExecutedSince(_lastHighlightCheckTime)) {
|
||||
PulseWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||
HighlightWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||
}
|
||||
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
@@ -8,9 +8,13 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static bool usePlainText = false;
|
||||
|
||||
MacroExportImportDialog::MacroExportImportDialog(Type type)
|
||||
: QDialog(nullptr),
|
||||
_importExportString(new QPlainTextEdit(this))
|
||||
_importExportString(new QPlainTextEdit(this)),
|
||||
_usePlainText(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.export.usePlainText")))
|
||||
{
|
||||
_importExportString->setReadOnly(type == Type::EXPORT_MACRO);
|
||||
auto label = new QLabel(obs_module_text(
|
||||
@@ -30,9 +34,15 @@ MacroExportImportDialog::MacroExportImportDialog(Type type)
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
buttons->setCenterButtons(true);
|
||||
|
||||
_usePlainText->setChecked(usePlainText);
|
||||
_usePlainText->setVisible(type == Type::EXPORT_MACRO);
|
||||
connect(_usePlainText, &QCheckBox::stateChanged, this,
|
||||
&MacroExportImportDialog::UsePlainTextChanged);
|
||||
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->addWidget(label);
|
||||
layout->addWidget(_importExportString);
|
||||
layout->addWidget(_usePlainText);
|
||||
layout->addWidget(buttons);
|
||||
setLayout(layout);
|
||||
|
||||
@@ -65,6 +75,21 @@ void MacroExportImportDialog::ExportMacros(const QString &json)
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MacroExportImportDialog::UsePlainTextChanged(int value)
|
||||
{
|
||||
if (usePlainText == (!!value)) {
|
||||
return;
|
||||
}
|
||||
const auto current = _importExportString->toPlainText();
|
||||
if (usePlainText) {
|
||||
_importExportString->setPlainText(compressMacroString(current));
|
||||
} else {
|
||||
_importExportString->setPlainText(
|
||||
decompressMacroString(current));
|
||||
}
|
||||
usePlainText = value;
|
||||
}
|
||||
|
||||
static bool isValidData(const QString &json)
|
||||
{
|
||||
OBSDataAutoRelease data =
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
@@ -13,8 +14,12 @@ public:
|
||||
static void ExportMacros(const QString &json);
|
||||
static bool ImportMacros(QString &json);
|
||||
|
||||
private slots:
|
||||
void UsePlainTextChanged(int);
|
||||
|
||||
private:
|
||||
QPlainTextEdit *_importExportString;
|
||||
QCheckBox *_usePlainText;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
247
lib/macro/macro-input.cpp
Normal file
247
lib/macro/macro-input.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
#include "macro-input.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <obs.hpp>
|
||||
|
||||
namespace advss {
|
||||
|
||||
void MacroInputVariables::Save(obs_data_t *obj) const
|
||||
{
|
||||
OBSDataArrayAutoRelease array = obs_data_array_create();
|
||||
for (auto &var : _inputVariables) {
|
||||
OBSDataAutoRelease arrayObj = obs_data_create();
|
||||
auto variable = var.lock();
|
||||
if (variable) {
|
||||
obs_data_set_string(arrayObj, "variableName",
|
||||
variable->Name().c_str());
|
||||
} else {
|
||||
obs_data_set_bool(arrayObj, "invalidVariable", true);
|
||||
}
|
||||
obs_data_array_push_back(array, arrayObj);
|
||||
}
|
||||
obs_data_set_array(obj, "inputVariables", array);
|
||||
}
|
||||
|
||||
void MacroInputVariables::Load(obs_data_t *obj)
|
||||
{
|
||||
OBSDataArrayAutoRelease array =
|
||||
obs_data_get_array(obj, "inputVariables");
|
||||
const size_t count = obs_data_array_count(array);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
OBSDataAutoRelease arrayObj = obs_data_array_item(array, i);
|
||||
const bool isInvalid =
|
||||
obs_data_get_bool(arrayObj, "invalidVariable");
|
||||
if (isInvalid) {
|
||||
_inputVariables.emplace_back();
|
||||
} else {
|
||||
const auto name =
|
||||
obs_data_get_string(arrayObj, "variableName");
|
||||
_inputVariables.emplace_back(
|
||||
GetWeakVariableByName(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MacroInputVariables::SetValues(const StringList &values)
|
||||
{
|
||||
if (_inputVariables.size() != (size_t)values.size()) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
blog(LOG_WARNING,
|
||||
"%s - sizes do not match (variables: %ld, values %d)",
|
||||
__func__, _inputVariables.size(), values.size());
|
||||
#else
|
||||
blog(LOG_WARNING,
|
||||
"%s - sizes do not match (variables: %ld, values %lld)",
|
||||
__func__, _inputVariables.size(), values.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
for (size_t index = 0;
|
||||
index < _inputVariables.size() && index < (size_t)values.size();
|
||||
index++) {
|
||||
auto variable = _inputVariables.at(index).lock();
|
||||
if (!variable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
variable->SetValue(values.at(index));
|
||||
}
|
||||
}
|
||||
|
||||
MacroInputSelection::MacroInputSelection(QWidget *parent) : ListEditor(parent)
|
||||
{
|
||||
_list->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
}
|
||||
|
||||
void MacroInputSelection::SetInputs(const MacroInputVariables &inputs)
|
||||
{
|
||||
_currentSelection = inputs;
|
||||
for (const auto &var : inputs._inputVariables) {
|
||||
auto variable = var.lock();
|
||||
const auto name =
|
||||
variable
|
||||
? QString::fromStdString(variable->Name())
|
||||
: obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.inputSettings.invalid");
|
||||
|
||||
QVariant v = QVariant::fromValue(name);
|
||||
auto item = new QListWidgetItem(name, _list);
|
||||
item->setData(Qt::UserRole, name);
|
||||
}
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void MacroInputSelection::Add()
|
||||
{
|
||||
std::string varName;
|
||||
bool accepted = VariableSelectionDialog::AskForVariable(this, varName);
|
||||
|
||||
if (!accepted || varName.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_currentSelection._inputVariables.emplace_back(
|
||||
GetWeakVariableByName(varName));
|
||||
|
||||
QVariant v = QVariant::fromValue(QString::fromStdString(varName));
|
||||
auto item = new QListWidgetItem(QString::fromStdString(varName), _list);
|
||||
item->setData(Qt::UserRole, QString::fromStdString(varName));
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void MacroInputSelection::Remove()
|
||||
{
|
||||
auto item = _list->currentItem();
|
||||
int idx = _list->currentRow();
|
||||
if (!item || idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
_currentSelection._inputVariables.erase(
|
||||
std::next(_currentSelection._inputVariables.begin(), idx));
|
||||
|
||||
delete item;
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void MacroInputSelection::Up()
|
||||
{
|
||||
int idx = _list->currentRow();
|
||||
if (idx < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
_list->insertItem(idx - 1, _list->takeItem(idx));
|
||||
_list->setCurrentRow(idx - 1);
|
||||
|
||||
std::iter_swap(
|
||||
std::next(_currentSelection._inputVariables.begin(), idx),
|
||||
std::next(_currentSelection._inputVariables.begin(), idx - 1));
|
||||
}
|
||||
|
||||
void MacroInputSelection::Down()
|
||||
{
|
||||
int idx = _list->currentRow();
|
||||
if (idx < 0 || idx >= _list->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_list->insertItem(idx + 1, _list->takeItem(idx));
|
||||
_list->setCurrentRow(idx + 1);
|
||||
|
||||
std::iter_swap(
|
||||
std::next(_currentSelection._inputVariables.begin(), idx + 1),
|
||||
std::next(_currentSelection._inputVariables.begin(), idx));
|
||||
}
|
||||
|
||||
void MacroInputSelection::Clicked(QListWidgetItem *item)
|
||||
{
|
||||
std::string varName;
|
||||
bool accepted = VariableSelectionDialog::AskForVariable(this, varName);
|
||||
|
||||
if (!accepted || varName.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
item->setText(QString::fromStdString(varName));
|
||||
int idx = _list->currentRow();
|
||||
|
||||
_currentSelection._inputVariables.at(idx) =
|
||||
GetWeakVariableByName(varName);
|
||||
}
|
||||
|
||||
MacroInputEdit::MacroInputEdit(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
_layout(new QGridLayout())
|
||||
{
|
||||
setLayout(_layout);
|
||||
}
|
||||
|
||||
void MacroInputEdit::SetInputVariablesAndValues(
|
||||
const MacroInputVariables &inputs, const StringList &values)
|
||||
{
|
||||
_variables = inputs;
|
||||
_values = values;
|
||||
if ((size_t)_values.size() < _variables._inputVariables.size()) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
for (int i = 0;
|
||||
_variables._inputVariables.size() - (size_t)_values.size();
|
||||
i++) {
|
||||
_values.push_back({});
|
||||
}
|
||||
#else
|
||||
_values.resize(_variables._inputVariables.size());
|
||||
#endif
|
||||
}
|
||||
SetupWidgets();
|
||||
}
|
||||
|
||||
bool MacroInputEdit::HasInputsToSet() const
|
||||
{
|
||||
return !_variables._inputVariables.empty();
|
||||
}
|
||||
|
||||
void HighligthMacroSettingsButton(bool enable);
|
||||
|
||||
void MacroInputEdit::SetupWidgets()
|
||||
{
|
||||
ClearLayout(_layout);
|
||||
|
||||
auto &vars = _variables._inputVariables;
|
||||
if (vars.empty()) {
|
||||
_layout->addWidget(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.inputSettings.noInputs")));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < vars.size(); index++) {
|
||||
auto variable = vars.at(index).lock();
|
||||
QLabel *label = new QLabel(
|
||||
variable
|
||||
? QString::fromStdString(variable->Name())
|
||||
: obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.inputSettings.invalid"));
|
||||
_layout->addWidget(label, index, 0);
|
||||
auto valueEdit = new VariableLineEdit(this);
|
||||
valueEdit->setEnabled(!!variable);
|
||||
valueEdit->setText(_values.at(index));
|
||||
connect(valueEdit, &VariableLineEdit::editingFinished,
|
||||
[this, valueEdit, index]() {
|
||||
_values[index] =
|
||||
valueEdit->text().toStdString();
|
||||
emit MacroInputValuesChanged(_values);
|
||||
});
|
||||
_layout->addWidget(valueEdit, index, 1);
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
63
lib/macro/macro-input.hpp
Normal file
63
lib/macro/macro-input.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
#include "list-editor.hpp"
|
||||
#include "string-list.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroInputVariables {
|
||||
public:
|
||||
void Save(obs_data_t *obj) const;
|
||||
void Load(obs_data_t *obj);
|
||||
void SetValues(const StringList &values);
|
||||
|
||||
private:
|
||||
std::vector<std::weak_ptr<Variable>> _inputVariables;
|
||||
friend class MacroInputSelection;
|
||||
friend class MacroInputEdit;
|
||||
};
|
||||
|
||||
class MacroInputSelection final : public ListEditor {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroInputSelection(QWidget *parent = nullptr);
|
||||
void SetInputs(const MacroInputVariables &inputs);
|
||||
MacroInputVariables GetInputs() const { return _currentSelection; }
|
||||
|
||||
private slots:
|
||||
void Add();
|
||||
void Remove();
|
||||
void Up();
|
||||
void Down();
|
||||
void Clicked(QListWidgetItem *);
|
||||
|
||||
private:
|
||||
MacroInputVariables _currentSelection;
|
||||
};
|
||||
|
||||
class MacroInputEdit final : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroInputEdit(QWidget *parent = nullptr);
|
||||
void SetInputVariablesAndValues(const MacroInputVariables &inputs,
|
||||
const StringList &values);
|
||||
bool HasInputsToSet() const;
|
||||
|
||||
signals:
|
||||
void MacroInputValuesChanged(const StringList &);
|
||||
|
||||
private:
|
||||
void SetupWidgets();
|
||||
|
||||
MacroInputVariables _variables;
|
||||
StringList _values;
|
||||
QGridLayout *_layout;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -7,68 +7,16 @@
|
||||
namespace advss {
|
||||
|
||||
MacroList::MacroList(QWidget *parent, bool allowDuplicates, bool reorder)
|
||||
: QWidget(parent),
|
||||
_list(new QListWidget()),
|
||||
_add(new QPushButton()),
|
||||
_remove(new QPushButton()),
|
||||
_up(new QPushButton()),
|
||||
_down(new QPushButton()),
|
||||
_controlsLayout(new QHBoxLayout()),
|
||||
_allowDuplicates(allowDuplicates),
|
||||
_reorder(reorder)
|
||||
: ListEditor(parent, reorder),
|
||||
_allowDuplicates(allowDuplicates)
|
||||
{
|
||||
_add->setMaximumWidth(22);
|
||||
_add->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("addIconSmall")));
|
||||
_add->setFlat(true);
|
||||
_remove->setMaximumWidth(22);
|
||||
_remove->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||
_remove->setFlat(true);
|
||||
_up->setMaximumWidth(22);
|
||||
_up->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
||||
_up->setFlat(true);
|
||||
_down->setMaximumWidth(22);
|
||||
_down->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("downArrowIconSmall")));
|
||||
_down->setFlat(true);
|
||||
|
||||
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add()));
|
||||
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove()));
|
||||
QWidget::connect(_up, SIGNAL(clicked()), this, SLOT(Up()));
|
||||
QWidget::connect(_down, SIGNAL(clicked()), this, SLOT(Down()));
|
||||
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
||||
this, SLOT(MacroItemClicked(QListWidgetItem *)));
|
||||
QWidget::connect(window(),
|
||||
SIGNAL(MacroRenamed(const QString &, const QString &)),
|
||||
this,
|
||||
SLOT(MacroRename(const QString &, const QString &)));
|
||||
QWidget::connect(window(), SIGNAL(MacroRemoved(const QString &)), this,
|
||||
SLOT(MacroRemove(const QString &)));
|
||||
|
||||
_controlsLayout->addWidget(_add);
|
||||
_controlsLayout->addWidget(_remove);
|
||||
if (reorder) {
|
||||
QFrame *line = new QFrame();
|
||||
line->setFrameShape(QFrame::VLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
_controlsLayout->addWidget(line);
|
||||
}
|
||||
_controlsLayout->addWidget(_up);
|
||||
_controlsLayout->addWidget(_down);
|
||||
_controlsLayout->addStretch();
|
||||
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->addWidget(_list);
|
||||
mainLayout->addLayout(_controlsLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_up->setVisible(reorder);
|
||||
_down->setVisible(reorder);
|
||||
|
||||
SetMacroListSize();
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void MacroList::SetContent(const std::vector<MacroRef> ¯os)
|
||||
@@ -89,7 +37,7 @@ void MacroList::SetContent(const std::vector<MacroRef> ¯os)
|
||||
new QListWidgetItem(listEntryName, _list);
|
||||
item->setData(Qt::UserRole, listEntryName);
|
||||
}
|
||||
SetMacroListSize();
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void MacroList::AddControl(QWidget *widget)
|
||||
@@ -122,7 +70,7 @@ void MacroList::MacroRemove(const QString &name)
|
||||
delete _list->item(idx);
|
||||
idx = FindEntry(name.toStdString());
|
||||
}
|
||||
SetMacroListSize();
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void MacroList::Add()
|
||||
@@ -142,7 +90,7 @@ void MacroList::Add()
|
||||
auto item =
|
||||
new QListWidgetItem(QString::fromStdString(macroName), _list);
|
||||
item->setData(Qt::UserRole, QString::fromStdString(macroName));
|
||||
SetMacroListSize();
|
||||
UpdateListSize();
|
||||
emit Added(macroName);
|
||||
}
|
||||
|
||||
@@ -154,7 +102,7 @@ void MacroList::Remove()
|
||||
return;
|
||||
}
|
||||
delete item;
|
||||
SetMacroListSize();
|
||||
UpdateListSize();
|
||||
emit Removed(idx);
|
||||
}
|
||||
|
||||
@@ -178,7 +126,7 @@ void MacroList::Down()
|
||||
}
|
||||
}
|
||||
|
||||
void MacroList::MacroItemClicked(QListWidgetItem *item)
|
||||
void MacroList::Clicked(QListWidgetItem *item)
|
||||
{
|
||||
std::string macroName;
|
||||
bool accepted = MacroSelectionDialog::AskForMacro(this, macroName);
|
||||
@@ -216,10 +164,4 @@ int MacroList::FindEntry(const std::string ¯o)
|
||||
return idx;
|
||||
}
|
||||
|
||||
void MacroList::SetMacroListSize()
|
||||
{
|
||||
SetHeightToContentHeight(_list);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
#pragma once
|
||||
#include "list-editor.hpp"
|
||||
#include "macro-ref.hpp"
|
||||
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class ADVSS_EXPORT MacroList : public QWidget {
|
||||
class ADVSS_EXPORT MacroList final : public ListEditor {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MacroList(QWidget *parent, bool allowDuplicates, bool reorder);
|
||||
@@ -22,7 +19,7 @@ private slots:
|
||||
void Remove();
|
||||
void Up();
|
||||
void Down();
|
||||
void MacroItemClicked(QListWidgetItem *);
|
||||
void Clicked(QListWidgetItem *);
|
||||
|
||||
signals:
|
||||
void Added(const std::string &);
|
||||
@@ -33,16 +30,8 @@ signals:
|
||||
|
||||
private:
|
||||
int FindEntry(const std::string ¯o);
|
||||
void SetMacroListSize();
|
||||
|
||||
QListWidget *_list;
|
||||
QPushButton *_add;
|
||||
QPushButton *_remove;
|
||||
QPushButton *_up;
|
||||
QPushButton *_down;
|
||||
QHBoxLayout *_controlsLayout;
|
||||
const bool _allowDuplicates;
|
||||
const bool _reorder;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
104
lib/macro/macro-segment-copy-paste.cpp
Normal file
104
lib/macro/macro-segment-copy-paste.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "macro.hpp"
|
||||
|
||||
#include <QShortcut>
|
||||
|
||||
namespace advss {
|
||||
|
||||
struct MacroSegmentCopyInfo {
|
||||
enum class Type { NONE, CONDITION, ACTION, ELSE };
|
||||
Type type = Type::NONE;
|
||||
std::shared_ptr<MacroSegment> segment;
|
||||
};
|
||||
static MacroSegmentCopyInfo copyInfo;
|
||||
|
||||
void AdvSceneSwitcher::CopyMacroSegment()
|
||||
{
|
||||
copyInfo.segment.reset();
|
||||
copyInfo.type = MacroSegmentCopyInfo::Type::NONE;
|
||||
|
||||
if (currentConditionIdx == -1 && currentActionIdx == -1 &&
|
||||
currentElseActionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentConditionIdx != -1) {
|
||||
copyInfo.type = MacroSegmentCopyInfo::Type::CONDITION;
|
||||
copyInfo.segment = macro->Conditions().at(currentConditionIdx);
|
||||
} else if (currentActionIdx != -1) {
|
||||
copyInfo.type = MacroSegmentCopyInfo::Type::ACTION;
|
||||
copyInfo.segment = macro->Actions().at(currentActionIdx);
|
||||
} else if (currentElseActionIdx != -1) {
|
||||
copyInfo.type = MacroSegmentCopyInfo::Type::ELSE;
|
||||
copyInfo.segment =
|
||||
macro->ElseActions().at(currentElseActionIdx);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::PasteMacroSegment()
|
||||
{
|
||||
if (copyInfo.type == MacroSegmentCopyInfo::Type::NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro || !copyInfo.segment) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
copyInfo.segment->Save(data);
|
||||
|
||||
switch (copyInfo.type) {
|
||||
case MacroSegmentCopyInfo::Type::CONDITION: {
|
||||
const auto condition = std::static_pointer_cast<MacroCondition>(
|
||||
copyInfo.segment);
|
||||
auto logic = condition->GetLogicType();
|
||||
if (logic > LogicType::ROOT_LAST &&
|
||||
macro->Conditions().empty()) {
|
||||
logic = LogicType::ROOT_NONE;
|
||||
}
|
||||
if (logic < LogicType::ROOT_LAST &&
|
||||
!macro->Conditions().empty()) {
|
||||
logic = LogicType::OR;
|
||||
}
|
||||
AddMacroCondition(macro.get(), macro->Conditions().size(),
|
||||
copyInfo.segment->GetId(), data.Get(), logic);
|
||||
break;
|
||||
}
|
||||
case MacroSegmentCopyInfo::Type::ACTION:
|
||||
AddMacroAction(macro.get(), macro->Actions().size(),
|
||||
copyInfo.segment->GetId(), data.Get());
|
||||
break;
|
||||
case MacroSegmentCopyInfo::Type::ELSE:
|
||||
AddMacroElseAction(macro.get(), macro->ElseActions().size(),
|
||||
copyInfo.segment->GetId(), data.Get());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroSegmentIsInClipboard()
|
||||
{
|
||||
return copyInfo.type != MacroSegmentCopyInfo::Type::NONE;
|
||||
}
|
||||
|
||||
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window)
|
||||
{
|
||||
auto copyShortcut = new QShortcut(QKeySequence("Ctrl+C"), window);
|
||||
QWidget::connect(copyShortcut, &QShortcut::activated, window,
|
||||
&AdvSceneSwitcher::CopyMacroSegment);
|
||||
auto pasteShortcut = new QShortcut(QKeySequence("Ctrl+V"), window);
|
||||
QWidget::connect(pasteShortcut, &QShortcut::activated, window,
|
||||
&AdvSceneSwitcher::PasteMacroSegment);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
8
lib/macro/macro-segment-copy-paste.hpp
Normal file
8
lib/macro/macro-segment-copy-paste.hpp
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace advss {
|
||||
|
||||
class AdvSceneSwitcher;
|
||||
|
||||
bool MacroSegmentIsInClipboard();
|
||||
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window);
|
||||
|
||||
} // namespace advss
|
||||
@@ -130,7 +130,7 @@ void MacroSegmentList::Highlight(int idx, QColor color)
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
PulseWidget(widget, color, QColor(0, 0, 0, 0), true);
|
||||
HighlightWidget(widget, color, QColor(0, 0, 0, 0), true);
|
||||
}
|
||||
|
||||
void MacroSegmentList::SetCollapsed(bool collapse)
|
||||
@@ -176,7 +176,8 @@ bool MacroSegmentList::eventFilter(QObject *object, QEvent *event)
|
||||
|
||||
void MacroSegmentList::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
if (event->button() == Qt::LeftButton ||
|
||||
event->button() == Qt::RightButton) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
_dragPosition = GetDragIndex(event->globalPos());
|
||||
#else
|
||||
@@ -246,6 +247,11 @@ MacroSegmentEdit *MacroSegmentList::WidgetAt(int idx)
|
||||
return static_cast<MacroSegmentEdit *>(item->widget());
|
||||
}
|
||||
|
||||
MacroSegmentEdit *MacroSegmentList::WidgetAt(const QPoint &pos)
|
||||
{
|
||||
return WidgetAt(GetSegmentIndexFromPos(mapToGlobal(pos)));
|
||||
}
|
||||
|
||||
void MacroSegmentList::HideLastDropLine()
|
||||
{
|
||||
if (_dropLineIdx >= 0 && _dropLineIdx < _contentLayout->count()) {
|
||||
@@ -319,7 +325,7 @@ QRect MacroSegmentList::GetContentItemRectWithPadding(int idx)
|
||||
return rect;
|
||||
}
|
||||
|
||||
int MacroSegmentList::GetWidgetIdx(const QPoint &pos)
|
||||
int MacroSegmentList::GetSegmentIndexFromPos(const QPoint &pos)
|
||||
{
|
||||
int idx = -1;
|
||||
for (int i = 0; i < _contentLayout->count(); ++i) {
|
||||
@@ -359,7 +365,7 @@ void MacroSegmentList::CheckScroll()
|
||||
|
||||
void MacroSegmentList::CheckDropLine(const QPoint &pos)
|
||||
{
|
||||
int idx = GetWidgetIdx(pos);
|
||||
int idx = GetSegmentIndexFromPos(pos);
|
||||
if (idx == _dragPosition) {
|
||||
return;
|
||||
}
|
||||
@@ -410,7 +416,7 @@ bool MacroSegmentList::IsInListArea(const QPoint &pos)
|
||||
|
||||
int MacroSegmentList::GetDropIndex(const QPoint &pos)
|
||||
{
|
||||
int idx = GetWidgetIdx(pos);
|
||||
int idx = GetSegmentIndexFromPos(pos);
|
||||
if (idx == _dragPosition) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
void SetHelpMsg(const QString &msg);
|
||||
void SetHelpMsgVisible(bool visible);
|
||||
MacroSegmentEdit *WidgetAt(int idx);
|
||||
MacroSegmentEdit *WidgetAt(const QPoint &);
|
||||
void Insert(int idx, MacroSegmentEdit *widget);
|
||||
void Add(QWidget *widget);
|
||||
void Remove(int idx);
|
||||
@@ -44,7 +45,7 @@ protected:
|
||||
private:
|
||||
int GetDragIndex(const QPoint &);
|
||||
int GetDropIndex(const QPoint &);
|
||||
int GetWidgetIdx(const QPoint &);
|
||||
int GetSegmentIndexFromPos(const QPoint &);
|
||||
void CheckScroll();
|
||||
void CheckDropLine(const QPoint &);
|
||||
bool IsInListArea(const QPoint &);
|
||||
|
||||
@@ -175,7 +175,7 @@ void MacroSegmentSelection::MarkSelectedSegment()
|
||||
index - 1, QColor(Qt::lightGray));
|
||||
}
|
||||
|
||||
PulseWidget(this, QColor(Qt::lightGray), QColor(0, 0, 0, 0), true);
|
||||
HighlightWidget(this, QColor(Qt::lightGray), QColor(0, 0, 0, 0), true);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -20,13 +20,30 @@ MacroSegment::MacroSegment(Macro *m, bool supportsVariableValue)
|
||||
|
||||
bool MacroSegment::Save(obs_data_t *obj) const
|
||||
{
|
||||
obs_data_set_bool(obj, "collapsed", static_cast<int>(_collapsed));
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_bool(data, "collapsed", _collapsed);
|
||||
obs_data_set_bool(data, "useCustomLabel", _useCustomLabel);
|
||||
obs_data_set_string(data, "customLabel", _customLabel.c_str());
|
||||
obs_data_set_obj(obj, "segmentSettings", data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroSegment::Load(obs_data_t *obj)
|
||||
{
|
||||
_collapsed = obs_data_get_bool(obj, "collapsed");
|
||||
// TODO: remove this fallback at some point
|
||||
if (obs_data_has_user_value(obj, "segmentSettings")) {
|
||||
OBSDataAutoRelease data =
|
||||
obs_data_get_obj(obj, "segmentSettings");
|
||||
_collapsed = obs_data_get_bool(data, "collapsed");
|
||||
_useCustomLabel = obs_data_get_bool(data, "useCustomLabel");
|
||||
_customLabel = obs_data_get_string(data, "customLabel");
|
||||
} else {
|
||||
_collapsed = obs_data_get_bool(obj, "collapsed");
|
||||
_useCustomLabel = false;
|
||||
_customLabel = obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.segment.defaultCustomLabel");
|
||||
}
|
||||
|
||||
ClearAvailableTempvars();
|
||||
return true;
|
||||
}
|
||||
@@ -42,12 +59,12 @@ std::string MacroSegment::GetShortDesc() const
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacroSegment::SetHighlight()
|
||||
void MacroSegment::EnableHighlight()
|
||||
{
|
||||
_highlight = true;
|
||||
}
|
||||
|
||||
bool MacroSegment::Highlight()
|
||||
bool MacroSegment::GetHighlightAndReset()
|
||||
{
|
||||
if (_highlight) {
|
||||
_highlight = false;
|
||||
@@ -177,7 +194,7 @@ void DecrementVariableRef(MacroSegment *segment)
|
||||
segment->_variableRefs--;
|
||||
}
|
||||
|
||||
MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent)
|
||||
MacroSegmentEdit::MacroSegmentEdit(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
_section(new Section(300)),
|
||||
_headerInfo(new QLabel()),
|
||||
@@ -186,8 +203,7 @@ MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent)
|
||||
_noBorderframe(new QFrame),
|
||||
_borderFrame(new QFrame),
|
||||
_dropLineAbove(new QFrame),
|
||||
_dropLineBelow(new QFrame),
|
||||
_showHighlight(highlight)
|
||||
_dropLineBelow(new QFrame)
|
||||
{
|
||||
_dropLineAbove->setLineWidth(3);
|
||||
_dropLineAbove->setFixedHeight(11);
|
||||
@@ -265,10 +281,6 @@ MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent)
|
||||
|
||||
// Enable dragging while clicking on the header text
|
||||
_headerInfo->installEventFilter(this);
|
||||
|
||||
_timer.setInterval(1500);
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(Highlight()));
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev)
|
||||
@@ -296,6 +308,12 @@ bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev)
|
||||
|
||||
void MacroSegmentEdit::HeaderInfoChanged(const QString &text)
|
||||
{
|
||||
if (Data() && Data()->GetUseCustomLabel()) {
|
||||
_headerInfo->show();
|
||||
_headerInfo->setText(
|
||||
QString::fromStdString(Data()->GetCustomLabel()));
|
||||
return;
|
||||
}
|
||||
_headerInfo->setVisible(!text.isEmpty());
|
||||
_headerInfo->setText(text);
|
||||
}
|
||||
@@ -307,22 +325,6 @@ void MacroSegmentEdit::Collapsed(bool collapsed)
|
||||
}
|
||||
}
|
||||
|
||||
void MacroSegmentEdit::Highlight()
|
||||
{
|
||||
if (!Data()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_showHighlight && Data()->Highlight()) {
|
||||
PulseWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroSegmentEdit::EnableHighlight(bool value)
|
||||
{
|
||||
_showHighlight = value;
|
||||
}
|
||||
|
||||
void MacroSegmentEdit::SetFocusPolicyOfWidgets()
|
||||
{
|
||||
QList<QWidget *> widgets = this->findChildren<QWidget *>();
|
||||
|
||||
@@ -28,13 +28,17 @@ public:
|
||||
int GetIndex() const { return _idx; }
|
||||
void SetCollapsed(bool collapsed) { _collapsed = collapsed; }
|
||||
bool GetCollapsed() const { return _collapsed; }
|
||||
void SetUseCustomLabel(bool enable) { _useCustomLabel = enable; }
|
||||
bool GetUseCustomLabel() const { return _useCustomLabel; }
|
||||
void SetCustomLabel(const std::string &label) { _customLabel = label; }
|
||||
std::string GetCustomLabel() const { return _customLabel; }
|
||||
virtual bool Save(obs_data_t *obj) const = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual bool PostLoad();
|
||||
virtual std::string GetShortDesc() const;
|
||||
virtual std::string GetId() const = 0;
|
||||
void SetHighlight();
|
||||
bool Highlight();
|
||||
void EnableHighlight();
|
||||
bool GetHighlightAndReset();
|
||||
virtual std::string GetVariableValue() const;
|
||||
|
||||
protected:
|
||||
@@ -63,6 +67,11 @@ private:
|
||||
bool _highlight = false;
|
||||
bool _collapsed = false;
|
||||
|
||||
// Custom header labels
|
||||
bool _useCustomLabel = false;
|
||||
std::string _customLabel = obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.segment.defaultCustomLabel");
|
||||
|
||||
// Variable helpers
|
||||
const bool _supportsVariableValue = false;
|
||||
int _variableRefs = 0;
|
||||
@@ -78,7 +87,7 @@ class MacroSegmentEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroSegmentEdit(bool highlight, QWidget *parent = nullptr);
|
||||
MacroSegmentEdit(QWidget *parent = nullptr);
|
||||
// Use this function to avoid accidental edits when scrolling through
|
||||
// list of actions and conditions
|
||||
void SetFocusPolicyOfWidgets();
|
||||
@@ -86,11 +95,11 @@ public:
|
||||
void SetSelected(bool);
|
||||
virtual std::shared_ptr<MacroSegment> Data() const = 0;
|
||||
|
||||
protected slots:
|
||||
public slots:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected slots:
|
||||
void Collapsed(bool);
|
||||
void Highlight();
|
||||
void EnableHighlight(bool);
|
||||
signals:
|
||||
void MacroAdded(const QString &name);
|
||||
void MacroRemoved(const QString &name);
|
||||
@@ -132,9 +141,6 @@ private:
|
||||
QFrame *_dropLineAbove;
|
||||
QFrame *_dropLineBelow;
|
||||
|
||||
bool _showHighlight;
|
||||
QTimer _timer;
|
||||
|
||||
friend class MacroSegmentList;
|
||||
};
|
||||
|
||||
|
||||
@@ -95,7 +95,9 @@ void MacroSelection::MacroRename(const QString &oldName, const QString &newName)
|
||||
}
|
||||
}
|
||||
|
||||
MacroSelectionDialog::MacroSelectionDialog(QWidget *)
|
||||
MacroSelectionDialog::MacroSelectionDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
_macroSelection(new MacroSelection(this))
|
||||
{
|
||||
setModal(true);
|
||||
setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||
@@ -103,21 +105,20 @@ MacroSelectionDialog::MacroSelectionDialog(QWidget *)
|
||||
setMinimumWidth(350);
|
||||
setMinimumHeight(70);
|
||||
|
||||
QDialogButtonBox *buttonbox = new QDialogButtonBox(
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
auto buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok |
|
||||
QDialogButtonBox::Cancel);
|
||||
|
||||
buttonbox->setCenterButtons(true);
|
||||
connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
_macroSelection = new MacroSelection(window());
|
||||
auto *selectionLayout = new QHBoxLayout;
|
||||
auto selectionLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{macroSelection}}", _macroSelection},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.askForMacro"),
|
||||
selectionLayout, widgetPlaceholders);
|
||||
auto *layout = new QVBoxLayout();
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(selectionLayout);
|
||||
layout->addWidget(buttonbox);
|
||||
setLayout(layout);
|
||||
@@ -125,7 +126,7 @@ MacroSelectionDialog::MacroSelectionDialog(QWidget *)
|
||||
|
||||
bool MacroSelectionDialog::AskForMacro(QWidget *parent, std::string ¯oName)
|
||||
{
|
||||
MacroSelectionDialog dialog(parent);
|
||||
MacroSelectionDialog dialog(GetSettingsWindow());
|
||||
dialog.setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
|
||||
|
||||
if (dialog.exec() != DialogCode::Accepted) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "macro-properties.hpp"
|
||||
#include "macro-settings.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "macro.hpp"
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static MacroProperties macroProperties;
|
||||
static GlobalMacroSettings macroSettings;
|
||||
|
||||
void MacroProperties::Save(obs_data_t *obj) const
|
||||
void GlobalMacroSettings::Save(obs_data_t *obj) const
|
||||
{
|
||||
auto data = obs_data_create();
|
||||
obs_data_set_bool(data, "highlightExecuted", _highlightExecuted);
|
||||
@@ -20,13 +20,16 @@ void MacroProperties::Save(obs_data_t *obj) const
|
||||
obs_data_set_bool(data, "highlightActions", _highlightActions);
|
||||
obs_data_set_bool(data, "newMacroRegisterHotkey",
|
||||
_newMacroRegisterHotkeys);
|
||||
obs_data_set_obj(obj, "macroProperties", data);
|
||||
obs_data_set_obj(obj, "macroSettings", data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void MacroProperties::Load(obs_data_t *obj)
|
||||
void GlobalMacroSettings::Load(obs_data_t *obj)
|
||||
{
|
||||
auto data = obs_data_get_obj(obj, "macroProperties");
|
||||
auto data = obs_data_get_obj(
|
||||
obj, obs_data_has_user_value(obj, "macroProperties")
|
||||
? "macroProperties"
|
||||
: "macroSettings");
|
||||
obs_data_set_default_bool(data, "highlightExecuted", true);
|
||||
obs_data_set_default_bool(data, "highlightConditions", true);
|
||||
obs_data_set_default_bool(data, "highlightActions", true);
|
||||
@@ -38,9 +41,9 @@ void MacroProperties::Load(obs_data_t *obj)
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
const MacroProperties &prop,
|
||||
Macro *macro)
|
||||
MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
||||
const GlobalMacroSettings &settings,
|
||||
Macro *macro)
|
||||
: QDialog(parent),
|
||||
_executed(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.highlightExecutedMacros"))),
|
||||
@@ -56,6 +59,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
"AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup"))),
|
||||
_currentStopActionsIfNotDone(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone"))),
|
||||
_currentInputs(new MacroInputSelection()),
|
||||
_currentMacroRegisterDock(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.currentRegisterDock"))),
|
||||
_currentMacroDockAddRunButton(new QCheckBox(obs_module_text(
|
||||
@@ -101,6 +105,16 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
generalLayout->addWidget(_currentStopActionsIfNotDone);
|
||||
generalOptions->setLayout(generalLayout);
|
||||
|
||||
auto inputOptions = new QGroupBox(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.inputSettings"));
|
||||
auto description = new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.inputSettings.description"));
|
||||
description->setWordWrap(true);
|
||||
auto inputLayout = new QVBoxLayout();
|
||||
inputLayout->addWidget(description);
|
||||
inputLayout->addWidget(_currentInputs);
|
||||
inputOptions->setLayout(inputLayout);
|
||||
|
||||
int row = 0;
|
||||
_dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2);
|
||||
row++;
|
||||
@@ -157,13 +171,13 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
connect(_currentMacroRegisterDock, &QCheckBox::stateChanged, this,
|
||||
&MacroPropertiesDialog::DockEnableChanged);
|
||||
&MacroSettingsDialog::DockEnableChanged);
|
||||
connect(_currentMacroDockAddRunButton, &QCheckBox::stateChanged, this,
|
||||
&MacroPropertiesDialog::RunButtonEnableChanged);
|
||||
&MacroSettingsDialog::RunButtonEnableChanged);
|
||||
connect(_currentMacroDockAddPauseButton, &QCheckBox::stateChanged, this,
|
||||
&MacroPropertiesDialog::PauseButtonEnableChanged);
|
||||
&MacroSettingsDialog::PauseButtonEnableChanged);
|
||||
connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this,
|
||||
&MacroPropertiesDialog::StatusLabelEnableChanged);
|
||||
&MacroSettingsDialog::StatusLabelEnableChanged);
|
||||
|
||||
auto scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
@@ -174,6 +188,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
layout->addWidget(highlightOptions);
|
||||
layout->addWidget(hotkeyOptions);
|
||||
layout->addWidget(generalOptions);
|
||||
layout->addWidget(inputOptions);
|
||||
layout->addWidget(_dockOptions);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
scrollArea->setWidget(contentWidget);
|
||||
@@ -183,14 +198,15 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
dialogLayout->addWidget(buttonbox);
|
||||
setLayout(dialogLayout);
|
||||
|
||||
_executed->setChecked(prop._highlightExecuted);
|
||||
_conditions->setChecked(prop._highlightConditions);
|
||||
_actions->setChecked(prop._highlightActions);
|
||||
_newMacroRegisterHotkeys->setChecked(prop._newMacroRegisterHotkeys);
|
||||
_executed->setChecked(settings._highlightExecuted);
|
||||
_conditions->setChecked(settings._highlightConditions);
|
||||
_actions->setChecked(settings._highlightActions);
|
||||
_newMacroRegisterHotkeys->setChecked(settings._newMacroRegisterHotkeys);
|
||||
|
||||
if (!macro || macro->IsGroup()) {
|
||||
hotkeyOptions->hide();
|
||||
generalOptions->hide();
|
||||
inputOptions->hide();
|
||||
_dockOptions->hide();
|
||||
return;
|
||||
}
|
||||
@@ -198,6 +214,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
_currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled());
|
||||
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
|
||||
_currentStopActionsIfNotDone->setChecked(macro->StopActionsIfNotDone());
|
||||
_currentInputs->SetInputs(macro->GetInputVariables());
|
||||
const bool dockEnabled = macro->DockEnabled();
|
||||
_currentMacroRegisterDock->setChecked(dockEnabled);
|
||||
_currentMacroDockAddRunButton->setChecked(macro->DockHasRunButton());
|
||||
@@ -245,7 +262,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
20);
|
||||
}
|
||||
|
||||
void MacroPropertiesDialog::DockEnableChanged(int enabled)
|
||||
void MacroSettingsDialog::DockEnableChanged(int enabled)
|
||||
{
|
||||
_currentMacroDockAddRunButton->setVisible(enabled);
|
||||
_currentMacroDockAddPauseButton->setVisible(enabled);
|
||||
@@ -270,37 +287,37 @@ void MacroPropertiesDialog::DockEnableChanged(int enabled)
|
||||
Resize();
|
||||
}
|
||||
|
||||
void MacroPropertiesDialog::RunButtonEnableChanged(int enabled)
|
||||
void MacroSettingsDialog::RunButtonEnableChanged(int enabled)
|
||||
{
|
||||
SetGridLayoutRowVisible(_dockLayout, _runButtonTextRow, enabled);
|
||||
Resize();
|
||||
}
|
||||
|
||||
void MacroPropertiesDialog::PauseButtonEnableChanged(int enabled)
|
||||
void MacroSettingsDialog::PauseButtonEnableChanged(int enabled)
|
||||
{
|
||||
SetGridLayoutRowVisible(_dockLayout, _pauseButtonTextRow, enabled);
|
||||
SetGridLayoutRowVisible(_dockLayout, _unpauseButtonTextRow, enabled);
|
||||
Resize();
|
||||
}
|
||||
|
||||
void MacroPropertiesDialog::StatusLabelEnableChanged(int enabled)
|
||||
void MacroSettingsDialog::StatusLabelEnableChanged(int enabled)
|
||||
{
|
||||
SetGridLayoutRowVisible(_dockLayout, _conditionsTrueTextRow, enabled);
|
||||
SetGridLayoutRowVisible(_dockLayout, _conditionsFalseTextRow, enabled);
|
||||
Resize();
|
||||
}
|
||||
|
||||
void MacroPropertiesDialog::Resize()
|
||||
void MacroSettingsDialog::Resize()
|
||||
{
|
||||
_dockOptions->adjustSize();
|
||||
_dockOptions->updateGeometry();
|
||||
}
|
||||
|
||||
bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
||||
MacroProperties &userInput,
|
||||
Macro *macro)
|
||||
bool MacroSettingsDialog::AskForSettings(QWidget *parent,
|
||||
GlobalMacroSettings &userInput,
|
||||
Macro *macro)
|
||||
{
|
||||
MacroPropertiesDialog dialog(parent, userInput, macro);
|
||||
MacroSettingsDialog dialog(parent, userInput, macro);
|
||||
dialog.setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
|
||||
if (dialog.exec() != DialogCode::Accepted) {
|
||||
return false;
|
||||
@@ -337,23 +354,23 @@ bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
||||
dialog._conditionsTrueStatusText->text().toStdString());
|
||||
macro->SetConditionsFalseStatusText(
|
||||
dialog._conditionsFalseStatusText->text().toStdString());
|
||||
|
||||
macro->SetInputVariables(dialog._currentInputs->GetInputs());
|
||||
return true;
|
||||
}
|
||||
|
||||
MacroProperties &GetGlobalMacroProperties()
|
||||
GlobalMacroSettings &GetGlobalMacroSettings()
|
||||
{
|
||||
return macroProperties;
|
||||
return macroSettings;
|
||||
}
|
||||
|
||||
void SaveGlobalMacroProperties(obs_data_t *obj)
|
||||
void SaveGlobalMacroSettings(obs_data_t *obj)
|
||||
{
|
||||
macroProperties.Save(obj);
|
||||
macroSettings.Save(obj);
|
||||
}
|
||||
|
||||
void LoadGlobalMacroProperties(obs_data_t *obj)
|
||||
void LoadGlobalMacroSettings(obs_data_t *obj)
|
||||
{
|
||||
macroProperties.Load(obj);
|
||||
macroSettings.Load(obj);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "macro-input.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
@@ -13,7 +14,7 @@ namespace advss {
|
||||
|
||||
class Macro;
|
||||
|
||||
class MacroProperties {
|
||||
class GlobalMacroSettings {
|
||||
public:
|
||||
void Save(obs_data_t *obj) const;
|
||||
void Load(obs_data_t *obj);
|
||||
@@ -25,13 +26,14 @@ public:
|
||||
};
|
||||
|
||||
// Dialog for configuring global and individual macro specific settings
|
||||
class MacroPropertiesDialog : public QDialog {
|
||||
class MacroSettingsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroPropertiesDialog(QWidget *parent, const MacroProperties &,
|
||||
Macro *macro);
|
||||
static bool AskForSettings(QWidget *parent, MacroProperties &userInput,
|
||||
MacroSettingsDialog(QWidget *parent, const GlobalMacroSettings &,
|
||||
Macro *macro);
|
||||
static bool AskForSettings(QWidget *parent,
|
||||
GlobalMacroSettings &userInput,
|
||||
Macro *macro);
|
||||
private slots:
|
||||
void DockEnableChanged(int);
|
||||
@@ -50,6 +52,7 @@ private:
|
||||
QCheckBox *_currentMacroRegisterHotkeys;
|
||||
QCheckBox *_currentSkipOnStartup;
|
||||
QCheckBox *_currentStopActionsIfNotDone;
|
||||
MacroInputSelection *_currentInputs;
|
||||
QCheckBox *_currentMacroRegisterDock;
|
||||
QCheckBox *_currentMacroDockAddRunButton;
|
||||
QCheckBox *_currentMacroDockAddPauseButton;
|
||||
@@ -70,8 +73,8 @@ private:
|
||||
int _conditionsFalseTextRow = -1;
|
||||
};
|
||||
|
||||
MacroProperties &GetGlobalMacroProperties();
|
||||
void SaveGlobalMacroProperties(obs_data_t *obj);
|
||||
void LoadGlobalMacroProperties(obs_data_t *obj);
|
||||
GlobalMacroSettings &GetGlobalMacroSettings();
|
||||
void SaveGlobalMacroSettings(obs_data_t *obj);
|
||||
void LoadGlobalMacroSettings(obs_data_t *obj);
|
||||
|
||||
} // namespace advss
|
||||
@@ -3,7 +3,8 @@
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "macro-export-import-dialog.hpp"
|
||||
#include "macro-properties.hpp"
|
||||
#include "macro-settings.hpp"
|
||||
#include "macro-segment-copy-paste.hpp"
|
||||
#include "macro-tree.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "math-helpers.hpp"
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static QMetaObject::Connection addPulse;
|
||||
static QObject *addPulse = nullptr;
|
||||
static QTimer onChangeHighlightTimer;
|
||||
|
||||
static bool macroNameExists(const std::string &name)
|
||||
@@ -67,7 +68,7 @@ bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
|
||||
placeHolderText = fmt.arg(++i);
|
||||
}
|
||||
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
bool accepted = NameDialog::AskForName(
|
||||
this, obs_module_text("AdvSceneSwitcher.macroTab.add"),
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.name"), name,
|
||||
placeHolderText);
|
||||
@@ -85,7 +86,7 @@ bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
|
||||
}
|
||||
|
||||
res = std::make_shared<Macro>(
|
||||
name, GetGlobalMacroProperties()._newMacroRegisterHotkeys);
|
||||
name, GetGlobalMacroSettings()._newMacroRegisterHotkeys);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -98,7 +99,8 @@ void AdvSceneSwitcher::on_macroAdd_clicked()
|
||||
}
|
||||
|
||||
ui->macros->Add(newMacro);
|
||||
ui->macroAdd->disconnect(addPulse);
|
||||
addPulse->deleteLater();
|
||||
addPulse = nullptr;
|
||||
emit MacroAdded(QString::fromStdString(name));
|
||||
}
|
||||
|
||||
@@ -199,7 +201,7 @@ void AdvSceneSwitcher::RenameSelectedMacro()
|
||||
|
||||
std::string oldName = macro->Name();
|
||||
std::string name;
|
||||
if (!AdvSSNameDialog::AskForName(
|
||||
if (!NameDialog::AskForName(
|
||||
this, obs_module_text("AdvSceneSwitcher.windowTitle"),
|
||||
obs_module_text("AdvSceneSwitcher.item.newName"), name,
|
||||
QString::fromStdString(oldName))) {
|
||||
@@ -370,7 +372,7 @@ bool AdvSceneSwitcher::ResolveMacroImportNameConflict(
|
||||
}
|
||||
|
||||
std::string newName;
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
bool accepted = NameDialog::AskForName(
|
||||
this,
|
||||
obs_module_text(macro->IsGroup()
|
||||
? "AdvSceneSwitcher.macroTab.addGroup"
|
||||
@@ -461,7 +463,7 @@ void AdvSceneSwitcher::ImportMacros()
|
||||
RunPostLoadSteps();
|
||||
|
||||
ui->macros->Reset(GetMacros(),
|
||||
GetGlobalMacroProperties()._highlightExecuted);
|
||||
GetGlobalMacroSettings()._highlightExecuted);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_macroName_editingFinished()
|
||||
@@ -741,8 +743,8 @@ void AdvSceneSwitcher::MacroSelectionChanged()
|
||||
|
||||
void AdvSceneSwitcher::HighlightOnChange()
|
||||
{
|
||||
if (!GetGlobalMacroProperties()._highlightActions &&
|
||||
!GetGlobalMacroProperties()._highlightExecuted) {
|
||||
if (!GetGlobalMacroSettings()._highlightActions &&
|
||||
!GetGlobalMacroSettings()._highlightExecuted) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -752,23 +754,21 @@ void AdvSceneSwitcher::HighlightOnChange()
|
||||
}
|
||||
|
||||
if (macro->OnChangePreventedActionsRecently()) {
|
||||
PulseWidget(ui->runMacroOnChange, Qt::yellow, Qt::transparent,
|
||||
true);
|
||||
HighlightWidget(ui->runMacroOnChange, Qt::yellow,
|
||||
Qt::transparent, true);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_macroProperties_clicked()
|
||||
void AdvSceneSwitcher::on_macroSettings_clicked()
|
||||
{
|
||||
MacroProperties prop = GetGlobalMacroProperties();
|
||||
bool accepted = MacroPropertiesDialog::AskForSettings(
|
||||
GlobalMacroSettings prop = GetGlobalMacroSettings();
|
||||
bool accepted = MacroSettingsDialog::AskForSettings(
|
||||
this, prop, GetSelectedMacro().get());
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
GetGlobalMacroProperties() = prop;
|
||||
GetGlobalMacroSettings() = prop;
|
||||
emit HighlightMacrosChanged(prop._highlightExecuted);
|
||||
emit HighlightActionsChanged(prop._highlightActions);
|
||||
emit HighlightConditionsChanged(prop._highlightConditions);
|
||||
}
|
||||
|
||||
static void moveControlsToSplitter(QSplitter *splitter, int idx,
|
||||
@@ -783,7 +783,7 @@ static void moveControlsToSplitter(QSplitter *splitter, int idx,
|
||||
splitter->setStyleSheet("QSplitter::handle {background: transparent;}");
|
||||
}
|
||||
|
||||
bool shouldRestoreSplitter(const QList<int> &pos)
|
||||
static bool shouldRestoreSplitter(const QList<int> &pos)
|
||||
{
|
||||
if (pos.size() == 0) {
|
||||
return false;
|
||||
@@ -797,16 +797,46 @@ bool shouldRestoreSplitter(const QList<int> &pos)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void runSegmentHighligtChecksHelper(MacroSegmentList *list)
|
||||
{
|
||||
MacroSegmentEdit *widget = nullptr;
|
||||
for (int i = 0; (widget = list->WidgetAt(i)); i++) {
|
||||
if (widget->Data() && widget->Data()->GetHighlightAndReset()) {
|
||||
list->Highlight(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void runSegmentHighligtChecks(AdvSceneSwitcher *ss)
|
||||
{
|
||||
if (!ss || !HighlightUIElementsEnabled()) {
|
||||
return;
|
||||
}
|
||||
auto macro = ss->GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &settings = GetGlobalMacroSettings();
|
||||
if (settings._highlightConditions) {
|
||||
runSegmentHighligtChecksHelper(ss->ui->conditionsList);
|
||||
}
|
||||
if (settings._highlightActions) {
|
||||
runSegmentHighligtChecksHelper(ss->ui->actionsList);
|
||||
runSegmentHighligtChecksHelper(ss->ui->elseActionsList);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupMacroTab()
|
||||
{
|
||||
ui->macroElseActions->installEventFilter(this);
|
||||
ui->macros->installEventFilter(this);
|
||||
|
||||
if (GetMacros().size() == 0 && !switcher->disableHints) {
|
||||
addPulse = PulseWidget(ui->macroAdd, QColor(Qt::green));
|
||||
addPulse = HighlightWidget(ui->macroAdd, QColor(Qt::green));
|
||||
}
|
||||
ui->macros->Reset(GetMacros(),
|
||||
GetGlobalMacroProperties()._highlightExecuted);
|
||||
GetGlobalMacroSettings()._highlightExecuted);
|
||||
connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this,
|
||||
SLOT(MacroSelectionAboutToChange()));
|
||||
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
||||
@@ -891,6 +921,14 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
switcher->macroListMacroEditSplitterPosition);
|
||||
}
|
||||
}
|
||||
|
||||
SetupSegmentCopyPasteShortcutHandlers(this);
|
||||
|
||||
// Macro segment highlight
|
||||
auto timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout,
|
||||
[this]() { runSegmentHighligtChecks(this); });
|
||||
timer->start(1500);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||
@@ -943,49 +981,107 @@ void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||
menu.exec(globalPos);
|
||||
}
|
||||
|
||||
static void handleCustomLabelChange(MacroSegmentEdit *segmentEdit,
|
||||
QAction *contextMenuOption)
|
||||
{
|
||||
bool enable = contextMenuOption->isChecked();
|
||||
auto segment = segmentEdit->Data();
|
||||
segment->SetUseCustomLabel(enable);
|
||||
if (!enable) {
|
||||
segmentEdit->HeaderInfoChanged(
|
||||
QString::fromStdString(segment->GetShortDesc()));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string label;
|
||||
bool accepted = NameDialog::AskForName(
|
||||
GetSettingsWindow(),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.segment.setCustomLabel"),
|
||||
"", label, QString::fromStdString(segment->GetCustomLabel()));
|
||||
if (!accepted) {
|
||||
segment->SetUseCustomLabel(false);
|
||||
return;
|
||||
}
|
||||
|
||||
segment->SetCustomLabel(label);
|
||||
segmentEdit->HeaderInfoChanged("");
|
||||
}
|
||||
|
||||
static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
||||
std::function<void(AdvSceneSwitcher *)> expand,
|
||||
std::function<void(AdvSceneSwitcher *)> collapse,
|
||||
std::function<void(AdvSceneSwitcher *)> maximize,
|
||||
std::function<void(AdvSceneSwitcher *)> minimize)
|
||||
std::function<void(AdvSceneSwitcher *)> minimize,
|
||||
MacroSegmentList *list)
|
||||
{
|
||||
QMenu menu;
|
||||
auto segmentEdit = list->WidgetAt(pos);
|
||||
|
||||
auto copy = menu.addAction(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.segment.copy"), ss,
|
||||
[ss]() { ss->CopyMacroSegment(); });
|
||||
copy->setEnabled(!!segmentEdit);
|
||||
auto paste = menu.addAction(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.segment.paste"), ss,
|
||||
[ss]() { ss->PasteMacroSegment(); });
|
||||
paste->setEnabled(MacroSegmentIsInClipboard());
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
if (segmentEdit) {
|
||||
auto customLabel = menu.addAction(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.segment.useCustomLabel"));
|
||||
customLabel->setCheckable(true);
|
||||
auto segment = segmentEdit ? segmentEdit->Data() : nullptr;
|
||||
customLabel->setChecked(segment &&
|
||||
segment->GetUseCustomLabel());
|
||||
QWidget::connect(customLabel, &QAction::triggered,
|
||||
std::bind(handleCustomLabelChange, segmentEdit,
|
||||
customLabel));
|
||||
}
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
||||
ss, [ss, expand]() { expand(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
|
||||
ss, [ss, collapse]() { collapse(ss); });
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
|
||||
ss, [ss, maximize]() { maximize(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
|
||||
ss, [ss, minimize]() { minimize(ss); });
|
||||
menu.exec(pos);
|
||||
|
||||
menu.exec(list->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
setupConextMenu(this, ui->actionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllActions,
|
||||
setupConextMenu(this, pos, &AdvSceneSwitcher::ExpandAllActions,
|
||||
&AdvSceneSwitcher::CollapseAllActions,
|
||||
&AdvSceneSwitcher::MaximizeActions,
|
||||
&AdvSceneSwitcher::MinimizeActions);
|
||||
&AdvSceneSwitcher::MinimizeActions, ui->actionsList);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroElseActionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
setupConextMenu(this, ui->elseActionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllElseActions,
|
||||
setupConextMenu(this, pos, &AdvSceneSwitcher::ExpandAllElseActions,
|
||||
&AdvSceneSwitcher::CollapseAllElseActions,
|
||||
&AdvSceneSwitcher::MaximizeElseActions,
|
||||
&AdvSceneSwitcher::MinimizeElseActions);
|
||||
&AdvSceneSwitcher::MinimizeElseActions,
|
||||
ui->elseActionsList);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroConditionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
setupConextMenu(this, ui->conditionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllConditions,
|
||||
setupConextMenu(this, pos, &AdvSceneSwitcher::ExpandAllConditions,
|
||||
&AdvSceneSwitcher::CollapseAllConditions,
|
||||
&AdvSceneSwitcher::MaximizeConditions,
|
||||
&AdvSceneSwitcher::MinimizeConditions);
|
||||
&AdvSceneSwitcher::MinimizeConditions,
|
||||
ui->conditionsList);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CopyMacro()
|
||||
@@ -1011,7 +1107,8 @@ void AdvSceneSwitcher::CopyMacro()
|
||||
Macro::PrepareMoveToGroup(macro->Parent(), newMacro);
|
||||
|
||||
ui->macros->Add(newMacro, macro);
|
||||
ui->macroAdd->disconnect(addPulse);
|
||||
addPulse->deleteLater();
|
||||
addPulse = nullptr;
|
||||
emit MacroAdded(QString::fromStdString(name));
|
||||
}
|
||||
|
||||
@@ -1303,58 +1400,47 @@ static void fade(QWidget *widget, bool fadeOut)
|
||||
animation->start(QPropertyAnimation::DeleteWhenStopped);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::FadeOutActionControls()
|
||||
void fadeWidgets(const std::vector<QWidget *> &widgets, bool fadeOut)
|
||||
{
|
||||
fade(ui->actionAdd, true);
|
||||
fade(ui->actionRemove, true);
|
||||
fade(ui->actionTop, true);
|
||||
fade(ui->actionUp, true);
|
||||
fade(ui->actionDown, true);
|
||||
fade(ui->actionBottom, true);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::FadeOutConditionControls()
|
||||
{
|
||||
fade(ui->conditionAdd, true);
|
||||
fade(ui->conditionRemove, true);
|
||||
fade(ui->conditionTop, true);
|
||||
fade(ui->conditionUp, true);
|
||||
fade(ui->conditionDown, true);
|
||||
fade(ui->conditionBottom, true);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ResetOpacityActionControls()
|
||||
{
|
||||
fade(ui->actionAdd, false);
|
||||
fade(ui->actionRemove, false);
|
||||
fade(ui->actionTop, false);
|
||||
fade(ui->actionUp, false);
|
||||
fade(ui->actionDown, false);
|
||||
fade(ui->actionBottom, false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ResetOpacityConditionControls()
|
||||
{
|
||||
fade(ui->conditionAdd, false);
|
||||
fade(ui->conditionRemove, false);
|
||||
fade(ui->conditionTop, false);
|
||||
fade(ui->conditionUp, false);
|
||||
fade(ui->conditionDown, false);
|
||||
fade(ui->conditionBottom, false);
|
||||
for (const auto &widget : widgets) {
|
||||
fade(widget, fadeOut);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::HighlightControls()
|
||||
{
|
||||
if ((currentActionIdx == -1 && currentConditionIdx == -1) ||
|
||||
(currentActionIdx != -1 && currentConditionIdx != -1)) {
|
||||
ResetOpacityActionControls();
|
||||
ResetOpacityConditionControls();
|
||||
const std::vector<QWidget *> conditionControls{
|
||||
ui->conditionAdd, ui->conditionRemove, ui->conditionTop,
|
||||
ui->conditionUp, ui->conditionDown, ui->conditionBottom,
|
||||
};
|
||||
const std::vector<QWidget *> actionControls{
|
||||
ui->actionAdd, ui->actionRemove, ui->actionTop,
|
||||
ui->actionUp, ui->actionDown, ui->actionBottom,
|
||||
};
|
||||
const std::vector<QWidget *> elseActionControls{
|
||||
ui->elseActionAdd, ui->elseActionRemove, ui->elseActionTop,
|
||||
ui->elseActionUp, ui->elseActionDown, ui->elseActionBottom,
|
||||
};
|
||||
|
||||
if ((currentActionIdx == -1 && currentConditionIdx == -1 &&
|
||||
currentElseActionIdx == -1)) {
|
||||
fadeWidgets(conditionControls, false);
|
||||
fadeWidgets(actionControls, false);
|
||||
fadeWidgets(elseActionControls, false);
|
||||
} else if (currentConditionIdx != -1) {
|
||||
fadeWidgets(conditionControls, false);
|
||||
fadeWidgets(actionControls, true);
|
||||
fadeWidgets(elseActionControls, true);
|
||||
} else if (currentActionIdx != -1) {
|
||||
FadeOutConditionControls();
|
||||
ResetOpacityActionControls();
|
||||
fadeWidgets(conditionControls, true);
|
||||
fadeWidgets(actionControls, false);
|
||||
fadeWidgets(elseActionControls, true);
|
||||
} else if (currentElseActionIdx != -1) {
|
||||
fadeWidgets(conditionControls, true);
|
||||
fadeWidgets(actionControls, true);
|
||||
fadeWidgets(elseActionControls, false);
|
||||
} else {
|
||||
FadeOutActionControls();
|
||||
ResetOpacityConditionControls();
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ void MacroTreeItem::HighlightIfExecuted()
|
||||
|
||||
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
||||
_macro->WasExecutedSince(_lastHighlightCheckTime)) {
|
||||
PulseWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||
HighlightWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||
}
|
||||
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ void Macro::PrepareMoveToGroup(std::shared_ptr<Macro> group,
|
||||
}
|
||||
}
|
||||
|
||||
bool Macro::CeckMatch()
|
||||
bool Macro::CeckMatch(bool ignorePause)
|
||||
{
|
||||
if (_isGroup) {
|
||||
return false;
|
||||
@@ -109,7 +109,7 @@ bool Macro::CeckMatch()
|
||||
|
||||
_matched = false;
|
||||
for (auto &c : _conditions) {
|
||||
if (_paused) {
|
||||
if (_paused && !ignorePause) {
|
||||
vblog(LOG_INFO, "Macro %s is paused", _name.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -137,37 +137,37 @@ bool Macro::CeckMatch()
|
||||
case LogicType::AND:
|
||||
_matched = _matched && cond;
|
||||
if (cond) {
|
||||
c->SetHighlight();
|
||||
c->EnableHighlight();
|
||||
}
|
||||
break;
|
||||
case LogicType::OR:
|
||||
_matched = _matched || cond;
|
||||
if (cond) {
|
||||
c->SetHighlight();
|
||||
c->EnableHighlight();
|
||||
}
|
||||
break;
|
||||
case LogicType::AND_NOT:
|
||||
_matched = _matched && !cond;
|
||||
if (!cond) {
|
||||
c->SetHighlight();
|
||||
c->EnableHighlight();
|
||||
}
|
||||
break;
|
||||
case LogicType::OR_NOT:
|
||||
_matched = _matched || !cond;
|
||||
if (!cond) {
|
||||
c->SetHighlight();
|
||||
c->EnableHighlight();
|
||||
}
|
||||
break;
|
||||
case LogicType::ROOT_NONE:
|
||||
_matched = cond;
|
||||
if (cond) {
|
||||
c->SetHighlight();
|
||||
c->EnableHighlight();
|
||||
}
|
||||
break;
|
||||
case LogicType::ROOT_NOT:
|
||||
_matched = !cond;
|
||||
if (!cond) {
|
||||
c->SetHighlight();
|
||||
c->EnableHighlight();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -185,6 +185,7 @@ bool Macro::CeckMatch()
|
||||
if (!_conditionSateChanged && _performActionsOnChange) {
|
||||
_onPreventedActionExecution = true;
|
||||
}
|
||||
|
||||
_lastMatched = _matched;
|
||||
_lastCheckTime = std::chrono::high_resolution_clock::now();
|
||||
return _matched;
|
||||
@@ -313,7 +314,7 @@ bool Macro::RunActionsHelper(
|
||||
break;
|
||||
}
|
||||
if (action->Enabled()) {
|
||||
action->SetHighlight();
|
||||
action->EnableHighlight();
|
||||
}
|
||||
}
|
||||
_done = true;
|
||||
@@ -348,6 +349,11 @@ void Macro::SetMatchOnChange(bool onChange)
|
||||
_performActionsOnChange = onChange;
|
||||
}
|
||||
|
||||
void Macro::SetStopActionsIfNotDone(bool stopActionsIfNotDone)
|
||||
{
|
||||
_stopActionsIfNotDone = stopActionsIfNotDone;
|
||||
}
|
||||
|
||||
void Macro::SetPaused(bool pause)
|
||||
{
|
||||
if (_paused && !pause) {
|
||||
@@ -382,6 +388,16 @@ void Macro::Stop()
|
||||
}
|
||||
}
|
||||
|
||||
MacroInputVariables Macro::GetInputVariables() const
|
||||
{
|
||||
return _inputVariables;
|
||||
}
|
||||
|
||||
void Macro::SetInputVariables(const MacroInputVariables &inputVariables)
|
||||
{
|
||||
_inputVariables = inputVariables;
|
||||
}
|
||||
|
||||
std::vector<TempVariable> Macro::GetTempVars(MacroSegment *filter) const
|
||||
{
|
||||
std::vector<TempVariable> res;
|
||||
@@ -610,6 +626,8 @@ bool Macro::Save(obs_data_t *obj) const
|
||||
}
|
||||
obs_data_set_array(obj, "elseActions", elseActions);
|
||||
|
||||
_inputVariables.Save(obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -748,6 +766,8 @@ bool Macro::Load(obs_data_t *obj)
|
||||
}
|
||||
UpdateElseActionIndices();
|
||||
|
||||
_inputVariables.Load(obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -819,10 +839,10 @@ void Macro::ResetUIHelpers()
|
||||
{
|
||||
_onPreventedActionExecution = false;
|
||||
for (auto c : _conditions) {
|
||||
c->Highlight();
|
||||
c->GetHighlightAndReset();
|
||||
}
|
||||
for (auto a : _actions) {
|
||||
a->Highlight();
|
||||
a->GetHighlightAndReset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "macro-action.hpp"
|
||||
#include "macro-condition.hpp"
|
||||
#include "macro-helpers.hpp"
|
||||
#include "macro-input.hpp"
|
||||
#include "macro-ref.hpp"
|
||||
#include "variable-string.hpp"
|
||||
#include "temp-variable.hpp"
|
||||
@@ -25,35 +26,44 @@ public:
|
||||
Macro(const std::string &name = "", const bool addHotkey = false);
|
||||
virtual ~Macro();
|
||||
|
||||
bool CeckMatch();
|
||||
bool PerformActions(bool match, bool forceParallel = false,
|
||||
bool ignorePause = false);
|
||||
bool Matched() const { return _matched; }
|
||||
bool ShouldRunActions() const;
|
||||
int64_t MsSinceLastCheck() const;
|
||||
std::string Name() const { return _name; }
|
||||
void SetName(const std::string &name);
|
||||
void SetRunInParallel(bool parallel) { _runInParallel = parallel; }
|
||||
bool RunInParallel() const { return _runInParallel; }
|
||||
|
||||
bool CeckMatch(bool ignorePause = false);
|
||||
bool Matched() const { return _matched; }
|
||||
int64_t MsSinceLastCheck() const;
|
||||
bool ShouldRunActions() const;
|
||||
bool PerformActions(bool match, bool forceParallel = false,
|
||||
bool ignorePause = false);
|
||||
|
||||
void SetPaused(bool pause = true);
|
||||
bool Paused() const { return _paused; }
|
||||
bool WasPausedSince(
|
||||
const std::chrono::high_resolution_clock::time_point &) const;
|
||||
|
||||
void Stop();
|
||||
bool GetStop() const { return _stop; }
|
||||
void ResetTimers();
|
||||
|
||||
void SetMatchOnChange(bool onChange);
|
||||
bool MatchOnChange() const { return _performActionsOnChange; }
|
||||
|
||||
void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; }
|
||||
bool SkipExecOnStart() const { return _skipExecOnStart; }
|
||||
void SetStopActionsIfNotDone(bool stopActionsIfNotDone)
|
||||
{
|
||||
_stopActionsIfNotDone = stopActionsIfNotDone;
|
||||
}
|
||||
|
||||
void SetStopActionsIfNotDone(bool stopActionsIfNotDone);
|
||||
bool StopActionsIfNotDone() const { return _stopActionsIfNotDone; }
|
||||
|
||||
int RunCount() const { return _runCount; };
|
||||
void ResetRunCount() { _runCount = 0; };
|
||||
void ResetTimers();
|
||||
|
||||
void AddHelperThread(std::thread &&);
|
||||
bool GetStop() const { return _stop; }
|
||||
void Stop();
|
||||
void SetRunInParallel(bool parallel) { _runInParallel = parallel; }
|
||||
bool RunInParallel() const { return _runInParallel; }
|
||||
|
||||
// Input variables
|
||||
MacroInputVariables GetInputVariables() const;
|
||||
void SetInputVariables(const MacroInputVariables &);
|
||||
|
||||
// Temporary variable helpers
|
||||
std::vector<TempVariable> GetTempVars(MacroSegment *filter) const;
|
||||
@@ -98,19 +108,21 @@ public:
|
||||
bool SwitchesScene() const;
|
||||
|
||||
// UI helpers
|
||||
const QList<int> &GetActionConditionSplitterPosition() const;
|
||||
void SetActionConditionSplitterPosition(const QList<int>);
|
||||
const QList<int> &GetElseActionSplitterPosition() const;
|
||||
const QList<int> &GetActionConditionSplitterPosition() const;
|
||||
void SetElseActionSplitterPosition(const QList<int>);
|
||||
const QList<int> &GetElseActionSplitterPosition() const;
|
||||
bool HasValidSplitterPositions() const;
|
||||
bool WasExecutedSince(
|
||||
const std::chrono::high_resolution_clock::time_point &) const;
|
||||
bool OnChangePreventedActionsRecently();
|
||||
void ResetUIHelpers();
|
||||
|
||||
// Hotkeys
|
||||
void EnablePauseHotkeys(bool);
|
||||
bool PauseHotkeysEnabled() const;
|
||||
|
||||
// Docks
|
||||
void EnableDock(bool);
|
||||
bool DockEnabled() const { return _registerDock; }
|
||||
void SetDockHasRunButton(bool value);
|
||||
@@ -182,6 +194,8 @@ private:
|
||||
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
MacroInputVariables _inputVariables;
|
||||
|
||||
// UI helpers
|
||||
bool _onPreventedActionExecution = false;
|
||||
|
||||
|
||||
258
lib/queue/action-queue-tab.cpp
Normal file
258
lib/queue/action-queue-tab.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
#include "action-queue-tab.hpp"
|
||||
#include "action-queue.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "sync-helpers.hpp"
|
||||
#include "tab-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
namespace advss {
|
||||
|
||||
static void setupTab(QTabWidget *);
|
||||
|
||||
static ActionQueueTable *tabWidget = nullptr;
|
||||
|
||||
void RegisterActionQueueTab()
|
||||
{
|
||||
AddPluginInitStep([]() {
|
||||
AddSetupTabCallback("actionQueueTab", ActionQueueTable::Create,
|
||||
setupTab);
|
||||
});
|
||||
}
|
||||
|
||||
static void setTabVisible(QTabWidget *tabWidget, bool visible)
|
||||
{
|
||||
SetTabVisibleByName(
|
||||
tabWidget, visible,
|
||||
obs_module_text("AdvSceneSwitcher.actionQueueTab.title"));
|
||||
}
|
||||
|
||||
ActionQueueTable *ActionQueueTable::Create()
|
||||
{
|
||||
tabWidget = new ActionQueueTable();
|
||||
return tabWidget;
|
||||
}
|
||||
|
||||
void ActionQueueTable::Add()
|
||||
{
|
||||
auto newQueue = std::make_shared<ActionQueue>();
|
||||
auto accepted =
|
||||
ActionQueueSettingsDialog::AskForSettings(this, *newQueue);
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
auto &queues = GetActionQueues();
|
||||
queues.emplace_back(newQueue);
|
||||
}
|
||||
|
||||
ActionQueueSignalManager::Instance()->Add(
|
||||
QString::fromStdString(newQueue->Name()));
|
||||
}
|
||||
|
||||
static QStringList getCellLabels(ActionQueue *queue, bool addName = true)
|
||||
{
|
||||
assert(queue);
|
||||
|
||||
auto result = QStringList();
|
||||
if (addName) {
|
||||
result << QString::fromStdString(queue->Name());
|
||||
}
|
||||
result << QString::number(queue->Size())
|
||||
<< QString::fromStdString(obs_module_text(
|
||||
queue->IsRunning()
|
||||
? "AdvSceneSwitcher.actionQueueTab.yes"
|
||||
: "AdvSceneSwitcher.actionQueueTab.no"))
|
||||
<< QString::fromStdString(obs_module_text(
|
||||
queue->RunsOnStartup()
|
||||
? "AdvSceneSwitcher.actionQueueTab.yes"
|
||||
: "AdvSceneSwitcher.actionQueueTab.no"));
|
||||
return result;
|
||||
}
|
||||
|
||||
static void updateQueueStatus(QTableWidget *table)
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); row++) {
|
||||
auto item = table->item(row, 0);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto weakQueue = GetWeakActionQueueByQString(item->text());
|
||||
auto queue = weakQueue.lock();
|
||||
if (!queue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateItemTableRow(table, row,
|
||||
getCellLabels(queue.get(), false));
|
||||
}
|
||||
}
|
||||
|
||||
static void openSettingsDialog()
|
||||
{
|
||||
auto selectedRows =
|
||||
tabWidget->Table()->selectionModel()->selectedRows();
|
||||
if (selectedRows.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto cell = tabWidget->Table()->item(selectedRows.last().row(), 0);
|
||||
if (!cell) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto weakQueue = GetWeakActionQueueByQString(cell->text());
|
||||
auto queue = weakQueue.lock();
|
||||
if (!queue) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto oldName = queue->Name();
|
||||
bool accepted = ActionQueueSettingsDialog::AskForSettings(
|
||||
tabWidget->Table(), *queue.get());
|
||||
if (accepted && oldName != queue->Name()) {
|
||||
ActionQueueSignalManager::Instance()->Rename(
|
||||
QString::fromStdString(oldName),
|
||||
QString::fromStdString(queue->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
static void removeQueuesWithNames(const QStringList &queueNames)
|
||||
{
|
||||
for (const auto &name : queueNames) {
|
||||
auto queue = GetWeakActionQueueByQString(name).lock();
|
||||
if (!queue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto &queues = GetActionQueues();
|
||||
queues.erase(
|
||||
std::remove_if(
|
||||
queues.begin(), queues.end(),
|
||||
[queue](const std::shared_ptr<Item> &item) {
|
||||
return item == queue;
|
||||
}),
|
||||
queues.end());
|
||||
}
|
||||
}
|
||||
|
||||
void ActionQueueTable::Remove()
|
||||
{
|
||||
auto selectedRows =
|
||||
tabWidget->Table()->selectionModel()->selectedRows();
|
||||
if (selectedRows.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList queueNames;
|
||||
for (const auto &row : selectedRows) {
|
||||
auto cell = tabWidget->Table()->item(row.row(), 0);
|
||||
if (!cell) {
|
||||
continue;
|
||||
}
|
||||
|
||||
queueNames << cell->text();
|
||||
}
|
||||
|
||||
int queueNameCount = queueNames.size();
|
||||
if (queueNameCount == 1) {
|
||||
QString deleteWarning = obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.removeSingleQueuePopup.text");
|
||||
if (!DisplayMessage(deleteWarning.arg(queueNames.at(0)),
|
||||
true)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
QString deleteWarning = obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.removeMultipleQueuesPopup.text");
|
||||
if (!DisplayMessage(deleteWarning.arg(queueNameCount), true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
RemoveItemsByName(GetActionQueues(), queueNames);
|
||||
}
|
||||
|
||||
for (const auto &name : queueNames) {
|
||||
ActionQueueSignalManager::Instance()->Remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
ActionQueueTable::ActionQueueTable(QTabWidget *parent)
|
||||
: ResourceTable(
|
||||
parent,
|
||||
obs_module_text("AdvSceneSwitcher.actionQueueTab.help"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.queueAddButton.tooltip"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.queueRemoveButton.tooltip"),
|
||||
QStringList()
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.name.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.size.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.isRunning.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.actionQueueTab.runOnStartup.header"),
|
||||
openSettingsDialog)
|
||||
{
|
||||
for (const auto &queue : GetActionQueues()) {
|
||||
auto q = std::static_pointer_cast<ActionQueue>(queue);
|
||||
AddItemTableRow(Table(), getCellLabels(q.get()));
|
||||
}
|
||||
|
||||
SetHelpVisible(GetActionQueues().empty());
|
||||
}
|
||||
|
||||
static void setupTab(QTabWidget *tab)
|
||||
{
|
||||
if (GetActionQueues().empty()) {
|
||||
setTabVisible(tab, false);
|
||||
}
|
||||
|
||||
QWidget::connect(ActionQueueSignalManager::Instance(),
|
||||
&ActionQueueSignalManager::Rename, tab,
|
||||
[](const QString &oldName, const QString &newName) {
|
||||
RenameItemTableRow(tabWidget->Table(), oldName,
|
||||
newName);
|
||||
});
|
||||
QWidget::connect(
|
||||
ActionQueueSignalManager::Instance(),
|
||||
&ActionQueueSignalManager::Add, tab,
|
||||
[tab](const QString &name) {
|
||||
AddItemTableRow(
|
||||
tabWidget->Table(),
|
||||
getCellLabels(GetWeakActionQueueByQString(name)
|
||||
.lock()
|
||||
.get()));
|
||||
tabWidget->SetHelpVisible(false);
|
||||
tabWidget->HighlightAddButton(false);
|
||||
setTabVisible(tab, true);
|
||||
});
|
||||
QWidget::connect(ActionQueueSignalManager::Instance(),
|
||||
&ActionQueueSignalManager::Remove, tab,
|
||||
[](const QString &name) {
|
||||
RemoveItemTableRow(tabWidget->Table(), name);
|
||||
if (tabWidget->Table()->rowCount() == 0) {
|
||||
tabWidget->SetHelpVisible(true);
|
||||
tabWidget->HighlightAddButton(true);
|
||||
}
|
||||
});
|
||||
|
||||
auto timer = new QTimer(tabWidget);
|
||||
timer->setInterval(1000);
|
||||
QWidget::connect(timer, &QTimer::timeout,
|
||||
[]() { updateQueueStatus(tabWidget->Table()); });
|
||||
timer->start();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
20
lib/queue/action-queue-tab.hpp
Normal file
20
lib/queue/action-queue-tab.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "resource-table.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class ActionQueueTable final : public ResourceTable {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static ActionQueueTable *Create();
|
||||
|
||||
private slots:
|
||||
void Add();
|
||||
void Remove();
|
||||
|
||||
private:
|
||||
ActionQueueTable(QTabWidget *parent = nullptr);
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -1,11 +1,19 @@
|
||||
#include "action-queue.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
static std::deque<std::shared_ptr<Item>> queues;
|
||||
|
||||
std::deque<std::shared_ptr<Item>> &GetActionQueues()
|
||||
{
|
||||
return queues;
|
||||
}
|
||||
|
||||
void RegisterActionQueueTab();
|
||||
|
||||
void SetupActionQueues()
|
||||
{
|
||||
static bool done = false;
|
||||
@@ -14,6 +22,7 @@ void SetupActionQueues()
|
||||
}
|
||||
AddSaveStep(SaveActionQueues);
|
||||
AddLoadStep(LoadActionQueues);
|
||||
RegisterActionQueueTab();
|
||||
done = true;
|
||||
}
|
||||
|
||||
@@ -371,11 +380,24 @@ static bool queueWithNameExists(const std::string &name)
|
||||
return !GetWeakActionQueueByName(name).expired();
|
||||
}
|
||||
|
||||
static void signalImportedQueues(void *varsPtr)
|
||||
{
|
||||
auto queues = std::unique_ptr<std::vector<std::shared_ptr<Item>>>(
|
||||
static_cast<std::vector<std::shared_ptr<Item>> *>(varsPtr));
|
||||
for (const auto &queue : *queues) {
|
||||
ActionQueueSignalManager::Instance()->Add(
|
||||
QString::fromStdString(queue->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
void ImportQueues(obs_data_t *data)
|
||||
{
|
||||
OBSDataArrayAutoRelease array =
|
||||
obs_data_get_array(data, "actionQueues");
|
||||
size_t count = obs_data_array_count(array);
|
||||
|
||||
auto importedQueues = new std::vector<std::shared_ptr<Item>>;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
OBSDataAutoRelease arrayElement = obs_data_array_item(array, i);
|
||||
auto queue = ActionQueue::Create();
|
||||
@@ -384,7 +406,10 @@ void ImportQueues(obs_data_t *data)
|
||||
continue;
|
||||
}
|
||||
queues.emplace_back(queue);
|
||||
importedQueues->emplace_back(queue);
|
||||
}
|
||||
|
||||
QeueUITask(signalImportedQueues, importedQueues);
|
||||
}
|
||||
|
||||
std::weak_ptr<ActionQueue> GetWeakActionQueueByName(const std::string &name)
|
||||
@@ -95,6 +95,7 @@ signals:
|
||||
void Remove(const QString &);
|
||||
};
|
||||
|
||||
std::deque<std::shared_ptr<Item>> &GetActionQueues();
|
||||
void SetupActionQueues();
|
||||
void SaveActionQueues(obs_data_t *);
|
||||
void LoadActionQueues(obs_data_t *);
|
||||
@@ -187,24 +187,6 @@ void SwitcherData::RunPostLoadSteps()
|
||||
postLoadSteps.clear();
|
||||
}
|
||||
|
||||
void SwitcherData::AddPluginInitStep(std::function<void()> function)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
pluginInitSteps.emplace_back(function);
|
||||
}
|
||||
|
||||
void SwitcherData::AddPluginPostLoadStep(std::function<void()> function)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
pluginPostLoadSteps.emplace_back(function);
|
||||
}
|
||||
|
||||
void SwitcherData::AddPluginCleanupStep(std::function<void()> function)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
pluginCleanupSteps.emplace_back(function);
|
||||
}
|
||||
|
||||
void SwitcherData::AddSaveStep(std::function<void(obs_data_t *)> function)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "switch-video.hpp"
|
||||
#include "switch-network.hpp"
|
||||
|
||||
#include "macro-properties.hpp"
|
||||
#include "macro-settings.hpp"
|
||||
#include "duration-control.hpp"
|
||||
#include "priority-helper.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
@@ -65,9 +65,6 @@ public:
|
||||
void AddPostLoadStep(std::function<void()>);
|
||||
void AddIntervalResetStep(std::function<void()>, bool lock = true);
|
||||
void RunPostLoadSteps();
|
||||
void AddPluginInitStep(std::function<void()>);
|
||||
void AddPluginPostLoadStep(std::function<void()>);
|
||||
void AddPluginCleanupStep(std::function<void()>);
|
||||
bool CheckForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||
int &linger, bool &setPreviousSceneAsMatch,
|
||||
bool ¯oMatch);
|
||||
@@ -106,9 +103,6 @@ public:
|
||||
std::vector<std::function<void(obs_data_t *)>> loadSteps;
|
||||
std::vector<std::function<void()>> postLoadSteps;
|
||||
std::vector<std::function<void()>> resetIntervalSteps;
|
||||
std::vector<std::function<void()>> pluginInitSteps;
|
||||
std::vector<std::function<void()>> pluginPostLoadSteps;
|
||||
std::vector<std::function<void()>> pluginCleanupSteps;
|
||||
|
||||
bool firstBoot = true;
|
||||
bool transitionActive = false;
|
||||
@@ -171,7 +165,6 @@ public:
|
||||
/* --- Start of UI section --- */
|
||||
|
||||
bool settingsWindowOpened = false;
|
||||
int lastOpenedTab = -1;
|
||||
std::string lastImportPath;
|
||||
QStringList loadFailureLibs;
|
||||
bool warnPluginLoadFailure = true;
|
||||
|
||||
19
lib/utils/help-icon.cpp
Normal file
19
lib/utils/help-icon.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "help-icon.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
HelpIcon::HelpIcon(const QString &tooltip, QWidget *parent) : QLabel(parent)
|
||||
{
|
||||
auto path = GetThemeTypeName() == "Light"
|
||||
? ":/res/images/help.svg"
|
||||
: ":/res/images/help_light.svg";
|
||||
QIcon icon(path);
|
||||
QPixmap pixmap = icon.pixmap(QSize(16, 16));
|
||||
setPixmap(pixmap);
|
||||
if (!tooltip.isEmpty()) {
|
||||
setToolTip(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
15
lib/utils/help-icon.hpp
Normal file
15
lib/utils/help-icon.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "export-symbol-helper.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class ADVSS_EXPORT HelpIcon : public QLabel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HelpIcon(const QString &tooltip = "", QWidget *parent = nullptr);
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -177,7 +177,7 @@ void ItemSelection::RenameItem()
|
||||
Item *item = variant.value<Item *>();
|
||||
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
bool accepted = NameDialog::AskForName(
|
||||
this, obs_module_text("AdvSceneSwitcher.windowTitle"),
|
||||
obs_module_text("AdvSceneSwitcher.item.newName"), name,
|
||||
QString::fromStdString(item->Name()));
|
||||
@@ -347,4 +347,18 @@ void Item::Save(obs_data_t *obj) const
|
||||
obs_data_set_string(obj, "name", _name.c_str());
|
||||
}
|
||||
|
||||
void RemoveItemsByName(std::deque<std::shared_ptr<Item>> &items,
|
||||
const QStringList &names)
|
||||
{
|
||||
for (const auto &name : names) {
|
||||
items.erase(std::remove_if(
|
||||
items.begin(), items.end(),
|
||||
[name](const std::shared_ptr<Item> &item) {
|
||||
return item->Name() ==
|
||||
name.toStdString();
|
||||
}),
|
||||
items.end());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -32,6 +32,9 @@ protected:
|
||||
friend ItemSettingsDialog;
|
||||
};
|
||||
|
||||
void EXPORT RemoveItemsByName(std::deque<std::shared_ptr<Item>> &items,
|
||||
const QStringList &names);
|
||||
|
||||
class ItemSettingsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -78,6 +81,7 @@ public:
|
||||
"AdvSceneSwitcher.item.nameNotAvailable",
|
||||
std::string_view configureTooltip = "", QWidget *parent = 0);
|
||||
virtual ~ItemSelection() = default;
|
||||
Item *GetCurrentItem();
|
||||
void SetItem(const std::string &);
|
||||
void ShowRenameContextMenu(bool value);
|
||||
|
||||
@@ -96,8 +100,6 @@ signals:
|
||||
void ItemRenamed(const QString &oldName, const QString &name);
|
||||
|
||||
private:
|
||||
Item *GetCurrentItem();
|
||||
|
||||
FilterComboBox *_selection;
|
||||
QPushButton *_modify;
|
||||
CreateItemFunc _create;
|
||||
|
||||
77
lib/utils/list-editor.cpp
Normal file
77
lib/utils/list-editor.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "list-editor.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
ListEditor::ListEditor(QWidget *parent, bool reorder)
|
||||
: QWidget(parent),
|
||||
_list(new QListWidget()),
|
||||
_add(new QPushButton()),
|
||||
_remove(new QPushButton()),
|
||||
_up(new QPushButton()),
|
||||
_down(new QPushButton()),
|
||||
_controlsLayout(new QHBoxLayout()),
|
||||
_mainLayout(new QVBoxLayout())
|
||||
{
|
||||
_add->setMaximumWidth(22);
|
||||
_add->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("addIconSmall")));
|
||||
_add->setFlat(true);
|
||||
_remove->setMaximumWidth(22);
|
||||
_remove->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||
_remove->setFlat(true);
|
||||
_up->setMaximumWidth(22);
|
||||
_up->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
||||
_up->setFlat(true);
|
||||
_down->setMaximumWidth(22);
|
||||
_down->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("downArrowIconSmall")));
|
||||
_down->setFlat(true);
|
||||
|
||||
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add()));
|
||||
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove()));
|
||||
QWidget::connect(_up, SIGNAL(clicked()), this, SLOT(Up()));
|
||||
QWidget::connect(_down, SIGNAL(clicked()), this, SLOT(Down()));
|
||||
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
||||
this, SLOT(Clicked(QListWidgetItem *)));
|
||||
|
||||
_controlsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_controlsLayout->addWidget(_add);
|
||||
_controlsLayout->addWidget(_remove);
|
||||
if (reorder) {
|
||||
auto line = new QFrame();
|
||||
line->setFrameShape(QFrame::VLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
_controlsLayout->addWidget(line);
|
||||
_controlsLayout->addWidget(_up);
|
||||
_controlsLayout->addWidget(_down);
|
||||
}
|
||||
_controlsLayout->addStretch();
|
||||
|
||||
_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_mainLayout->addWidget(_list);
|
||||
_mainLayout->addLayout(_controlsLayout);
|
||||
setLayout(_mainLayout);
|
||||
}
|
||||
|
||||
void ListEditor::showEvent(QShowEvent *e)
|
||||
{
|
||||
QWidget::showEvent(e);
|
||||
// This is necessary as the list viewport might not be updated yet while
|
||||
// the list was hidden.
|
||||
// Thus, previous calls to UpdateListSize() might not have resized the
|
||||
// widget correctly, for example due to not regarding the horizontal
|
||||
// scrollbar yet.
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void ListEditor::UpdateListSize()
|
||||
{
|
||||
SetHeightToContentHeight(_list);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
38
lib/utils/list-editor.hpp
Normal file
38
lib/utils/list-editor.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include "export-symbol-helper.hpp"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <QLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class ADVSS_EXPORT ListEditor : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ListEditor(QWidget *parent = nullptr, bool reorder = true);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
|
||||
private slots:
|
||||
virtual void Add() = 0;
|
||||
virtual void Remove() = 0;
|
||||
virtual void Up(){};
|
||||
virtual void Down(){};
|
||||
virtual void Clicked(QListWidgetItem *) {}
|
||||
|
||||
protected:
|
||||
void UpdateListSize();
|
||||
|
||||
QListWidget *_list;
|
||||
QPushButton *_add;
|
||||
QPushButton *_remove;
|
||||
QPushButton *_up;
|
||||
QPushButton *_down;
|
||||
QHBoxLayout *_controlsLayout;
|
||||
QVBoxLayout *_mainLayout;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -5,22 +5,22 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
AdvSSNameDialog::AdvSSNameDialog(QWidget *parent) : QDialog(parent)
|
||||
NameDialog::NameDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
_label(new QLabel(this)),
|
||||
_userText(new QLineEdit(this))
|
||||
|
||||
{
|
||||
setModal(true);
|
||||
setWindowModality(Qt::WindowModality::WindowModal);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setFixedWidth(555);
|
||||
setMinimumHeight(100);
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
auto layout = new QVBoxLayout;
|
||||
setLayout(layout);
|
||||
|
||||
label = new QLabel(this);
|
||||
layout->addWidget(label);
|
||||
label->setText("Set Text");
|
||||
|
||||
userText = new QLineEdit(this);
|
||||
layout->addWidget(userText);
|
||||
layout->addWidget(_label);
|
||||
layout->addWidget(_userText);
|
||||
|
||||
QDialogButtonBox *buttonbox = new QDialogButtonBox(
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
@@ -30,43 +30,44 @@ AdvSSNameDialog::AdvSSNameDialog(QWidget *parent) : QDialog(parent)
|
||||
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
static bool IsWhitespace(char ch)
|
||||
static bool isWhitespace(char ch)
|
||||
{
|
||||
return ch == ' ' || ch == '\t';
|
||||
}
|
||||
|
||||
static void CleanWhitespace(std::string &str)
|
||||
static void cleanWhitespace(std::string &str)
|
||||
{
|
||||
while (str.size() && IsWhitespace(str.back()))
|
||||
while (str.size() && isWhitespace(str.back())) {
|
||||
str.erase(str.end() - 1);
|
||||
while (str.size() && IsWhitespace(str.front()))
|
||||
}
|
||||
while (str.size() && isWhitespace(str.front())) {
|
||||
str.erase(str.begin());
|
||||
}
|
||||
}
|
||||
|
||||
bool AdvSSNameDialog::AskForName(QWidget *parent, const QString &title,
|
||||
const QString &text,
|
||||
std::string &userTextInput,
|
||||
const QString &placeHolder, int maxSize,
|
||||
bool clean)
|
||||
bool NameDialog::AskForName(QWidget *parent, const QString &title,
|
||||
const QString &prompt, std::string &userTextInput,
|
||||
const QString &placeHolder, int maxSize, bool clean)
|
||||
{
|
||||
if (maxSize <= 0 || maxSize > 32767) {
|
||||
maxSize = 170;
|
||||
}
|
||||
|
||||
AdvSSNameDialog dialog(parent);
|
||||
NameDialog dialog(parent);
|
||||
dialog.setWindowTitle(title);
|
||||
|
||||
dialog.label->setText(text);
|
||||
dialog.userText->setMaxLength(maxSize);
|
||||
dialog.userText->setText(placeHolder);
|
||||
dialog.userText->selectAll();
|
||||
dialog._label->setVisible(!prompt.isEmpty());
|
||||
dialog._label->setText(prompt);
|
||||
dialog._userText->setMaxLength(maxSize);
|
||||
dialog._userText->setText(placeHolder);
|
||||
dialog._userText->selectAll();
|
||||
|
||||
if (dialog.exec() != DialogCode::Accepted) {
|
||||
return false;
|
||||
}
|
||||
userTextInput = dialog.userText->text().toUtf8().constData();
|
||||
userTextInput = dialog._userText->text().toUtf8().constData();
|
||||
if (clean) {
|
||||
CleanWhitespace(userTextInput);
|
||||
cleanWhitespace(userTextInput);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,23 +8,23 @@
|
||||
namespace advss {
|
||||
|
||||
// Based on OBS's NameDialog
|
||||
class AdvSSNameDialog : public QDialog {
|
||||
class NameDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AdvSSNameDialog(QWidget *parent);
|
||||
NameDialog(QWidget *parent);
|
||||
|
||||
// Returns true if user clicks OK, false otherwise
|
||||
// userTextInput returns string that user typed into dialog
|
||||
EXPORT static bool AskForName(QWidget *parent, const QString &title,
|
||||
const QString &text,
|
||||
const QString &prompt,
|
||||
std::string &userTextInput,
|
||||
const QString &placeHolder = QString(""),
|
||||
int maxSize = 170, bool clean = true);
|
||||
|
||||
private:
|
||||
QLabel *label;
|
||||
QLineEdit *userText;
|
||||
QLabel *_label;
|
||||
QLineEdit *_userText;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -9,7 +9,8 @@ namespace advss {
|
||||
const char *obs_module_text(const char *text)
|
||||
{
|
||||
if (!advss::switcher) {
|
||||
return "";
|
||||
assert(false);
|
||||
return "obs_module_text called too early";
|
||||
}
|
||||
return advss::switcher->Translate(text);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static std::vector<std::function<void()>> &getPluginInitSteps()
|
||||
{
|
||||
static std::vector<std::function<void()>> steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
static std::vector<std::function<void()>> &getPluginPostLoadSteps()
|
||||
{
|
||||
static std::vector<std::function<void()>> steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
static std::vector<std::function<void()>> &getPluginCleanupSteps()
|
||||
{
|
||||
static std::vector<std::function<void()>> steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
static std::mutex mutex;
|
||||
|
||||
void SavePluginSettings(obs_data_t *obj)
|
||||
{
|
||||
GetSwitcher()->SaveSettings(obj);
|
||||
@@ -40,17 +60,44 @@ void RunPostLoadSteps()
|
||||
|
||||
void AddPluginInitStep(std::function<void()> step)
|
||||
{
|
||||
GetSwitcher()->AddPluginInitStep(step);
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
getPluginInitSteps().emplace_back(step);
|
||||
}
|
||||
|
||||
void AddPluginPostLoadStep(std::function<void()> step)
|
||||
{
|
||||
GetSwitcher()->AddPluginPostLoadStep(step);
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
getPluginPostLoadSteps().emplace_back(step);
|
||||
}
|
||||
|
||||
void AddPluginCleanupStep(std::function<void()> step)
|
||||
{
|
||||
GetSwitcher()->AddPluginCleanupStep(step);
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
getPluginCleanupSteps().emplace_back(step);
|
||||
}
|
||||
|
||||
void RunPluginInitSteps()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
for (const auto &step : getPluginInitSteps()) {
|
||||
step();
|
||||
}
|
||||
}
|
||||
|
||||
void RunPluginPostLoadSteps()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
for (const auto &step : getPluginPostLoadSteps()) {
|
||||
step();
|
||||
}
|
||||
}
|
||||
|
||||
void RunPluginCleanupSteps()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
for (const auto &step : getPluginCleanupSteps()) {
|
||||
step();
|
||||
}
|
||||
}
|
||||
|
||||
void StopPlugin()
|
||||
|
||||
@@ -17,6 +17,9 @@ EXPORT void RunPostLoadSteps();
|
||||
EXPORT void AddPluginInitStep(std::function<void()>);
|
||||
EXPORT void AddPluginPostLoadStep(std::function<void()>);
|
||||
EXPORT void AddPluginCleanupStep(std::function<void()>);
|
||||
void RunPluginInitSteps();
|
||||
extern "C" EXPORT void RunPluginPostLoadSteps();
|
||||
void RunPluginCleanupSteps();
|
||||
|
||||
EXPORT void StopPlugin();
|
||||
EXPORT void StartPlugin();
|
||||
|
||||
70
lib/utils/resource-table-hotkey-handler.cpp
Normal file
70
lib/utils/resource-table-hotkey-handler.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "resource-table-hotkey-handler.hpp"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QWidget>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace advss {
|
||||
|
||||
void RegisterHotkeyFunction(QWidget *widget, Qt::Key key,
|
||||
std::function<void()> func)
|
||||
{
|
||||
ResourceTabHotkeyHandler::Instance()->RegisterHandler(widget, key,
|
||||
func);
|
||||
}
|
||||
|
||||
void DeregisterHotkeyFunctions(QWidget *widget)
|
||||
{
|
||||
ResourceTabHotkeyHandler::Instance()->Deregister(widget);
|
||||
}
|
||||
|
||||
ResourceTabHotkeyHandler *ResourceTabHotkeyHandler::Instance()
|
||||
{
|
||||
static ResourceTabHotkeyHandler handler;
|
||||
return &handler;
|
||||
}
|
||||
|
||||
void ResourceTabHotkeyHandler::RegisterHandler(QWidget *widget, Qt::Key key,
|
||||
std::function<void()> func)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_callbacks.emplace(widget, CallbackData{key, func});
|
||||
widget->installEventFilter(this);
|
||||
}
|
||||
|
||||
void ResourceTabHotkeyHandler::Deregister(QWidget *widget)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_callbacks.erase(widget);
|
||||
}
|
||||
|
||||
bool ResourceTabHotkeyHandler::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() != QEvent::KeyPress) {
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
auto pressedKey = keyEvent->key();
|
||||
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
auto it = _callbacks.find(obj);
|
||||
if (it == _callbacks.end()) {
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
auto current = it;
|
||||
while (current != _callbacks.end() && current->first == it->first) {
|
||||
auto &[_, cbData] = *current;
|
||||
if (pressedKey != cbData.key) {
|
||||
++current;
|
||||
continue;
|
||||
}
|
||||
cbData.func();
|
||||
++current;
|
||||
continue;
|
||||
}
|
||||
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
37
lib/utils/resource-table-hotkey-handler.hpp
Normal file
37
lib/utils/resource-table-hotkey-handler.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include "export-symbol-helper.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <QEvent>
|
||||
#include <QObject>
|
||||
|
||||
namespace advss {
|
||||
|
||||
EXPORT void RegisterHotkeyFunction(QWidget *, Qt::Key,
|
||||
std::function<void()> func);
|
||||
EXPORT void DeregisterHotkeyFunctions(QWidget *);
|
||||
|
||||
class ResourceTabHotkeyHandler : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static ResourceTabHotkeyHandler *Instance();
|
||||
void RegisterHandler(QWidget *, Qt::Key, std::function<void()> func);
|
||||
void Deregister(QWidget *);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
private:
|
||||
struct CallbackData {
|
||||
Qt::Key key;
|
||||
std::function<void()> func;
|
||||
};
|
||||
|
||||
ResourceTabHotkeyHandler() : QObject(){};
|
||||
|
||||
std::multimap<QObject *, CallbackData> _callbacks;
|
||||
std::mutex _mutex;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
161
lib/utils/resource-table.cpp
Normal file
161
lib/utils/resource-table.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#include "resource-table.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "resource-table-hotkey-handler.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QHeaderView>
|
||||
|
||||
namespace advss {
|
||||
|
||||
ResourceTable::ResourceTable(QTabWidget *parent, const QString &help,
|
||||
const QString &addToolTip,
|
||||
const QString &removeToolTip,
|
||||
const QStringList &headers,
|
||||
const std::function<void()> &openSettings)
|
||||
: QWidget(parent),
|
||||
_table(new QTableWidget()),
|
||||
_add(new QPushButton()),
|
||||
_remove(new QPushButton()),
|
||||
_help(new QLabel(help))
|
||||
{
|
||||
_add->setMaximumWidth(22);
|
||||
_add->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("addIconSmall")));
|
||||
_add->setFlat(true);
|
||||
_add->setToolTip(addToolTip);
|
||||
|
||||
_remove->setMaximumWidth(22);
|
||||
_remove->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||
_remove->setFlat(true);
|
||||
_remove->setToolTip(removeToolTip);
|
||||
|
||||
_help->setWordWrap(true);
|
||||
_help->setAlignment(Qt::AlignCenter);
|
||||
|
||||
_table->setColumnCount(headers.size());
|
||||
_table->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::ResizeMode::Interactive);
|
||||
_table->setHorizontalHeaderLabels(headers);
|
||||
_table->verticalHeader()->hide();
|
||||
_table->setCornerButtonEnabled(false);
|
||||
_table->setShowGrid(false);
|
||||
_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
|
||||
auto helpAndTableLayout = new QGridLayout();
|
||||
helpAndTableLayout->setContentsMargins(0, 0, 0, 0);
|
||||
helpAndTableLayout->addWidget(_table, 0, 0);
|
||||
helpAndTableLayout->addWidget(_help, 0, 0, Qt::AlignCenter);
|
||||
|
||||
auto controlLayout = new QHBoxLayout;
|
||||
controlLayout->setContentsMargins(0, 0, 0, 0);
|
||||
controlLayout->addWidget(_add);
|
||||
controlLayout->addWidget(_remove);
|
||||
controlLayout->addStretch();
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(helpAndTableLayout);
|
||||
layout->addLayout(controlLayout);
|
||||
setLayout(layout);
|
||||
|
||||
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add()));
|
||||
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove()));
|
||||
QWidget::connect(_table, &QTableWidget::cellDoubleClicked,
|
||||
[openSettings]() { openSettings(); });
|
||||
|
||||
RegisterHotkeyFunction(this, Qt::Key_F2, openSettings);
|
||||
RegisterHotkeyFunction(this, Qt::Key_Delete, [this]() { Remove(); });
|
||||
}
|
||||
|
||||
ResourceTable::~ResourceTable()
|
||||
{
|
||||
DeregisterHotkeyFunctions(this);
|
||||
}
|
||||
|
||||
void ResourceTable::SetHelpVisible(bool visible) const
|
||||
{
|
||||
_help->setVisible(visible);
|
||||
}
|
||||
|
||||
void ResourceTable::HighlightAddButton(bool enable)
|
||||
{
|
||||
if (_highlightConnection) {
|
||||
_highlightConnection->deleteLater();
|
||||
_highlightConnection = nullptr;
|
||||
}
|
||||
|
||||
if (enable && HighlightUIElementsEnabled()) {
|
||||
_highlightConnection = HighlightWidget(_add, QColor(Qt::green));
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceTable::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
const auto columnCount = _table->columnCount();
|
||||
const auto columnSize = (_table->width() - 1) / columnCount;
|
||||
for (int i = 0; i < columnCount; ++i) {
|
||||
_table->horizontalHeader()->resizeSection(i, columnSize);
|
||||
}
|
||||
}
|
||||
|
||||
void AddItemTableRow(QTableWidget *table, const QStringList &cellLabels)
|
||||
{
|
||||
int row = table->rowCount();
|
||||
table->setRowCount(row + 1);
|
||||
|
||||
int col = 0;
|
||||
for (const auto &cellLabel : cellLabels) {
|
||||
auto *item = new QTableWidgetItem(cellLabel);
|
||||
item->setToolTip(cellLabel);
|
||||
table->setItem(row, col, item);
|
||||
col++;
|
||||
}
|
||||
|
||||
table->sortByColumn(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void UpdateItemTableRow(QTableWidget *table, int row,
|
||||
const QStringList &cellLabels)
|
||||
{
|
||||
int col = 1; // Skip the name cell
|
||||
for (const auto &cellLabel : cellLabels) {
|
||||
auto item = table->item(row, col);
|
||||
item->setText(cellLabel);
|
||||
item->setToolTip(cellLabel);
|
||||
col++;
|
||||
}
|
||||
}
|
||||
|
||||
void RenameItemTableRow(QTableWidget *table, const QString &oldName,
|
||||
const QString &newName)
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); row++) {
|
||||
auto item = table->item(row, 0);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item->text() == oldName) {
|
||||
item->setText(newName);
|
||||
table->sortByColumn(0, Qt::AscendingOrder);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void RemoveItemTableRow(QTableWidget *table, const QString &name)
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); ++row) {
|
||||
auto item = table->item(row, 0);
|
||||
if (item && item->text() == name) {
|
||||
table->removeRow(row);
|
||||
return;
|
||||
}
|
||||
}
|
||||
table->sortByColumn(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
50
lib/utils/resource-table.hpp
Normal file
50
lib/utils/resource-table.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include "export-symbol-helper.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QString>
|
||||
#include <QTableWidget>
|
||||
|
||||
class QResizeEvent;
|
||||
|
||||
namespace advss {
|
||||
|
||||
class ADVSS_EXPORT ResourceTable : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ResourceTable(QTabWidget *parent, const QString &help,
|
||||
const QString &addToolTip, const QString &removeToolTip,
|
||||
const QStringList &headers,
|
||||
const std::function<void()> &openSettings);
|
||||
virtual ~ResourceTable();
|
||||
|
||||
QTableWidget *Table() const { return _table; }
|
||||
void SetHelpVisible(bool) const;
|
||||
void HighlightAddButton(bool);
|
||||
|
||||
protected slots:
|
||||
virtual void Add() {}
|
||||
virtual void Remove() {}
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
QTableWidget *_table;
|
||||
QPushButton *_add;
|
||||
QPushButton *_remove;
|
||||
QLabel *_help;
|
||||
|
||||
QObject *_highlightConnection = nullptr;
|
||||
};
|
||||
|
||||
EXPORT void AddItemTableRow(QTableWidget *table, const QStringList &cells);
|
||||
EXPORT void UpdateItemTableRow(QTableWidget *table, int row,
|
||||
const QStringList &cells);
|
||||
EXPORT void RenameItemTableRow(QTableWidget *table, const QString &oldName,
|
||||
const QString &newName);
|
||||
EXPORT void RemoveItemTableRow(QTableWidget *table, const QString &name);
|
||||
|
||||
} // namespace advss
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <obs-frontend-api.h>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QPalette>
|
||||
#include <QToolBar>
|
||||
|
||||
namespace advss {
|
||||
@@ -15,6 +16,50 @@ namespace advss {
|
||||
void OpenSettingsWindow();
|
||||
StatusDock *dock = nullptr;
|
||||
|
||||
static QString colorToString(const QColor &color)
|
||||
{
|
||||
return QString("rgba(") + QString::number(color.red()) + "," +
|
||||
QString::number(color.green()) + "," +
|
||||
QString::number(color.blue()) + "," +
|
||||
QString::number(color.alpha()) + ")";
|
||||
}
|
||||
|
||||
static QString getDefaultBackgroundColorString()
|
||||
{
|
||||
static QString defaultColorString;
|
||||
static bool cacheReady = false;
|
||||
|
||||
if (cacheReady) {
|
||||
return defaultColorString;
|
||||
}
|
||||
|
||||
QWidget tempWidget;
|
||||
const auto defaultColor =
|
||||
tempWidget.palette().brush(QPalette::Window).color();
|
||||
defaultColorString = colorToString(defaultColor);
|
||||
|
||||
cacheReady = true;
|
||||
return defaultColorString;
|
||||
}
|
||||
|
||||
static QString getDefaultTextColorString()
|
||||
{
|
||||
static QString defaultColorString;
|
||||
static bool cacheReady = false;
|
||||
|
||||
if (cacheReady) {
|
||||
return defaultColorString;
|
||||
}
|
||||
|
||||
QLabel tempWidget;
|
||||
const auto defaultColor =
|
||||
tempWidget.palette().brush(QPalette::Text).color();
|
||||
defaultColorString = colorToString(defaultColor);
|
||||
|
||||
cacheReady = true;
|
||||
return defaultColorString;
|
||||
}
|
||||
|
||||
StatusControl::StatusControl(QWidget *parent, bool noLayout)
|
||||
: QWidget(parent),
|
||||
_button(new QPushButton("-", this)),
|
||||
@@ -28,30 +73,22 @@ StatusControl::StatusControl(QWidget *parent, bool noLayout)
|
||||
_statusPrefix->setWordWrap(true);
|
||||
_statusPrefix->setSizePolicy(QSizePolicy::Expanding,
|
||||
QSizePolicy::Expanding);
|
||||
_status->setStyleSheet("QLabel{ \
|
||||
border-style: outset; \
|
||||
border-width: 2px; \
|
||||
border-radius: 7px; \
|
||||
border-color: rgb(0,0,0,0) \
|
||||
}");
|
||||
_status->setSizePolicy(QSizePolicy::Maximum,
|
||||
QSizePolicy::MinimumExpanding);
|
||||
|
||||
QWidget::connect(_button, SIGNAL(clicked()), this,
|
||||
SLOT(ButtonClicked()));
|
||||
|
||||
if (!noLayout) {
|
||||
QHBoxLayout *statusLayout = new QHBoxLayout();
|
||||
statusLayout->addWidget(_statusPrefix);
|
||||
statusLayout->addStretch();
|
||||
statusLayout->addWidget(_status);
|
||||
statusLayout->setStretch(0, 10);
|
||||
_buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_buttonLayout->addWidget(_button);
|
||||
QVBoxLayout *layout = new QVBoxLayout();
|
||||
layout->addLayout(statusLayout);
|
||||
_statusPrefix->setAlignment(Qt::AlignCenter);
|
||||
_status->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(_statusPrefix);
|
||||
layout->addWidget(_status);
|
||||
layout->addLayout(_buttonLayout);
|
||||
setLayout(layout);
|
||||
} else {
|
||||
_status->setSizePolicy(QSizePolicy::Maximum,
|
||||
QSizePolicy::MinimumExpanding);
|
||||
}
|
||||
|
||||
if (PluginIsRunning()) {
|
||||
@@ -94,7 +131,8 @@ void StatusControl::SetStarted()
|
||||
_button->setText(
|
||||
obs_module_text("AdvSceneSwitcher.generalTab.status.stop"));
|
||||
_status->setText(obs_module_text("AdvSceneSwitcher.status.active"));
|
||||
_status->disconnect(_pulse);
|
||||
_pulse->deleteLater();
|
||||
SetStatusStyleSheet(false);
|
||||
_setToStopped = false;
|
||||
}
|
||||
|
||||
@@ -103,13 +141,31 @@ void StatusControl::SetStopped()
|
||||
_button->setText(
|
||||
obs_module_text("AdvSceneSwitcher.generalTab.status.start"));
|
||||
_status->setText(obs_module_text("AdvSceneSwitcher.status.inactive"));
|
||||
SetStatusStyleSheet(true);
|
||||
if (HighlightUIElementsEnabled()) {
|
||||
_pulse = PulseWidget(_status, QColor(Qt::red),
|
||||
QColor(0, 0, 0, 0));
|
||||
_pulse = HighlightWidget(_status, QColor(Qt::red),
|
||||
QColor(0, 0, 0, 0));
|
||||
}
|
||||
_setToStopped = true;
|
||||
}
|
||||
|
||||
void StatusControl::SetStatusStyleSheet(bool stopped) const
|
||||
{
|
||||
auto style = QString("QLabel{ "
|
||||
"background-color: ");
|
||||
if (stopped) {
|
||||
style += getDefaultBackgroundColorString() + "; ";
|
||||
} else {
|
||||
style += "transparent; ";
|
||||
}
|
||||
style += "border-style: outset; "
|
||||
"border-width: 2px; "
|
||||
"border-radius: 7px; "
|
||||
"border-color: " +
|
||||
getDefaultTextColorString() + "; }";
|
||||
_status->setStyleSheet(style);
|
||||
}
|
||||
|
||||
StatusDock::StatusDock(QWidget *parent) : OBSDock(parent)
|
||||
{
|
||||
setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
|
||||
|
||||
@@ -26,13 +26,14 @@ private slots:
|
||||
private:
|
||||
void SetStopped();
|
||||
void SetStarted();
|
||||
void SetStatusStyleSheet(bool stopped) const;
|
||||
|
||||
QPushButton *_button;
|
||||
QHBoxLayout *_buttonLayout;
|
||||
QLabel *_status;
|
||||
QLabel *_statusPrefix;
|
||||
QTimer _timer;
|
||||
QMetaObject::Connection _pulse;
|
||||
QObject *_pulse = nullptr;
|
||||
|
||||
bool _setToStopped = true;
|
||||
};
|
||||
|
||||
@@ -49,60 +49,12 @@ void StringList::ResolveVariables()
|
||||
StringListEdit::StringListEdit(QWidget *parent, const QString &addString,
|
||||
const QString &addStringDescription,
|
||||
int maxStringSize, bool allowEmtpy)
|
||||
: QWidget(parent),
|
||||
_list(new QListWidget()),
|
||||
_add(new QPushButton()),
|
||||
_remove(new QPushButton()),
|
||||
_up(new QPushButton()),
|
||||
_down(new QPushButton()),
|
||||
: ListEditor(parent),
|
||||
_addString(addString),
|
||||
_addStringDescription(addStringDescription),
|
||||
_maxStringSize(maxStringSize),
|
||||
_allowEmpty(allowEmtpy)
|
||||
{
|
||||
_add->setMaximumWidth(22);
|
||||
_add->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("addIconSmall")));
|
||||
_add->setFlat(true);
|
||||
_remove->setMaximumWidth(22);
|
||||
_remove->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||
_remove->setFlat(true);
|
||||
_up->setMaximumWidth(22);
|
||||
_up->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
||||
_up->setFlat(true);
|
||||
_down->setMaximumWidth(22);
|
||||
_down->setProperty("themeID",
|
||||
QVariant(QString::fromUtf8("downArrowIconSmall")));
|
||||
_down->setFlat(true);
|
||||
|
||||
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add()));
|
||||
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove()));
|
||||
QWidget::connect(_up, SIGNAL(clicked()), this, SLOT(Up()));
|
||||
QWidget::connect(_down, SIGNAL(clicked()), this, SLOT(Down()));
|
||||
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
||||
this, SLOT(Clicked(QListWidgetItem *)));
|
||||
|
||||
auto controlLayout = new QHBoxLayout;
|
||||
controlLayout->setContentsMargins(0, 0, 0, 0);
|
||||
controlLayout->addWidget(_add);
|
||||
controlLayout->addWidget(_remove);
|
||||
QFrame *line = new QFrame();
|
||||
line->setFrameShape(QFrame::VLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
controlLayout->addWidget(line);
|
||||
controlLayout->addWidget(_up);
|
||||
controlLayout->addWidget(_down);
|
||||
controlLayout->addStretch();
|
||||
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->addWidget(_list);
|
||||
mainLayout->addLayout(controlLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
}
|
||||
|
||||
void StringListEdit::SetStringList(const StringList &list)
|
||||
@@ -115,7 +67,7 @@ void StringListEdit::SetStringList(const StringList &list)
|
||||
_list);
|
||||
item->setData(Qt::UserRole, string);
|
||||
}
|
||||
SetListSize();
|
||||
UpdateListSize();
|
||||
}
|
||||
|
||||
void StringListEdit::SetMaxStringSize(int size)
|
||||
@@ -123,23 +75,12 @@ void StringListEdit::SetMaxStringSize(int size)
|
||||
_maxStringSize = size;
|
||||
}
|
||||
|
||||
void StringListEdit::showEvent(QShowEvent *e)
|
||||
{
|
||||
QWidget::showEvent(e);
|
||||
// This is necessary as the list viewport might not be updated yet
|
||||
// while the list was hidden.
|
||||
// Thus, previous calls to SetListSize() might not have resized the
|
||||
// widget correctly, for example due to not regarding the horizontal
|
||||
// scrollbar yet.
|
||||
SetListSize();
|
||||
}
|
||||
|
||||
void StringListEdit::Add()
|
||||
{
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(this, _addString,
|
||||
_addStringDescription, name,
|
||||
"", _maxStringSize, false);
|
||||
bool accepted = NameDialog::AskForName(this, _addString,
|
||||
_addStringDescription, name, "",
|
||||
_maxStringSize, false);
|
||||
|
||||
if (!accepted || (!_allowEmpty && name.empty())) {
|
||||
return;
|
||||
@@ -153,7 +94,7 @@ void StringListEdit::Add()
|
||||
_stringList << string;
|
||||
|
||||
// Delay resizing to make sure the list viewport was already updated
|
||||
QTimer::singleShot(0, this, [this]() { SetListSize(); });
|
||||
QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
|
||||
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
@@ -173,7 +114,7 @@ void StringListEdit::Remove()
|
||||
delete item;
|
||||
|
||||
// Delay resizing to make sure the list viewport was already updated
|
||||
QTimer::singleShot(0, this, [this]() { SetListSize(); });
|
||||
QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
|
||||
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
@@ -205,10 +146,10 @@ void StringListEdit::Down()
|
||||
void StringListEdit::Clicked(QListWidgetItem *item)
|
||||
{
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(this, _addString,
|
||||
_addStringDescription, name,
|
||||
item->text(),
|
||||
_maxStringSize, false);
|
||||
bool accepted = NameDialog::AskForName(this, _addString,
|
||||
_addStringDescription, name,
|
||||
item->text(), _maxStringSize,
|
||||
false);
|
||||
|
||||
if (!accepted || (!_allowEmpty && name.empty())) {
|
||||
return;
|
||||
@@ -222,16 +163,9 @@ void StringListEdit::Clicked(QListWidgetItem *item)
|
||||
_stringList[idx] = string;
|
||||
|
||||
// Delay resizing to make sure the list viewport was already updated
|
||||
QTimer::singleShot(0, this, [this]() { SetListSize(); });
|
||||
QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
|
||||
|
||||
StringListChanged(_stringList);
|
||||
}
|
||||
|
||||
void StringListEdit::SetListSize()
|
||||
{
|
||||
SetHeightToContentHeight(_list);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
@@ -1,27 +1,25 @@
|
||||
#pragma once
|
||||
#include "variable-string.hpp"
|
||||
#include "export-symbol-helper.hpp"
|
||||
#include "list-editor.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "variable-string.hpp"
|
||||
|
||||
#include <obs-data.h>
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <QStringList>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class StringList : public QList<StringVariable> {
|
||||
public:
|
||||
bool Save(obs_data_t *obj, const char *name,
|
||||
const char *elementName = "string") const;
|
||||
bool Load(obs_data_t *obj, const char *name,
|
||||
const char *elementName = "string");
|
||||
void ResolveVariables();
|
||||
EXPORT bool Save(obs_data_t *obj, const char *name,
|
||||
const char *elementName = "string") const;
|
||||
EXPORT bool Load(obs_data_t *obj, const char *name,
|
||||
const char *elementName = "string");
|
||||
EXPORT void ResolveVariables();
|
||||
|
||||
friend class StringListEdit;
|
||||
};
|
||||
|
||||
class StringListEdit : public QWidget {
|
||||
class ADVSS_EXPORT StringListEdit final : public ListEditor {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@@ -31,9 +29,6 @@ public:
|
||||
void SetStringList(const StringList &);
|
||||
void SetMaxStringSize(int);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
|
||||
private slots:
|
||||
void Add();
|
||||
void Remove();
|
||||
@@ -44,16 +39,8 @@ signals:
|
||||
void StringListChanged(const StringList &);
|
||||
|
||||
private:
|
||||
void SetListSize();
|
||||
|
||||
StringList _stringList;
|
||||
|
||||
QListWidget *_list;
|
||||
QPushButton *_add;
|
||||
QPushButton *_remove;
|
||||
QPushButton *_up;
|
||||
QPushButton *_down;
|
||||
|
||||
QString _addString;
|
||||
QString _addStringDescription;
|
||||
int _maxStringSize = 170;
|
||||
@@ -5,8 +5,15 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
EXPORT std::mutex *GetMutex();
|
||||
EXPORT std::lock_guard<std::mutex> LockContext();
|
||||
EXPORT std::unique_lock<std::mutex> *GetLoopLock();
|
||||
// Helper used in macro segment edit widgets
|
||||
#define GUARD_LOADING_AND_LOCK() \
|
||||
if (_loading || !_entryData) { \
|
||||
return; \
|
||||
} \
|
||||
auto lock = LockContext();
|
||||
|
||||
[[nodiscard]] EXPORT std::mutex *GetMutex();
|
||||
[[nodiscard]] EXPORT std::lock_guard<std::mutex> LockContext();
|
||||
[[nodiscard]] EXPORT std::unique_lock<std::mutex> *GetLoopLock();
|
||||
|
||||
} // namespace advss
|
||||
|
||||
182
lib/utils/tab-helpers.cpp
Normal file
182
lib/utils/tab-helpers.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
#include "tab-helpers.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
|
||||
#include <obs.hpp>
|
||||
#include <QTabBar>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace advss {
|
||||
|
||||
static std::vector<std::string> tabNames = {
|
||||
"generalTab", "macroTab", "windowTitleTab",
|
||||
"executableTab", "screenRegionTab", "mediaTab",
|
||||
"fileTab", "randomTab", "timeTab",
|
||||
"idleTab", "sceneSequenceTab", "audioTab",
|
||||
"videoTab", "networkTab", "sceneGroupTab",
|
||||
"transitionsTab", "pauseTab", "sceneTriggerTab"};
|
||||
|
||||
static std::vector<int> tabOrder = std::vector<int>(tabNames.size());
|
||||
|
||||
namespace {
|
||||
struct TabCallbacks {
|
||||
std::function<QWidget *()> createWidget;
|
||||
std::function<void(QTabWidget *)> setupTab;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static std::unordered_map<const char *, TabCallbacks> createTabCallbacks;
|
||||
|
||||
static int lastOpenedTab = -1;
|
||||
|
||||
void SetTabVisibleByName(QTabWidget *tabWidget, bool visible,
|
||||
const QString &name)
|
||||
{
|
||||
for (int idx = 0; idx < tabWidget->count(); idx++) {
|
||||
if (tabWidget->tabText(idx) != name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tabWidget->setTabVisible(idx, visible);
|
||||
}
|
||||
}
|
||||
|
||||
void AddSetupTabCallback(const char *tabName,
|
||||
std::function<QWidget *()> createWidget,
|
||||
std::function<void(QTabWidget *)> setupTab)
|
||||
{
|
||||
if (std::find(tabNames.begin(), tabNames.end(), tabName) !=
|
||||
tabNames.end()) {
|
||||
return;
|
||||
}
|
||||
tabNames.emplace_back(tabName);
|
||||
TabCallbacks callbacks = {createWidget, setupTab};
|
||||
createTabCallbacks.emplace(tabName, callbacks);
|
||||
}
|
||||
|
||||
void SaveLastOpenedTab(QTabWidget *tabWidget)
|
||||
{
|
||||
lastOpenedTab = tabWidget->currentIndex();
|
||||
}
|
||||
|
||||
void ResetLastOpenedTab()
|
||||
{
|
||||
lastOpenedTab = -1;
|
||||
}
|
||||
|
||||
void SaveTabOrder(obs_data_t *obj)
|
||||
{
|
||||
OBSDataArrayAutoRelease tabWidgetOrder = obs_data_array_create();
|
||||
for (size_t i = 0; i < tabNames.size(); i++) {
|
||||
OBSDataAutoRelease entry = obs_data_create();
|
||||
obs_data_set_int(entry, tabNames[i].c_str(), tabOrder[i]);
|
||||
obs_data_array_push_back(tabWidgetOrder, entry);
|
||||
}
|
||||
obs_data_set_array(obj, "tabWidgetOrder", tabWidgetOrder);
|
||||
}
|
||||
|
||||
static bool tabWidgetOrderValid()
|
||||
{
|
||||
auto tmp = std::vector<int>(tabNames.size());
|
||||
std::iota(tmp.begin(), tmp.end(), 0);
|
||||
|
||||
for (auto &p : tmp) {
|
||||
auto it = std::find(tabOrder.begin(), tabOrder.end(), p);
|
||||
if (it == tabOrder.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void resetTabWidgetOrder()
|
||||
{
|
||||
tabOrder = std::vector<int>(tabNames.size());
|
||||
std::iota(tabOrder.begin(), tabOrder.end(), 0);
|
||||
}
|
||||
|
||||
void LoadTabOrder(obs_data_t *obj)
|
||||
{
|
||||
OBSDataArrayAutoRelease defaultTabWidgetOrder = obs_data_array_create();
|
||||
for (size_t i = 0; i < tabNames.size(); i++) {
|
||||
OBSDataAutoRelease entry = obs_data_create();
|
||||
obs_data_set_default_int(entry, tabNames[i].c_str(), i);
|
||||
obs_data_array_push_back(defaultTabWidgetOrder, entry);
|
||||
}
|
||||
obs_data_set_default_array(obj, "tabWidgetOrder",
|
||||
defaultTabWidgetOrder);
|
||||
|
||||
tabOrder.clear();
|
||||
OBSDataArrayAutoRelease tabWidgetOrder =
|
||||
obs_data_get_array(obj, "tabWidgetOrder");
|
||||
for (size_t i = 0; i < tabNames.size(); i++) {
|
||||
OBSDataAutoRelease entry =
|
||||
obs_data_array_item(tabWidgetOrder, i);
|
||||
tabOrder.emplace_back(
|
||||
(int)(obs_data_get_int(entry, tabNames[i].c_str())));
|
||||
}
|
||||
|
||||
if (!tabWidgetOrderValid()) {
|
||||
resetTabWidgetOrder();
|
||||
}
|
||||
}
|
||||
|
||||
static int findTabIndex(QTabWidget *tabWidget, int pos)
|
||||
{
|
||||
int at = -1;
|
||||
QString tabName = QString::fromStdString(tabNames.at(pos));
|
||||
QWidget *page = tabWidget->findChild<QWidget *>(tabName);
|
||||
if (page) {
|
||||
at = tabWidget->indexOf(page);
|
||||
}
|
||||
if (at == -1) {
|
||||
blog(LOG_INFO, "failed to find tab %s",
|
||||
tabName.toUtf8().constData());
|
||||
}
|
||||
|
||||
return at;
|
||||
}
|
||||
|
||||
void SetTabOrder(QTabWidget *tabWidget)
|
||||
{
|
||||
if (!tabWidgetOrderValid()) {
|
||||
resetTabWidgetOrder();
|
||||
}
|
||||
|
||||
auto bar = tabWidget->tabBar();
|
||||
for (int i = 0; i < bar->count(); ++i) {
|
||||
int curPos = findTabIndex(tabWidget, tabOrder[i]);
|
||||
|
||||
if (i != curPos && curPos != -1) {
|
||||
bar->moveTab(curPos, i);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget::connect(bar, &QTabBar::tabMoved, [](int from, int to) {
|
||||
std::swap(tabOrder[from], tabOrder[to]);
|
||||
});
|
||||
}
|
||||
|
||||
void SetCurrentTab(QTabWidget *tabWidget)
|
||||
{
|
||||
if (lastOpenedTab >= 0 && tabWidget->isTabVisible(lastOpenedTab)) {
|
||||
tabWidget->setCurrentIndex(lastOpenedTab);
|
||||
}
|
||||
}
|
||||
|
||||
void SetupOtherTabs(QTabWidget *tabWidget)
|
||||
{
|
||||
for (const auto &[name, callbacks] : createTabCallbacks) {
|
||||
auto widget = callbacks.createWidget();
|
||||
widget->setObjectName(name);
|
||||
auto tabText = obs_module_text(
|
||||
(std::string("AdvSceneSwitcher.") + name + ".title")
|
||||
.c_str());
|
||||
tabWidget->insertTab(0, widget, tabText);
|
||||
callbacks.setupTab(tabWidget);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
22
lib/utils/tab-helpers.hpp
Normal file
22
lib/utils/tab-helpers.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "export-symbol-helper.hpp"
|
||||
|
||||
#include <obs-data.h>
|
||||
#include <QTabWidget>
|
||||
|
||||
namespace advss {
|
||||
|
||||
EXPORT void AddSetupTabCallback(const char *tabName,
|
||||
std::function<QWidget *()> createWidget,
|
||||
std::function<void(QTabWidget *)> setupTab);
|
||||
EXPORT void SetTabVisibleByName(QTabWidget *tabWidget, bool visible,
|
||||
const QString &name);
|
||||
void SaveLastOpenedTab(QTabWidget *tabWidget);
|
||||
void ResetLastOpenedTab();
|
||||
void SetTabOrder(QTabWidget *tabWidget);
|
||||
void SetCurrentTab(QTabWidget *tabWidget);
|
||||
void SetupOtherTabs(QTabWidget *tabWidget);
|
||||
void SaveTabOrder(obs_data_t *obj);
|
||||
void LoadTabOrder(obs_data_t *obj);
|
||||
|
||||
} // namespace advss
|
||||
@@ -250,6 +250,8 @@ TempVariableSelection::TempVariableSelection(QWidget *parent)
|
||||
_info->setPixmap(pixmap);
|
||||
_info->hide();
|
||||
|
||||
_selection->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
_selection->setMaximumWidth(350);
|
||||
_selection->setDuplicatesEnabled(true);
|
||||
PopulateSelection();
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
EXPORT void Load(obs_data_t *, Macro *, const char *name = "tempVar");
|
||||
EXPORT std::optional<const TempVariable> GetTempVariable(Macro *) const;
|
||||
EXPORT bool operator==(const TempVariableRef &other) const;
|
||||
bool HasValidID() const { return !_id.empty(); }
|
||||
|
||||
private:
|
||||
enum class SegmentType { NONE, CONDITION, ACTION, ELSEACTION };
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
||||
QColor endColor, bool once)
|
||||
QObject *HighlightWidget(QWidget *widget, QColor startColor, QColor endColor,
|
||||
bool once)
|
||||
{
|
||||
QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect(widget);
|
||||
widget->setGraphicsEffect(effect);
|
||||
@@ -24,33 +24,22 @@ QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
||||
animation->setEndValue(endColor);
|
||||
animation->setDuration(1000);
|
||||
|
||||
QMetaObject::Connection con;
|
||||
// Clean up the effect when the animation is deleted
|
||||
QWidget::connect(animation, &QPropertyAnimation::destroyed, [widget]() {
|
||||
if (widget) {
|
||||
widget->setGraphicsEffect(nullptr);
|
||||
}
|
||||
});
|
||||
|
||||
if (once) {
|
||||
auto widgetPtr = widget;
|
||||
con = QWidget::connect(
|
||||
animation, &QPropertyAnimation::finished,
|
||||
[widgetPtr]() {
|
||||
if (widgetPtr) {
|
||||
widgetPtr->setGraphicsEffect(nullptr);
|
||||
}
|
||||
});
|
||||
animation->start(QPropertyAnimation::DeleteWhenStopped);
|
||||
} else {
|
||||
auto widgetPtr = widget;
|
||||
con = QWidget::connect(
|
||||
animation, &QPropertyAnimation::finished,
|
||||
[animation, widgetPtr]() {
|
||||
QTimer *timer = new QTimer(widgetPtr);
|
||||
QWidget::connect(timer, &QTimer::timeout,
|
||||
[animation] {
|
||||
animation->start();
|
||||
});
|
||||
timer->setSingleShot(true);
|
||||
timer->start(1000);
|
||||
});
|
||||
animation->start();
|
||||
return animation;
|
||||
}
|
||||
return con;
|
||||
|
||||
QWidget::connect(animation, &QPropertyAnimation::finished,
|
||||
[animation]() { animation->start(); });
|
||||
animation->start();
|
||||
return animation;
|
||||
}
|
||||
|
||||
static int getHorizontalScrollBarHeight(QListWidget *list)
|
||||
@@ -166,4 +155,9 @@ std::string GetThemeTypeName()
|
||||
#endif
|
||||
}
|
||||
|
||||
void QeueUITask(void (*task)(void *param), void *param)
|
||||
{
|
||||
obs_queue_task(OBS_TASK_UI, task, param, false);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
EXPORT QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
||||
QColor endColor = QColor(0, 0, 0, 0),
|
||||
bool once = false);
|
||||
// Returns QObject* to QPropertyAnimation object
|
||||
// Delete it to stop the animation
|
||||
EXPORT QObject *HighlightWidget(QWidget *widget, QColor startColor,
|
||||
QColor endColor = QColor(0, 0, 0, 0),
|
||||
bool once = false);
|
||||
|
||||
EXPORT void SetHeightToContentHeight(QListWidget *list);
|
||||
EXPORT void SetButtonIcon(QPushButton *button, const char *path);
|
||||
@@ -29,4 +31,6 @@ EXPORT void DisplayTrayMessage(const QString &title, const QString &msg,
|
||||
|
||||
EXPORT std::string GetThemeTypeName();
|
||||
|
||||
void QeueUITask(void (*task)(void *param), void *param);
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -76,15 +76,15 @@ std::string ToString(double value)
|
||||
}
|
||||
|
||||
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
||||
QPushButton *addButton,
|
||||
QMetaObject::Connection *addHighlight)
|
||||
QPushButton *addButton, QObject *addHighlight)
|
||||
{
|
||||
if (!list || !newWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (addButton && addHighlight) {
|
||||
addButton->disconnect(*addHighlight);
|
||||
if (addHighlight) {
|
||||
addHighlight->deleteLater();
|
||||
addHighlight = nullptr;
|
||||
}
|
||||
|
||||
QListWidgetItem *item;
|
||||
|
||||
@@ -24,7 +24,7 @@ std::string ToString(double value);
|
||||
|
||||
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
||||
QPushButton *addButton = nullptr,
|
||||
QMetaObject::Connection *addHighlight = nullptr);
|
||||
QObject *addHighlight = nullptr);
|
||||
bool listMoveUp(QListWidget *list);
|
||||
bool listMoveDown(QListWidget *list);
|
||||
|
||||
|
||||
@@ -1,28 +1,61 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "variable-tab.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "sync-helpers.hpp"
|
||||
#include "tab-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
#include <QTableWidgetItem>
|
||||
#include <QTimer>
|
||||
|
||||
namespace advss {
|
||||
|
||||
static void setVariableTabVisible(QTabWidget *tabWidget, bool visible)
|
||||
{
|
||||
for (int idx = 0; idx < tabWidget->count(); idx++) {
|
||||
if (tabWidget->tabText(idx) !=
|
||||
obs_module_text("AdvSceneSwitcher.variableTab.title")) {
|
||||
continue;
|
||||
}
|
||||
static bool registerTab();
|
||||
static void setupTab(QTabWidget *);
|
||||
static bool registerTabDone = registerTab();
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
// TODO: Switch to setTabVisible() once QT 5.15 is more wide spread
|
||||
tabWidget->setTabEnabled(idx, visible);
|
||||
tabWidget->setStyleSheet(
|
||||
"QTabBar::tab::disabled {width: 0; height: 0; margin: 0; padding: 0; border: none;} ");
|
||||
#else
|
||||
tabWidget->setTabVisible(idx, visible);
|
||||
#endif
|
||||
static VariableTable *tabWidget = nullptr;
|
||||
|
||||
static bool registerTab()
|
||||
{
|
||||
AddPluginInitStep([]() {
|
||||
AddSetupTabCallback("variableTab", VariableTable::Create,
|
||||
setupTab);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setTabVisible(QTabWidget *tabWidget, bool visible)
|
||||
{
|
||||
SetTabVisibleByName(
|
||||
tabWidget, visible,
|
||||
obs_module_text("AdvSceneSwitcher.variableTab.title"));
|
||||
}
|
||||
|
||||
VariableTable *VariableTable::Create()
|
||||
{
|
||||
tabWidget = new VariableTable();
|
||||
return tabWidget;
|
||||
}
|
||||
|
||||
void VariableTable::Add()
|
||||
{
|
||||
auto newVariable = std::make_shared<Variable>();
|
||||
auto accepted =
|
||||
VariableSettingsDialog::AskForSettings(this, *newVariable);
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
auto &variables = GetVariables();
|
||||
variables.emplace_back(newVariable);
|
||||
}
|
||||
|
||||
VariableSignalManager::Instance()->Add(
|
||||
QString::fromStdString(newVariable->Name()));
|
||||
}
|
||||
|
||||
static QString formatSaveActionText(Variable *variable)
|
||||
@@ -91,46 +124,18 @@ static QString formatLastChangedTooltip(Variable *variable)
|
||||
.arg(QString::fromStdString(variable->GetPreviousValue()));
|
||||
}
|
||||
|
||||
static void addVariableRow(QTableWidget *table, Variable *variable)
|
||||
static QStringList getCellLabels(Variable *variable, bool addName = true)
|
||||
{
|
||||
if (!variable) {
|
||||
blog(LOG_INFO, "%s called with nullptr", __func__);
|
||||
assert(false);
|
||||
return;
|
||||
assert(variable);
|
||||
|
||||
auto result = QStringList();
|
||||
if (addName) {
|
||||
result << QString::fromStdString(variable->Name());
|
||||
}
|
||||
|
||||
int row = table->rowCount();
|
||||
table->setRowCount(row + 1);
|
||||
|
||||
int col = 0;
|
||||
auto *item =
|
||||
new QTableWidgetItem(QString::fromStdString(variable->Name()));
|
||||
table->setItem(row, col, item);
|
||||
auto varValue = QString::fromStdString(variable->Value(false));
|
||||
item = new QTableWidgetItem(varValue);
|
||||
item->setToolTip(varValue);
|
||||
table->setItem(row, ++col, item);
|
||||
item = new QTableWidgetItem(formatSaveActionText(variable));
|
||||
table->setItem(row, ++col, item);
|
||||
item = new QTableWidgetItem(formatLastUsedText(variable));
|
||||
table->setItem(row, ++col, item);
|
||||
item = new QTableWidgetItem(formatLastChangedText(variable));
|
||||
item->setToolTip(formatLastChangedTooltip(variable));
|
||||
table->setItem(row, ++col, item);
|
||||
|
||||
table->sortByColumn(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
static void removeVariableRow(QTableWidget *table, const QString &name)
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); ++row) {
|
||||
auto item = table->item(row, 0);
|
||||
if (item && item->text() == name) {
|
||||
table->removeRow(row);
|
||||
return;
|
||||
}
|
||||
}
|
||||
table->sortByColumn(0, Qt::AscendingOrder);
|
||||
result << QString::fromStdString(variable->Value(false))
|
||||
<< formatSaveActionText(variable) << formatLastUsedText(variable)
|
||||
<< formatLastChangedText(variable);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void updateVariableStatus(QTableWidget *table)
|
||||
@@ -147,116 +152,29 @@ static void updateVariableStatus(QTableWidget *table)
|
||||
continue;
|
||||
}
|
||||
|
||||
item = table->item(row, 1);
|
||||
auto varValue = QString::fromStdString(variable->Value(false));
|
||||
item->setText(varValue);
|
||||
item->setToolTip(varValue);
|
||||
item = table->item(row, 2);
|
||||
item->setText(formatSaveActionText(variable.get()));
|
||||
item = table->item(row, 3);
|
||||
item->setText(formatLastUsedText(variable.get()));
|
||||
item = table->item(row, 4);
|
||||
item->setText(formatLastChangedText(variable.get()));
|
||||
item->setToolTip(formatLastChangedTooltip(variable.get()));
|
||||
}
|
||||
}
|
||||
UpdateItemTableRow(table, row,
|
||||
getCellLabels(variable.get(), false));
|
||||
|
||||
static void renameVariable(QTableWidget *table, const QString &oldName,
|
||||
const QString &newName)
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); row++) {
|
||||
auto item = table->item(row, 0);
|
||||
if (!item) {
|
||||
// Special tooltip handling for the "last used" cell
|
||||
const auto lastUsedItem = table->item(row, 4);
|
||||
if (!lastUsedItem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item->text() == oldName) {
|
||||
item->setText(newName);
|
||||
table->sortByColumn(0, Qt::AscendingOrder);
|
||||
return;
|
||||
}
|
||||
const auto lastUsedTooltip =
|
||||
formatLastChangedTooltip(variable.get());
|
||||
lastUsedItem->setToolTip(lastUsedTooltip);
|
||||
}
|
||||
blog(LOG_INFO, "%s called but entry \"%s\" not found", __func__,
|
||||
oldName.toStdString().c_str());
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupVariableTab()
|
||||
static void openSettingsDialog()
|
||||
{
|
||||
ui->variables->installEventFilter(this);
|
||||
|
||||
if (GetVariables().empty()) {
|
||||
setVariableTabVisible(ui->tabWidget, false);
|
||||
} else {
|
||||
ui->variablesHelp->hide();
|
||||
}
|
||||
|
||||
static const QStringList horizontalHeaders =
|
||||
QStringList()
|
||||
<< obs_module_text("AdvSceneSwitcher.variableTab.name.header")
|
||||
<< obs_module_text("AdvSceneSwitcher.variableTab.value.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.saveLoadBehavior.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.lastUsed.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.lastChanged.header");
|
||||
|
||||
auto &variables = GetVariables();
|
||||
|
||||
ui->variables->setColumnCount(horizontalHeaders.size());
|
||||
ui->variables->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::ResizeMode::Stretch);
|
||||
ui->variables->setHorizontalHeaderLabels(horizontalHeaders);
|
||||
|
||||
for (const auto &var : variables) {
|
||||
auto variable = std::static_pointer_cast<Variable>(var);
|
||||
addVariableRow(ui->variables, variable.get());
|
||||
}
|
||||
|
||||
ui->variables->resizeColumnsToContents();
|
||||
ui->variables->resizeRowsToContents();
|
||||
|
||||
QWidget::connect(
|
||||
VariableSignalManager::Instance(),
|
||||
&VariableSignalManager::Rename,
|
||||
[this](const QString &oldName, const QString &newName) {
|
||||
renameVariable(ui->variables, oldName, newName);
|
||||
});
|
||||
QWidget::connect(VariableSignalManager::Instance(),
|
||||
&VariableSignalManager::Add, this,
|
||||
[this](const QString &name) {
|
||||
addVariableRow(ui->variables,
|
||||
GetVariableByQString(name));
|
||||
ui->variablesHelp->hide();
|
||||
setVariableTabVisible(ui->tabWidget, true);
|
||||
});
|
||||
QWidget::connect(VariableSignalManager::Instance(),
|
||||
&VariableSignalManager::Remove, this,
|
||||
[this](const QString &name) {
|
||||
removeVariableRow(ui->variables, name);
|
||||
if (ui->variables->rowCount() == 0) {
|
||||
ui->variablesHelp->show();
|
||||
}
|
||||
});
|
||||
QWidget::connect(ui->variables, &QTableWidget::cellDoubleClicked, this,
|
||||
&AdvSceneSwitcher::OpenSettingsForSelectedVariable);
|
||||
|
||||
auto timer = new QTimer(this);
|
||||
timer->setInterval(1000);
|
||||
QWidget::connect(timer, &QTimer::timeout,
|
||||
[this]() { updateVariableStatus(ui->variables); });
|
||||
timer->start();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::OpenSettingsForSelectedVariable()
|
||||
{
|
||||
auto selectedRows = ui->variables->selectionModel()->selectedRows();
|
||||
auto selectedRows =
|
||||
tabWidget->Table()->selectionModel()->selectedRows();
|
||||
if (selectedRows.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto cell = ui->variables->item(selectedRows.last().row(), 0);
|
||||
auto cell = tabWidget->Table()->item(selectedRows.last().row(), 0);
|
||||
if (!cell) {
|
||||
return;
|
||||
}
|
||||
@@ -268,8 +186,8 @@ void AdvSceneSwitcher::OpenSettingsForSelectedVariable()
|
||||
}
|
||||
|
||||
auto oldName = variable->Name();
|
||||
bool accepted = VariableSettingsDialog::AskForSettings(ui->variables,
|
||||
*variable.get());
|
||||
bool accepted = VariableSettingsDialog::AskForSettings(
|
||||
tabWidget->Table(), *variable.get());
|
||||
if (accepted && oldName != variable->Name()) {
|
||||
VariableSignalManager::Instance()->Rename(
|
||||
QString::fromStdString(oldName),
|
||||
@@ -277,35 +195,17 @@ void AdvSceneSwitcher::OpenSettingsForSelectedVariable()
|
||||
}
|
||||
}
|
||||
|
||||
static void removeVariablesWithNames(const QStringList &varNames)
|
||||
void VariableTable::Remove()
|
||||
{
|
||||
for (const auto &name : varNames) {
|
||||
auto variable = GetVariableByQString(name);
|
||||
if (!variable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto &variables = GetVariables();
|
||||
variables.erase(
|
||||
std::remove_if(
|
||||
variables.begin(), variables.end(),
|
||||
[variable](const std::shared_ptr<Item> &item) {
|
||||
return item.get() == variable;
|
||||
}),
|
||||
variables.end());
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveSelectedVariables()
|
||||
{
|
||||
auto selectedRows = ui->variables->selectionModel()->selectedRows();
|
||||
auto selectedRows =
|
||||
tabWidget->Table()->selectionModel()->selectedRows();
|
||||
if (selectedRows.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList varNames;
|
||||
for (auto row : selectedRows) {
|
||||
auto cell = ui->variables->item(row.row(), 0);
|
||||
for (const auto &row : selectedRows) {
|
||||
auto cell = tabWidget->Table()->item(row.row(), 0);
|
||||
if (!cell) {
|
||||
continue;
|
||||
}
|
||||
@@ -330,7 +230,7 @@ void AdvSceneSwitcher::RemoveSelectedVariables()
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
removeVariablesWithNames(varNames);
|
||||
RemoveItemsByName(GetVariables(), varNames);
|
||||
}
|
||||
|
||||
for (const auto &name : varNames) {
|
||||
@@ -338,28 +238,71 @@ void AdvSceneSwitcher::RemoveSelectedVariables()
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_variableAdd_clicked()
|
||||
VariableTable::VariableTable(QTabWidget *parent)
|
||||
: ResourceTable(
|
||||
parent, obs_module_text("AdvSceneSwitcher.variableTab.help"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.variableAddButton.tooltip"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.variableRemoveButton.tooltip"),
|
||||
QStringList()
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.name.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.value.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.saveLoadBehavior.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.lastUsed.header")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.variableTab.lastChanged.header"),
|
||||
openSettingsDialog)
|
||||
{
|
||||
auto newVariable = std::make_shared<Variable>();
|
||||
auto accepted =
|
||||
VariableSettingsDialog::AskForSettings(this, *newVariable);
|
||||
if (!accepted) {
|
||||
return;
|
||||
for (const auto &variable : GetVariables()) {
|
||||
auto v = std::static_pointer_cast<Variable>(variable);
|
||||
AddItemTableRow(Table(), getCellLabels(v.get()));
|
||||
}
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
auto &variables = GetVariables();
|
||||
variables.emplace_back(newVariable);
|
||||
}
|
||||
|
||||
VariableSignalManager::Instance()->Add(
|
||||
QString::fromStdString(newVariable->Name()));
|
||||
SetHelpVisible(GetVariables().empty());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_variableRemove_clicked()
|
||||
static void setupTab(QTabWidget *tab)
|
||||
{
|
||||
RemoveSelectedVariables();
|
||||
if (GetVariables().empty()) {
|
||||
setTabVisible(tab, false);
|
||||
}
|
||||
|
||||
QWidget::connect(VariableSignalManager::Instance(),
|
||||
&VariableSignalManager::Rename, tab,
|
||||
[](const QString &oldName, const QString &newName) {
|
||||
RenameItemTableRow(tabWidget->Table(), oldName,
|
||||
newName);
|
||||
});
|
||||
QWidget::connect(
|
||||
VariableSignalManager::Instance(), &VariableSignalManager::Add,
|
||||
tab, [tab](const QString &name) {
|
||||
AddItemTableRow(
|
||||
tabWidget->Table(),
|
||||
getCellLabels(GetVariableByQString(name)));
|
||||
tabWidget->SetHelpVisible(false);
|
||||
tabWidget->HighlightAddButton(false);
|
||||
setTabVisible(tab, true);
|
||||
});
|
||||
QWidget::connect(VariableSignalManager::Instance(),
|
||||
&VariableSignalManager::Remove, tab,
|
||||
[](const QString &name) {
|
||||
RemoveItemTableRow(tabWidget->Table(), name);
|
||||
if (tabWidget->Table()->rowCount() == 0) {
|
||||
tabWidget->SetHelpVisible(true);
|
||||
tabWidget->HighlightAddButton(true);
|
||||
}
|
||||
});
|
||||
|
||||
auto timer = new QTimer(tabWidget);
|
||||
timer->setInterval(1000);
|
||||
QWidget::connect(timer, &QTimer::timeout,
|
||||
[]() { updateVariableStatus(tabWidget->Table()); });
|
||||
timer->start();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
20
lib/variables/variable-tab.hpp
Normal file
20
lib/variables/variable-tab.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "resource-table.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableTable final : public ResourceTable {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static VariableTable *Create();
|
||||
|
||||
private slots:
|
||||
void Add();
|
||||
void Remove();
|
||||
|
||||
private:
|
||||
VariableTable(QTabWidget *parent = nullptr);
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "variable.hpp"
|
||||
#include "math-helpers.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QGridLayout>
|
||||
@@ -267,6 +268,53 @@ void VariableSelection::SetVariable(const std::weak_ptr<Variable> &variable_)
|
||||
}
|
||||
}
|
||||
|
||||
VariableSelectionDialog::VariableSelectionDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
_variableSelection(new VariableSelection(this))
|
||||
{
|
||||
setModal(true);
|
||||
setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setMinimumWidth(350);
|
||||
setMinimumHeight(70);
|
||||
|
||||
auto buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok |
|
||||
QDialogButtonBox::Cancel);
|
||||
|
||||
buttonbox->setCenterButtons(true);
|
||||
connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
auto selectionLayout = new QHBoxLayout();
|
||||
selectionLayout->addWidget(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.variable.selectionDialog")));
|
||||
selectionLayout->addWidget(_variableSelection);
|
||||
selectionLayout->addStretch();
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(selectionLayout);
|
||||
layout->addWidget(buttonbox);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
QWidget *GetSettingsWindow();
|
||||
|
||||
bool VariableSelectionDialog::AskForVariable(QWidget *parent,
|
||||
std::string &varName)
|
||||
{
|
||||
VariableSelectionDialog dialog(GetSettingsWindow());
|
||||
dialog.setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
|
||||
|
||||
if (dialog.exec() != DialogCode::Accepted) {
|
||||
return false;
|
||||
}
|
||||
auto item = dialog._variableSelection->GetCurrentItem();
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
varName = item->Name();
|
||||
return true;
|
||||
}
|
||||
|
||||
VariableSignalManager::VariableSignalManager(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
@@ -375,11 +423,23 @@ void LoadVariables(obs_data_t *obj)
|
||||
obs_data_array_release(variablesArray);
|
||||
}
|
||||
|
||||
static void signalImportedVariables(void *varsPtr)
|
||||
{
|
||||
auto vars = std::unique_ptr<std::vector<std::shared_ptr<Item>>>(
|
||||
static_cast<std::vector<std::shared_ptr<Item>> *>(varsPtr));
|
||||
for (const auto &var : *vars) {
|
||||
VariableSignalManager::Instance()->Add(
|
||||
QString::fromStdString(var->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
void ImportVariables(obs_data_t *data)
|
||||
{
|
||||
obs_data_array_t *array = obs_data_get_array(data, "variables");
|
||||
size_t count = obs_data_array_count(array);
|
||||
|
||||
auto importedVars = new std::vector<std::shared_ptr<Item>>;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *arrayElement = obs_data_array_item(array, i);
|
||||
auto var = Variable::Create();
|
||||
@@ -391,9 +451,12 @@ void ImportVariables(obs_data_t *data)
|
||||
}
|
||||
|
||||
GetVariables().emplace_back(var);
|
||||
importedVars->emplace_back(var);
|
||||
}
|
||||
|
||||
obs_data_array_release(array);
|
||||
|
||||
QeueUITask(signalImportedVariables, importedVars);
|
||||
}
|
||||
|
||||
std::chrono::high_resolution_clock::time_point GetLastVariableChangeTime()
|
||||
|
||||
@@ -82,6 +82,17 @@ public:
|
||||
void SetVariable(const std::weak_ptr<Variable> &);
|
||||
};
|
||||
|
||||
class VariableSelectionDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableSelectionDialog(QWidget *parent);
|
||||
static bool AskForVariable(QWidget *parent, std::string &variableName);
|
||||
|
||||
private:
|
||||
VariableSelection *_variableSelection;
|
||||
};
|
||||
|
||||
class ADVSS_EXPORT VariableSignalManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
@@ -87,6 +87,8 @@ target_sources(
|
||||
macro-condition-file.hpp
|
||||
macro-condition-filter.cpp
|
||||
macro-condition-filter.hpp
|
||||
macro-condition-folder.cpp
|
||||
macro-condition-folder.hpp
|
||||
macro-condition-hotkey.cpp
|
||||
macro-condition-hotkey.hpp
|
||||
macro-condition-idle.cpp
|
||||
@@ -166,8 +168,6 @@ target_sources(
|
||||
utils/source-settings-helpers.hpp
|
||||
utils/source-setting.cpp
|
||||
utils/source-setting.hpp
|
||||
utils/string-list.cpp
|
||||
utils/string-list.hpp
|
||||
utils/striped-frame.cpp
|
||||
utils/striped-frame.hpp
|
||||
utils/text-helpers.cpp
|
||||
@@ -175,7 +175,9 @@ target_sources(
|
||||
utils/transition-selection.cpp
|
||||
utils/transition-selection.hpp
|
||||
utils/websocket-helpers.cpp
|
||||
utils/websocket-helpers.hpp)
|
||||
utils/websocket-helpers.hpp
|
||||
utils/websocket-tab.cpp
|
||||
utils/websocket-tab.hpp)
|
||||
|
||||
if(OS_WINDOWS)
|
||||
target_sources(${PROJECT_NAME} PRIVATE utils/windows/windows.cpp)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "macro-action-run.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QDesktopServices>
|
||||
@@ -130,16 +129,10 @@ MacroActionRunEdit::MacroActionRunEdit(
|
||||
_waitLayout(new QHBoxLayout()),
|
||||
_wait(new QCheckBox()),
|
||||
_timeout(new DurationSelection(this, true, 0.1)),
|
||||
_waitHelp(new QLabel())
|
||||
_waitHelp(new HelpIcon(obs_module_text(
|
||||
"AdvSceneSwitcher.action.run.wait.help.tooltip")))
|
||||
{
|
||||
QString helpIconPath = GetThemeTypeName() == "Light"
|
||||
? ":/res/images/help.svg"
|
||||
: ":/res/images/help_light.svg";
|
||||
QIcon helpIcon(helpIconPath);
|
||||
_waitHelp->setPixmap(helpIcon.pixmap(QSize(16, 16)));
|
||||
_waitHelp->hide();
|
||||
_waitHelp->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.action.run.wait.help.tooltip"));
|
||||
|
||||
QWidget::connect(_procConfig,
|
||||
SIGNAL(ConfigChanged(const ProcessConfig &)), this,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "help-icon.hpp"
|
||||
#include "process-config.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
@@ -60,7 +61,7 @@ private:
|
||||
QHBoxLayout *_waitLayout;
|
||||
QCheckBox *_wait;
|
||||
DurationSelection *_timeout;
|
||||
QLabel *_waitHelp;
|
||||
HelpIcon *_waitHelp;
|
||||
|
||||
std::shared_ptr<MacroActionRun> _entryData;
|
||||
bool _loading = true;
|
||||
|
||||
@@ -94,15 +94,15 @@ MacroActionSystrayEdit::MacroActionSystrayEdit(
|
||||
layout->addWidget(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.systray.title")),
|
||||
row, 0);
|
||||
layout->addWidget(_title, ++row, 1);
|
||||
layout->addWidget(_title, row++, 1);
|
||||
layout->addWidget(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.systray.message")),
|
||||
row, 0);
|
||||
layout->addWidget(_message, ++row, 1);
|
||||
layout->addWidget(_message, row++, 1);
|
||||
layout->addWidget(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.systray.icon")),
|
||||
row, 0);
|
||||
layout->addWidget(_iconPath, ++row, 1);
|
||||
layout->addWidget(_iconPath, row++, 1);
|
||||
|
||||
auto mainlayout = new QVBoxLayout();
|
||||
mainlayout->addLayout(layout);
|
||||
|
||||
@@ -151,7 +151,7 @@ MacroActionWebsocketEdit::MacroActionWebsocketEdit(
|
||||
_apiType(new QComboBox(this)),
|
||||
_messageType(new QComboBox(this)),
|
||||
_message(new VariableTextEdit(this)),
|
||||
_connection(new ConnectionSelection(this)),
|
||||
_connection(new WSConnectionSelection(this)),
|
||||
_editLayout(new QHBoxLayout()),
|
||||
_settingsConflict(new QLabel())
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
API _api = API::SCENE_SWITCHER;
|
||||
MessageType _type = MessageType::REQUEST;
|
||||
StringVariable _message = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
std::weak_ptr<Connection> _connection;
|
||||
std::weak_ptr<WSConnection> _connection;
|
||||
|
||||
private:
|
||||
void SendRequest(const std::string &msg);
|
||||
@@ -84,7 +84,7 @@ private:
|
||||
QComboBox *_apiType;
|
||||
QComboBox *_messageType;
|
||||
VariableTextEdit *_message;
|
||||
ConnectionSelection *_connection;
|
||||
WSConnectionSelection *_connection;
|
||||
QHBoxLayout *_editLayout;
|
||||
QLabel *_settingsConflict;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "macro-action-window.hpp"
|
||||
#include "help-icon.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "platform-funcs.hpp"
|
||||
#include "selection-helpers.hpp"
|
||||
@@ -163,7 +164,8 @@ MacroActionWindowEdit::MacroActionWindowEdit(
|
||||
: QWidget(parent),
|
||||
_actions(new QComboBox()),
|
||||
_windows(new QComboBox()),
|
||||
_regex(new RegexConfigWidget(this))
|
||||
_regex(new RegexConfigWidget(this)),
|
||||
_infoLayout(new QHBoxLayout())
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
|
||||
@@ -171,6 +173,15 @@ MacroActionWindowEdit::MacroActionWindowEdit(
|
||||
_windows->setMaxVisibleItems(20);
|
||||
PopulateWindowSelection(_windows);
|
||||
|
||||
auto focusLimitation = new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.action.window.type.setFocusWindow.limitation"));
|
||||
_infoLayout->addWidget(focusLimitation);
|
||||
|
||||
auto focusLimitationDetails = new HelpIcon(obs_module_text(
|
||||
"AdvSceneSwitcher.action.window.type.setFocusWindow.limitation.details"));
|
||||
_infoLayout->addWidget(focusLimitationDetails);
|
||||
_infoLayout->addStretch();
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_windows, SIGNAL(currentTextChanged(const QString &)),
|
||||
@@ -179,12 +190,15 @@ MacroActionWindowEdit::MacroActionWindowEdit(
|
||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||
SLOT(RegexChanged(const RegexConfig &)));
|
||||
|
||||
auto layout = new QHBoxLayout;
|
||||
auto entryLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.window.entry"),
|
||||
layout,
|
||||
entryLayout,
|
||||
{{"{{actions}}", _actions},
|
||||
{"{{windows}}", _windows},
|
||||
{"{{regex}}", _regex}});
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(entryLayout);
|
||||
layout->addLayout(_infoLayout);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -200,8 +214,7 @@ void MacroActionWindowEdit::UpdateEntryData()
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_windows->setCurrentText(QString::fromStdString(_entryData->_window));
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionWindowEdit::WindowChanged(const QString &text)
|
||||
@@ -228,6 +241,15 @@ void MacroActionWindowEdit::RegexChanged(const RegexConfig ®ex)
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionWindowEdit::SetWidgetVisibility()
|
||||
{
|
||||
SetLayoutVisible(_infoLayout,
|
||||
_entryData->_action ==
|
||||
MacroActionWindow::Action::SET_FOCUS_WINDOW);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionWindowEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
@@ -236,6 +258,7 @@ void MacroActionWindowEdit::ActionChanged(int value)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionWindow::Action>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -59,9 +59,12 @@ signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QComboBox *_actions;
|
||||
QComboBox *_windows;
|
||||
RegexConfigWidget *_regex;
|
||||
QHBoxLayout *_infoLayout;
|
||||
|
||||
std::shared_ptr<MacroActionWindow> _entryData;
|
||||
bool _loading = true;
|
||||
|
||||
@@ -61,13 +61,49 @@ MacroConditionAudio::~MacroConditionAudio()
|
||||
obs_volmeter_destroy(_volmeter);
|
||||
}
|
||||
|
||||
float MacroConditionAudio::GetVolumePeak()
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
using namespace std::chrono;
|
||||
static constexpr std::chrono::milliseconds timeout = 250ms;
|
||||
|
||||
// OBS might rarely not update _peak quickly enough when very low
|
||||
// intervals are configured on the General tab.
|
||||
// In that case _peak might be set to negative infinity still, which
|
||||
// will result in unexpected behavior, so we use the previously valid
|
||||
// peak value instead.
|
||||
//
|
||||
// If no volume update was received within a timeout window, however, it
|
||||
// is assumed, that the source no longer produces any audio output and
|
||||
// thus a peak volume value of negative infinity is used.
|
||||
|
||||
float peak;
|
||||
|
||||
std::lock_guard<std::mutex> lock(_peakMutex);
|
||||
auto msPassedSinceLastUpdate = duration_cast<milliseconds>(
|
||||
high_resolution_clock::now() - _lastPeakUpdate);
|
||||
if (_lastPeakUpdate.time_since_epoch().count() != 0 &&
|
||||
msPassedSinceLastUpdate > timeout) {
|
||||
peak = -std::numeric_limits<float>::infinity();
|
||||
} else {
|
||||
peak = _peakUpdated ? _peak : _previousPeak;
|
||||
}
|
||||
|
||||
_previousPeak = peak;
|
||||
_peak = -std::numeric_limits<float>::infinity();
|
||||
_peakUpdated = false;
|
||||
|
||||
return peak;
|
||||
}
|
||||
|
||||
bool MacroConditionAudio::CheckOutputCondition()
|
||||
{
|
||||
bool ret = false;
|
||||
OBSSourceAutoRelease source =
|
||||
obs_weak_source_get_source(_audioSource.GetSource());
|
||||
|
||||
double curVolume = _useDb ? _peak : DecibelToPercent(_peak) * 100;
|
||||
float peak = GetVolumePeak();
|
||||
double curVolume = _useDb ? peak : DecibelToPercent(peak) * 100;
|
||||
|
||||
switch (_outputCondition) {
|
||||
case OutputCondition::ABOVE:
|
||||
@@ -92,7 +128,6 @@ bool MacroConditionAudio::CheckOutputCondition()
|
||||
SetTempVarValue("output_volume", std::to_string(curVolume));
|
||||
|
||||
// Reset for next check
|
||||
_peak = -std::numeric_limits<float>::infinity();
|
||||
if (_audioSource.GetType() == SourceSelection::Type::VARIABLE) {
|
||||
ResetVolmeter();
|
||||
}
|
||||
@@ -329,11 +364,14 @@ void MacroConditionAudio::SetVolumeLevel(void *data, const float *,
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(c->_peakMutex);
|
||||
for (int i = 0; i < MAX_AUDIO_CHANNELS; i++) {
|
||||
if (peak[i] > c->_peak) {
|
||||
c->_peak = peak[i];
|
||||
}
|
||||
}
|
||||
c->_peakUpdated = true;
|
||||
c->_lastPeakUpdate = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void MacroConditionAudio::ResetVolmeter()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user