Compare commits

...

15 Commits

Author SHA1 Message Date
WarmUpTill
f8212da80f debug 2025-11-06 20:09:00 +01:00
WarmUpTill
862bc420ad force 2025-11-06 20:09:00 +01:00
WarmUpTill
f832d6c52e debug 2025-11-06 20:09:00 +01:00
WarmUpTill
790d0095f3 use old cache 2025-11-06 20:09:00 +01:00
WarmUpTill
81409ba22d Revert "Update based on obs-plugintemplate to enable switch to OBS 31.1.1"
This reverts commit 1494b1db6c.
2025-11-06 20:09:00 +01:00
WarmUpTill
e687cf139a Revert "buildspec: Update OBS Studio dependency to 31.1.1"
This reverts commit 5f2237ac2a.
2025-11-06 20:09:00 +01:00
WarmUpTill
9c109742fb Add option to change action state based on label and action type
Some checks failed
debian-build / build (push) Has been cancelled
Check locale / ubuntu64 (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
2025-11-05 20:49:24 +01:00
WarmUpTill
b8b0682aaf Add support for else actions to MacroSegmentSelection 2025-11-05 20:49:24 +01:00
WarmUpTill
f93175db77 Sort scenes alphabetically
Prior to implementing canvas suppor they were in the order they are in
the scenes dock.
After switching from obs_frontend_get_scene_names() to
obs_canvas_enum_scenes() this seems to not always be the case.
2025-11-05 20:49:24 +01:00
WarmUpTill
8f92ba3ffa Increase slide index selection maximum to 9999 2025-11-05 20:49:24 +01:00
WarmUpTill
0d56de11d1 Refactor to support loading macro properties on import 2025-11-05 20:49:24 +01:00
WarmUpTill
e1020a1909 Fix poad load steps being executed too frequently
Some checks failed
debian-build / build (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
2025-10-30 20:48:33 +01:00
WarmUpTill
8b0bd4193b Fix temp var save / loading not working 2025-10-30 20:48:33 +01:00
WarmUpTill
d55bb6bc86 Fall back to obs_frontend_get_current_scene()
Some checks failed
debian-build / build (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
If there wasn't any scene change yet GetCurrentScene() would always
return nullptr and break various scene checks.
For example, this could happen when startup up a fresh OBS install for
the first time.
2025-10-29 12:26:44 +01:00
WarmUpTill
0583331bfd Fix scene selection not working without secondary canvases 2025-10-29 12:26:44 +01:00
33 changed files with 574 additions and 237 deletions

View File

@@ -6,7 +6,7 @@ on:
description: "Project name detected by parsing build spec file" description: "Project name detected by parsing build spec file"
value: ${{ jobs.check-event.outputs.pluginName }} value: ${{ jobs.check-event.outputs.pluginName }}
env: env:
DEP_DIR: .deps/advss-build-dependencies-3 DEP_DIR: .deps/advss-build-dependencies-2
jobs: jobs:
check-event: check-event:
name: Check GitHub Event Data 🔎 name: Check GitHub Event Data 🔎

View File

@@ -1,33 +1,33 @@
{ {
"dependencies": { "dependencies": {
"obs-studio": { "obs-studio": {
"version": "31.1.1", "version": "30.1.2",
"baseUrl": "https://github.com/obsproject/obs-studio/archive/refs/tags", "baseUrl": "https://github.com/obsproject/obs-studio/archive/refs/tags",
"label": "OBS sources", "label": "OBS sources",
"hashes": { "hashes": {
"macos": "39751f067bacc13d44b116c5138491b5f1391f91516d3d590d874edd21292291", "macos": "490bae1c392b3b344b0270afd8cb887da4bc50bd92c0c426e96713c1ccb9701a",
"windows-x64": "2c8427c10b55ac6d68008df2e9a3e82f4647aaad18f105e30d4713c2de678ccf" "windows-x64": "c2dd03fa7fd01fad5beafce8f7156da11f9ed9a588373fd40b44a06f4c03b867"
} }
}, },
"prebuilt": { "prebuilt": {
"version": "2025-07-11", "version": "2024-03-19",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download", "baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-Built obs-deps", "label": "Pre-Built obs-deps",
"hashes": { "hashes": {
"macos": "495687e63383d1a287684b6e2e9bfe246bb8f156fe265926afb1a325af1edd2a", "macos": "2e9bfb55a5e0e4c1086fa1fda4cf268debfead473089df2aaea80e1c7a3ca7ff",
"windows-x64": "c8c642c1070dc31ce9a0f1e4cef5bb992f4bff4882255788b5da12129e85caa7" "windows-x64": "6e86068371526a967e805f6f9903f9407adb683c21820db5f07da8f30d11e998"
} }
}, },
"qt6": { "qt6": {
"version": "2025-07-11", "version": "2024-03-19",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download", "baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-Built Qt6", "label": "Pre-Built Qt6",
"hashes": { "hashes": {
"macos": "d3f5f04b6ea486e032530bdf0187cbda9a54e0a49621a4c8ba984c5023998867", "macos": "694f1e639c017e3b1f456f735330dc5afae287cbea85757101af1368de3142c8",
"windows-x64": "0e76bf0555dd5382838850b748d3dcfab44a1e1058441309ab54e1a65b156d0a" "windows-x64": "72d1df34a0ef7413a681d5fcc88cae81da60adc03dcd23ef17862ab170bcc0dd"
}, },
"debugSymbols": { "debugSymbols": {
"windows-x64": "11b7be92cf66a273299b8f3515c07a5cfb61614b59a4e67f7fc5ecba5e2bdf21" "windows-x64": "fbddd1f659c360f2291911ac5709b67b6f8182e6bca519d24712e4f6fd3cc865"
} }
} }
}, },

View File

@@ -65,16 +65,17 @@ function(_setup_obs_studio)
if(OS_WINDOWS) if(OS_WINDOWS)
set(_cmake_generator "${CMAKE_GENERATOR}") set(_cmake_generator "${CMAKE_GENERATOR}")
set(_cmake_arch set(_cmake_arch "-A ${arch}")
"-A ${arch},version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
set(_cmake_extra set(_cmake_extra
"-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION} -DCMAKE_ENABLE_SCRIPTING=OFF" "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION} -DCMAKE_ENABLE_SCRIPTING=OFF"
) )
set(_cmake_version "2.0.0")
elseif(OS_MACOS) elseif(OS_MACOS)
set(_cmake_generator "Xcode") set(_cmake_generator "Xcode")
set(_cmake_arch "-DCMAKE_OSX_ARCHITECTURES:STRING='arm64;x86_64'") set(_cmake_arch "-DCMAKE_OSX_ARCHITECTURES:STRING='arm64;x86_64'")
set(_cmake_extra set(_cmake_extra
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
set(_cmake_version "3.0.0")
endif() endif()
message(STATUS "Configure ${label} (${arch})") message(STATUS "Configure ${label} (${arch})")
@@ -82,42 +83,32 @@ function(_setup_obs_studio)
COMMAND COMMAND
"${CMAKE_COMMAND}" -S "${dependencies_dir}/${_obs_destination}" -B "${CMAKE_COMMAND}" -S "${dependencies_dir}/${_obs_destination}" -B
"${dependencies_dir}/${_obs_destination}/build_${arch}" -G "${dependencies_dir}/${_obs_destination}/build_${arch}" -G
${_cmake_generator} "${_cmake_arch}" -DOBS_CMAKE_VERSION:STRING=3.0.0 ${_cmake_generator} "${_cmake_arch}"
-DENABLE_PLUGINS:BOOL=OFF -DENABLE_FRONTEND:BOOL=OFF -DOBS_CMAKE_VERSION:STRING=${_cmake_version} -DENABLE_PLUGINS:BOOL=OFF
-DOBS_VERSION_OVERRIDE:STRING=${_obs_version} -DENABLE_UI:BOOL=OFF -DOBS_VERSION_OVERRIDE:STRING=${_obs_version}
"-DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATH}'" ${_is_fresh} ${_cmake_extra} "-DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATH}'" ${_is_fresh} ${_cmake_extra}
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
OUTPUT_QUIET) OUTPUT_QUIET)
message(STATUS "Configure ${label} (${arch}) - done") message(STATUS "Configure ${label} (${arch}) - done")
message(STATUS "Build ${label} (Debug - ${arch})") message(STATUS "Build ${label} (${arch})")
execute_process( execute_process(
COMMAND "${CMAKE_COMMAND}" --build build_${arch} --target obs-frontend-api COMMAND "${CMAKE_COMMAND}" --build build_${arch} --target obs-frontend-api
--config Debug --parallel --config Debug --parallel
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}" WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
OUTPUT_QUIET) OUTPUT_QUIET)
message(STATUS "Build ${label} (Debug - ${arch}) - done") message(STATUS "Build ${label} (${arch}) - done")
message(STATUS "Build ${label} (Release - ${arch})")
execute_process(
COMMAND "${CMAKE_COMMAND}" --build build_${arch} --target obs-frontend-api
--config Release --parallel
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
OUTPUT_QUIET)
message(STATUS "Build ${label} (Reelase - ${arch}) - done")
message(STATUS "Install ${label} (${arch})") message(STATUS "Install ${label} (${arch})")
if(OS_WINDOWS)
set(_cmake_extra "--component obs_libraries")
else()
set(_cmake_extra "")
endif()
execute_process( execute_process(
COMMAND "${CMAKE_COMMAND}" --install build_${arch} --component Development COMMAND "${CMAKE_COMMAND}" --install build_${arch} --component Development
--config Debug --prefix "${dependencies_dir}" --config Debug --prefix "${dependencies_dir}" ${_cmake_extra}
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
OUTPUT_QUIET)
execute_process(
COMMAND "${CMAKE_COMMAND}" --install build_${arch} --component Development
--config Release --prefix "${dependencies_dir}"
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}" WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
OUTPUT_QUIET) OUTPUT_QUIET)

View File

@@ -4,7 +4,6 @@
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
if(WIN32 AND (NOT OpenSSL_FOUND)) if(WIN32 AND (NOT OpenSSL_FOUND))
set(_openssl_roots set(_openssl_roots
"$ENV{ProgramFiles}/OpenSSL-Win64" "$ENV{ProgramFiles}/OpenSSL" "$ENV{ProgramFiles}/OpenSSL-Win64" "$ENV{ProgramFiles}/OpenSSL"
"$ENV{ProgramW6432}/OpenSSL-Win64") "$ENV{ProgramW6432}/OpenSSL-Win64")
@@ -47,20 +46,33 @@ if(WIN32 AND (NOT OpenSSL_FOUND))
AND EXISTS "${_root}/${_suffix}/libcrypto.lib") AND EXISTS "${_root}/${_suffix}/libcrypto.lib")
set(OPENSSL_ROOT_DIR set(OPENSSL_ROOT_DIR
"${_root}" "${_root}"
CACHE PATH "Path to OpenSSL root") CACHE PATH "Path to OpenSSL root" FORCE)
set(OPENSSL_CRYPTO_LIBRARY set(OPENSSL_CRYPTO_LIBRARY
"${_root}/${_suffix}/libcrypto.lib" "${_root}/${_suffix}/libcrypto.lib"
CACHE FILEPATH "OpenSSL crypto lib") CACHE FILEPATH "OpenSSL crypto lib" FORCE)
set(OPENSSL_SSL_LIBRARY set(OPENSSL_SSL_LIBRARY
"${_root}/${_suffix}/libssl.lib" "${_root}/${_suffix}/libssl.lib"
CACHE FILEPATH "OpenSSL ssl lib") CACHE FILEPATH "OpenSSL ssl lib" FORCE)
set(OPENSSL_INCLUDE_DIR set(OPENSSL_INCLUDE_DIR
"${_root}/include" "${_root}/include"
CACHE PATH "OpenSSL include dir") CACHE PATH "OpenSSL include dir" FORCE)
set(OpenSSL_FOUND set(OpenSSL_FOUND
TRUE TRUE
CACHE BOOL "Whether OpenSSL was found") CACHE BOOL "Whether OpenSSL was found" FORCE)
message(STATUS "Found OpenSSL at: ${_root}/${_suffix}") message(STATUS "Found OpenSSL at: ${_root}/${_suffix}")
# Recursively list all files under OPENSSL_ROOT_DIR
file(GLOB_RECURSE OPENSSL_FILES "${OPENSSL_ROOT_DIR}/*")
message(STATUS "Listing contents of OPENSSL_ROOT_DIR:")
foreach(file ${OPENSSL_FILES})
message(STATUS " ${file}")
endforeach()
get_cmake_property(_variableNames VARIABLES)
list(SORT _variableNames)
foreach(_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
return() return()
endif() endif()
endforeach() endforeach()

View File

@@ -984,12 +984,16 @@ AdvSceneSwitcher.action.macro.type.disableAction="Disable action"
AdvSceneSwitcher.action.macro.type.enableAction="Enable action" AdvSceneSwitcher.action.macro.type.enableAction="Enable action"
AdvSceneSwitcher.action.macro.type.toggleAction="Toggle action" AdvSceneSwitcher.action.macro.type.toggleAction="Toggle action"
AdvSceneSwitcher.action.macro.type.nestedMacro="Nested macro" AdvSceneSwitcher.action.macro.type.nestedMacro="Nested macro"
AdvSceneSwitcher.action.macro.actionSelectionType.index="at index"
AdvSceneSwitcher.action.macro.actionSelectionType.label="with label"
AdvSceneSwitcher.action.macro.actionSelectionType.id="of action type"
AdvSceneSwitcher.action.macro.type.nestedMacro.conditionHelp="This section allows you to define macro conditions.\n\nClick the plus button below to add a new condition." AdvSceneSwitcher.action.macro.type.nestedMacro.conditionHelp="This section allows you to define macro conditions.\n\nClick the plus button below to add a new condition."
AdvSceneSwitcher.action.macro.type.nestedMacro.actionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are met.\n\nClick the plus button below to add a new action." AdvSceneSwitcher.action.macro.type.nestedMacro.actionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are met.\n\nClick the plus button below to add a new action."
AdvSceneSwitcher.action.macro.type.nestedMacro.elseActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are *not* met.\n\nClick the plus button below to add a new action." AdvSceneSwitcher.action.macro.type.nestedMacro.elseActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are *not* met.\n\nClick the plus button below to add a new action."
AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}of{{macros}}" AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}of{{macros}}"
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}of{{conditionMacros}}" AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.layout.actionState="{{actions}}{{actionSelectionType}}{{actionIndex}}{{label}}{{regex}}{{actionTypes}}in{{actionSections}}section of{{macros}}"
AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
AdvSceneSwitcher.action.pluginState="Plugin state" AdvSceneSwitcher.action.pluginState="Plugin state"
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin" AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:" AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"

View File

@@ -861,9 +861,9 @@ AdvSceneSwitcher.action.macro.type.stop="Parar ações"
AdvSceneSwitcher.action.macro.type.disableAction="Desabilitar ação" AdvSceneSwitcher.action.macro.type.disableAction="Desabilitar ação"
AdvSceneSwitcher.action.macro.type.enableAction="Habilitar ação" AdvSceneSwitcher.action.macro.type.enableAction="Habilitar ação"
AdvSceneSwitcher.action.macro.type.toggleAction="Alternar ação" AdvSceneSwitcher.action.macro.type.toggleAction="Alternar ação"
AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}de{{macros}}" AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}de{{macros}}"
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}de{{conditionMacros}}" AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}de{{conditionMacros}}"
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
AdvSceneSwitcher.action.pluginState="Estado do plugin" AdvSceneSwitcher.action.pluginState="Estado do plugin"
AdvSceneSwitcher.action.pluginState.type.stop="Parar o plugin Advanced Scene Switcher" AdvSceneSwitcher.action.pluginState.type.stop="Parar o plugin Advanced Scene Switcher"
AdvSceneSwitcher.action.pluginState.type.noMatch="Alterar o comportamento em caso de não correspondência:" AdvSceneSwitcher.action.pluginState.type.noMatch="Alterar o comportamento em caso de não correspondência:"

View File

@@ -920,9 +920,9 @@ AdvSceneSwitcher.action.macro.type.stop="停止操作"
AdvSceneSwitcher.action.macro.type.disableAction="停用操作" AdvSceneSwitcher.action.macro.type.disableAction="停用操作"
AdvSceneSwitcher.action.macro.type.enableAction="启用操作" AdvSceneSwitcher.action.macro.type.enableAction="启用操作"
AdvSceneSwitcher.action.macro.type.toggleAction="切换操作开关" AdvSceneSwitcher.action.macro.type.toggleAction="切换操作开关"
AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}{{macros}}" AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}{{macros}}"
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}{{conditionMacros}}" AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}{{conditionMacros}}"
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
AdvSceneSwitcher.action.pluginState="插件状态" AdvSceneSwitcher.action.pluginState="插件状态"
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件" AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:" AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:"

View File

@@ -421,7 +421,7 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
static void ResetMacros() static void ResetMacros()
{ {
for (auto &m : GetMacros()) { for (auto &m : GetTopLevelMacros()) {
ResetMacroRunCount(m.get()); ResetMacroRunCount(m.get());
ResetMacroConditionTimers(m.get()); ResetMacroConditionTimers(m.get());
} }

View File

@@ -459,7 +459,7 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
LoadHotkeys(obj); LoadHotkeys(obj);
LoadUISettings(obj); LoadUISettings(obj);
RunPostLoadSteps(); RunAndClearPostLoadSteps();
// Reset on startup and scene collection change // Reset on startup and scene collection change
ResetLastOpenedTab(); ResetLastOpenedTab();

View File

@@ -117,7 +117,7 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
*_entryData = MacroActionFactory::Create(id, macro); *_entryData = MacroActionFactory::Create(id, macro);
(*_entryData)->SetIndex(idx); (*_entryData)->SetIndex(idx);
(*_entryData)->PostLoad(); (*_entryData)->PostLoad();
RunPostLoadSteps(); RunAndClearPostLoadSteps();
} }
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData); auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),

View File

@@ -2,6 +2,7 @@
#include "help-icon.hpp" #include "help-icon.hpp"
#include "layout-helpers.hpp" #include "layout-helpers.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "macro-action-factory.hpp"
namespace advss { namespace advss {
@@ -12,6 +13,74 @@ bool MacroActionMacro::_registered = MacroActionFactory::Register(
{MacroActionMacro::Create, MacroActionMacroEdit::Create, {MacroActionMacro::Create, MacroActionMacroEdit::Create,
"AdvSceneSwitcher.action.macro"}); "AdvSceneSwitcher.action.macro"});
void MacroActionMacro::AdjustActionState(Macro *macro) const
{
const auto &macroActions = _useElseSection ? macro->ElseActions()
: macro->Actions();
std::vector<std::shared_ptr<MacroAction>> actionsToModify;
switch (_actionSelectionType) {
case SelectionType::INDEX: {
const bool isValidAction =
(_useElseSection &&
IsValidElseActionIndex(macro, _actionIndex - 1)) ||
(!_useElseSection &&
IsValidActionIndex(macro, _actionIndex - 1));
if (isValidAction) {
actionsToModify.emplace_back(
macroActions.at(_actionIndex - 1));
}
break;
}
case SelectionType::LABEL:
for (const auto &action : macroActions) {
if (!action->GetUseCustomLabel()) {
continue;
}
const auto label = action->GetCustomLabel();
if (_regex.Enabled()) {
if (_regex.Matches(label, _label)) {
actionsToModify.emplace_back(action);
}
continue;
}
if (label == std::string(_label)) {
actionsToModify.emplace_back(action);
}
}
break;
case SelectionType::ID:
for (const auto &action : macroActions) {
if (action->GetId() == _actionId) {
actionsToModify.emplace_back(action);
}
}
break;
default:
break;
}
for (const auto &action : actionsToModify) {
switch (_action) {
case Action::DISABLE_ACTION:
action->SetEnabled(false);
break;
case Action::ENABLE_ACTION:
action->SetEnabled(true);
break;
case Action::TOGGLE_ACTION:
action->SetEnabled(!action->Enabled());
break;
default:
break;
}
}
}
bool MacroActionMacro::PerformAction() bool MacroActionMacro::PerformAction()
{ {
if (_action == Action::NESTED_MACRO) { if (_action == Action::NESTED_MACRO) {
@@ -44,23 +113,9 @@ bool MacroActionMacro::PerformAction()
macro->Stop(); macro->Stop();
break; break;
case Action::DISABLE_ACTION: case Action::DISABLE_ACTION:
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
false)) {
macro->Actions().at(_actionIndex - 1)->SetEnabled(false);
}
break;
case Action::ENABLE_ACTION: case Action::ENABLE_ACTION:
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
false)) {
macro->Actions().at(_actionIndex - 1)->SetEnabled(true);
}
break;
case Action::TOGGLE_ACTION: case Action::TOGGLE_ACTION:
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1, AdjustActionState(macro.get());
false)) {
auto action = macro->Actions().at(_actionIndex - 1);
action->SetEnabled(!action->Enabled());
}
break; break;
default: default:
break; break;
@@ -115,9 +170,14 @@ void MacroActionMacro::LogAction() const
bool MacroActionMacro::Save(obs_data_t *obj) const bool MacroActionMacro::Save(obs_data_t *obj) const
{ {
MacroAction::Save(obj); MacroAction::Save(obj);
_macro.Save(obj);
_actionIndex.Save(obj, "actionIndex");
obs_data_set_int(obj, "action", static_cast<int>(_action)); obs_data_set_int(obj, "action", static_cast<int>(_action));
_macro.Save(obj);
obs_data_set_int(obj, "actionSelectionType",
static_cast<int>(_actionSelectionType));
_actionIndex.Save(obj, "actionIndex");
_label.Save(obj, "label");
obs_data_set_string(obj, "actionId", _actionId.c_str());
_regex.Save(obj);
_runOptions.Save(obj); _runOptions.Save(obj);
OBSDataAutoRelease nestedMacroData = obs_data_create(); OBSDataAutoRelease nestedMacroData = obs_data_create();
_nestedMacro->Save(nestedMacroData); _nestedMacro->Save(nestedMacroData);
@@ -129,10 +189,15 @@ bool MacroActionMacro::Save(obs_data_t *obj) const
bool MacroActionMacro::Load(obs_data_t *obj) bool MacroActionMacro::Load(obs_data_t *obj)
{ {
MacroAction::Load(obj); MacroAction::Load(obj);
_macro.Load(obj);
_actionIndex.Load(obj, "actionIndex");
_action = static_cast<MacroActionMacro::Action>( _action = static_cast<MacroActionMacro::Action>(
obs_data_get_int(obj, "action")); obs_data_get_int(obj, "action"));
_macro.Load(obj);
_actionSelectionType = static_cast<SelectionType>(
obs_data_get_int(obj, "actionSelectionType"));
_actionIndex.Load(obj, "actionIndex");
_label.Load(obj, "label");
_actionId = obs_data_get_string(obj, "actionId");
_regex.Load(obj);
_runOptions.Load(obj); _runOptions.Load(obj);
if (obs_data_has_user_value(obj, "nestedMacro")) { if (obs_data_has_user_value(obj, "nestedMacro")) {
@@ -183,6 +248,7 @@ std::shared_ptr<MacroAction> MacroActionMacro::Copy() const
void MacroActionMacro::ResolveVariablesToFixedValues() void MacroActionMacro::ResolveVariablesToFixedValues()
{ {
_actionIndex.ResolveVariables(); _actionIndex.ResolveVariables();
_label.ResolveVariables();
} }
static void runActionsHelper(Macro *macro, bool runElseActions, bool setInputs, static void runActionsHelper(Macro *macro, bool runElseActions, bool setInputs,
@@ -266,7 +332,7 @@ static void populateConditionBehaviorSelection(QComboBox *list)
"AdvSceneSwitcher.action.macro.type.run.conditions.false")); "AdvSceneSwitcher.action.macro.type.run.conditions.false"));
} }
static void populateActionTypeSelection(QComboBox *list) static void populateActionSectionSelection(QComboBox *list)
{ {
list->addItem(obs_module_text( list->addItem(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.actionType.regular")); "AdvSceneSwitcher.action.macro.type.run.actionType.regular"));
@@ -274,19 +340,47 @@ static void populateActionTypeSelection(QComboBox *list)
"AdvSceneSwitcher.action.macro.type.run.actionType.else")); "AdvSceneSwitcher.action.macro.type.run.actionType.else"));
} }
static void populateActionTypes(QComboBox *list)
{
for (const auto &[id, info] : MacroActionFactory::GetActionTypes()) {
list->addItem(obs_module_text(info._name.c_str()),
QString::fromStdString(id));
}
}
static void populateActionSelectionTypes(QComboBox *list)
{
list->addItem(
obs_module_text(
"AdvSceneSwitcher.action.macro.actionSelectionType.index"),
static_cast<int>(MacroActionMacro::SelectionType::INDEX));
list->addItem(
obs_module_text(
"AdvSceneSwitcher.action.macro.actionSelectionType.label"),
static_cast<int>(MacroActionMacro::SelectionType::LABEL));
list->addItem(
obs_module_text(
"AdvSceneSwitcher.action.macro.actionSelectionType.id"),
static_cast<int>(MacroActionMacro::SelectionType::ID));
}
MacroActionMacroEdit::MacroActionMacroEdit( MacroActionMacroEdit::MacroActionMacroEdit(
QWidget *parent, std::shared_ptr<MacroActionMacro> entryData) QWidget *parent, std::shared_ptr<MacroActionMacro> entryData)
: ResizableWidget(parent), : ResizableWidget(parent),
_actions(new QComboBox()),
_macros(new MacroSelection(parent)), _macros(new MacroSelection(parent)),
_actionSelectionType(new QComboBox(this)),
_actionIndex(new MacroSegmentSelection( _actionIndex(new MacroSegmentSelection(
this, MacroSegmentSelection::Type::ACTION)), this, MacroSegmentSelection::Type::ACTION)),
_actions(new QComboBox()), _label(new VariableLineEdit(this)),
_actionTypes(new FilterComboBox(this)),
_regex(new RegexConfigWidget(this)),
_conditionMacros(new MacroSelection(parent)), _conditionMacros(new MacroSelection(parent)),
_conditionBehaviors(new QComboBox()), _conditionBehaviors(new QComboBox()),
_reevaluateConditionState(new QCheckBox( _reevaluateConditionState(new QCheckBox(
obs_module_text("AdvSceneSwitcher.action.macro.type.run." obs_module_text("AdvSceneSwitcher.action.macro.type.run."
"updateConditionMatchState"))), "updateConditionMatchState"))),
_actionTypes(new QComboBox()), _actionSections(new QComboBox(this)),
_skipWhenPaused(new QCheckBox(obs_module_text( _skipWhenPaused(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))), "AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))),
_setInputs(new QCheckBox(obs_module_text( _setInputs(new QCheckBox(obs_module_text(
@@ -305,7 +399,9 @@ MacroActionMacroEdit::MacroActionMacroEdit(
{ {
populateActionSelection(_actions); populateActionSelection(_actions);
populateConditionBehaviorSelection(_conditionBehaviors); populateConditionBehaviorSelection(_conditionBehaviors);
populateActionTypeSelection(_actionTypes); populateActionSectionSelection(_actionSections);
populateActionSelectionTypes(_actionSelectionType);
populateActionTypes(_actionTypes);
_conditionMacros->HideSelectedMacro(); _conditionMacros->HideSelectedMacro();
@@ -313,16 +409,25 @@ MacroActionMacroEdit::MacroActionMacroEdit(
this, SLOT(MacroChanged(const QString &))); this, SLOT(MacroChanged(const QString &)));
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int))); SLOT(ActionChanged(int)));
QWidget::connect(_actionSelectionType, SIGNAL(currentIndexChanged(int)),
this, SLOT(ActionSelectionTypeChanged(int)));
QWidget::connect(_actionIndex, QWidget::connect(_actionIndex,
SIGNAL(SelectionChanged(const IntVariable &)), this, SIGNAL(SelectionChanged(const IntVariable &)), this,
SLOT(ActionIndexChanged(const IntVariable &))); SLOT(ActionIndexChanged(const IntVariable &)));
QWidget::connect(_label, SIGNAL(editingFinished()), this,
SLOT(LabelChanged()));
QWidget::connect(_actionTypes, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionTypeChanged(int)));
QWidget::connect(_regex,
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
SLOT(RegexChanged(const RegexConfig &)));
QWidget::connect(_conditionMacros, QWidget::connect(_conditionMacros,
SIGNAL(currentTextChanged(const QString &)), this, SIGNAL(currentTextChanged(const QString &)), this,
SLOT(ConditionMacroChanged(const QString &))); SLOT(ConditionMacroChanged(const QString &)));
QWidget::connect(_conditionBehaviors, SIGNAL(currentIndexChanged(int)), QWidget::connect(_conditionBehaviors, SIGNAL(currentIndexChanged(int)),
this, SLOT(ConditionBehaviorChanged(int))); this, SLOT(ConditionBehaviorChanged(int)));
QWidget::connect(_actionTypes, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actionSections, SIGNAL(currentIndexChanged(int)),
SLOT(ActionTypeChanged(int))); this, SLOT(ActionSectionChanged(int)));
QWidget::connect(_skipWhenPaused, SIGNAL(stateChanged(int)), this, QWidget::connect(_skipWhenPaused, SIGNAL(stateChanged(int)), this,
SLOT(SkipWhenPausedChanged(int))); SLOT(SkipWhenPausedChanged(int)));
QWidget::connect(_setInputs, SIGNAL(stateChanged(int)), this, QWidget::connect(_setInputs, SIGNAL(stateChanged(int)), this,
@@ -375,17 +480,24 @@ void MacroActionMacroEdit::UpdateEntryData()
if (!_entryData) { if (!_entryData) {
return; return;
} }
_actions->setCurrentIndex( _actions->setCurrentIndex(
_actions->findData(static_cast<int>(_entryData->_action))); _actions->findData(static_cast<int>(_entryData->_action)));
_actionSelectionType->setCurrentIndex(_actionSelectionType->findData(
static_cast<int>(_entryData->_actionSelectionType)));
_actionIndex->SetValue(_entryData->_actionIndex); _actionIndex->SetValue(_entryData->_actionIndex);
_actionIndex->SetMacro(_entryData->_macro.GetMacro()); _actionIndex->SetMacro(_entryData->_macro.GetMacro());
_label->setText(_entryData->_label);
_actionTypes->setCurrentIndex(_actionTypes->findData(
QString::fromStdString(_entryData->_actionId)));
_regex->SetRegexConfig(_entryData->_regex);
_macros->SetCurrentMacro(_entryData->_macro); _macros->SetCurrentMacro(_entryData->_macro);
_conditionMacros->SetCurrentMacro(_entryData->_runOptions.macro); _conditionMacros->SetCurrentMacro(_entryData->_runOptions.macro);
_conditionBehaviors->setCurrentIndex( _conditionBehaviors->setCurrentIndex(
static_cast<int>(_entryData->_runOptions.logic)); static_cast<int>(_entryData->_runOptions.logic));
_reevaluateConditionState->setChecked( _reevaluateConditionState->setChecked(
_entryData->_runOptions.reevaluateConditionState); _entryData->_runOptions.reevaluateConditionState);
_actionTypes->setCurrentIndex( _actionSections->setCurrentIndex(
_entryData->_runOptions.runElseActions ? 1 : 0); _entryData->_runOptions.runElseActions ? 1 : 0);
_skipWhenPaused->setChecked(_entryData->_runOptions.skipWhenPaused); _skipWhenPaused->setChecked(_entryData->_runOptions.skipWhenPaused);
_setInputs->setChecked(_entryData->_runOptions.setInputs); _setInputs->setChecked(_entryData->_runOptions.setInputs);
@@ -424,12 +536,40 @@ void MacroActionMacroEdit::ActionChanged(int idx)
SetWidgetVisibility(); SetWidgetVisibility();
} }
void MacroActionMacroEdit::ActionSelectionTypeChanged(int idx)
{
GUARD_LOADING_AND_LOCK();
_entryData->_actionSelectionType =
static_cast<MacroActionMacro::SelectionType>(
_actionSelectionType->itemData(idx).toInt());
SetWidgetVisibility();
}
void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value) void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value)
{ {
GUARD_LOADING_AND_LOCK(); GUARD_LOADING_AND_LOCK();
_entryData->_actionIndex = value; _entryData->_actionIndex = value;
} }
void MacroActionMacroEdit::LabelChanged()
{
GUARD_LOADING_AND_LOCK();
_entryData->_label = _label->text().toStdString();
}
void MacroActionMacroEdit::ActionTypeChanged(int idx)
{
GUARD_LOADING_AND_LOCK();
_entryData->_actionId =
_actionTypes->itemData(idx).toString().toStdString();
}
void MacroActionMacroEdit::RegexChanged(const RegexConfig &regex)
{
GUARD_LOADING_AND_LOCK();
_entryData->_regex = regex;
}
void MacroActionMacroEdit::ConditionMacroChanged(const QString &text) void MacroActionMacroEdit::ConditionMacroChanged(const QString &text)
{ {
GUARD_LOADING_AND_LOCK(); GUARD_LOADING_AND_LOCK();
@@ -451,10 +591,13 @@ void MacroActionMacroEdit::ReevaluateConditionStateChanged(int value)
SetWidgetVisibility(); SetWidgetVisibility();
} }
void MacroActionMacroEdit::ActionTypeChanged(int value) void MacroActionMacroEdit::ActionSectionChanged(int useElse)
{ {
GUARD_LOADING_AND_LOCK(); GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.runElseActions = value; _entryData->_runOptions.runElseActions = useElse;
_entryData->_useElseSection = useElse;
_actionIndex->SetType(useElse ? MacroSegmentSelection::Type::ELSE_ACTION
: MacroSegmentSelection::Type::ACTION);
} }
void MacroActionMacroEdit::SkipWhenPausedChanged(int value) void MacroActionMacroEdit::SkipWhenPausedChanged(int value)
@@ -483,7 +626,11 @@ void MacroActionMacroEdit::SetWidgetVisibility()
_entryLayout->removeWidget(_actions); _entryLayout->removeWidget(_actions);
_entryLayout->removeWidget(_actionIndex); _entryLayout->removeWidget(_actionIndex);
_entryLayout->removeWidget(_macros); _entryLayout->removeWidget(_macros);
_entryLayout->removeWidget(_actionSections);
_entryLayout->removeWidget(_label);
_entryLayout->removeWidget(_regex);
_entryLayout->removeWidget(_actionTypes); _entryLayout->removeWidget(_actionTypes);
_entryLayout->removeWidget(_actionSelectionType);
_conditionLayout->removeWidget(_conditionBehaviors); _conditionLayout->removeWidget(_conditionBehaviors);
_conditionLayout->removeWidget(_conditionMacros); _conditionLayout->removeWidget(_conditionMacros);
@@ -494,19 +641,40 @@ void MacroActionMacroEdit::SetWidgetVisibility()
{"{{actions}}", _actions}, {"{{actions}}", _actions},
{"{{actionIndex}}", _actionIndex}, {"{{actionIndex}}", _actionIndex},
{"{{macros}}", _macros}, {"{{macros}}", _macros},
{"{{actionTypes}}", _actionTypes}, {"{{actionSections}}", _actionSections},
{"{{conditionBehaviors}}", _conditionBehaviors}, {"{{conditionBehaviors}}", _conditionBehaviors},
{"{{conditionMacros}}", _conditionMacros}, {"{{conditionMacros}}", _conditionMacros},
{"{{actionSelectionType}}", _actionSelectionType},
{"{{label}}", _label},
{"{{regex}}", _regex},
{"{{actionTypes}}", _actionTypes},
}; };
PlaceWidgets( const auto action = _entryData->_action;
obs_module_text( const char *layoutText = "";
_entryData->_action == switch (action) {
MacroActionMacro::Action::RUN_ACTIONS case MacroActionMacro::Action::PAUSE:
? "AdvSceneSwitcher.action.macro.entry.run" case MacroActionMacro::Action::UNPAUSE:
: "AdvSceneSwitcher.action.macro.entry.other"), case MacroActionMacro::Action::TOGGLE_PAUSE:
_entryLayout, placeholders); case MacroActionMacro::Action::RESET_COUNTER:
case MacroActionMacro::Action::STOP:
case MacroActionMacro::Action::NESTED_MACRO:
layoutText = "AdvSceneSwitcher.action.macro.layout.other";
break;
case MacroActionMacro::Action::RUN_ACTIONS:
layoutText = "AdvSceneSwitcher.action.macro.layout.run";
break;
case MacroActionMacro::Action::DISABLE_ACTION:
case MacroActionMacro::Action::ENABLE_ACTION:
case MacroActionMacro::Action::TOGGLE_ACTION:
layoutText = "AdvSceneSwitcher.action.macro.layout.actionState";
break;
default:
break;
}
PlaceWidgets(obs_module_text(layoutText), _entryLayout, placeholders);
if (_entryData->_runOptions.logic == if (_entryData->_runOptions.logic ==
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS) { MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS) {
@@ -515,56 +683,63 @@ void MacroActionMacroEdit::SetWidgetVisibility()
} else { } else {
PlaceWidgets( PlaceWidgets(
obs_module_text( obs_module_text(
"AdvSceneSwitcher.action.macro.entry.run.condition"), "AdvSceneSwitcher.action.macro.layout.run.condition"),
_conditionLayout, placeholders); _conditionLayout, placeholders);
} }
if (_entryData->_action == MacroActionMacro::Action::RUN_ACTIONS || if (action == MacroActionMacro::Action::RUN_ACTIONS ||
_entryData->_action == MacroActionMacro::Action::STOP) { action == MacroActionMacro::Action::STOP) {
_macros->HideSelectedMacro(); _macros->HideSelectedMacro();
} else { } else {
_macros->ShowAllMacros(); _macros->ShowAllMacros();
} }
const auto actionSelectionType = _entryData->_actionSelectionType;
const bool isModifyingActionState = const bool isModifyingActionState =
_entryData->_action == action == MacroActionMacro::Action::DISABLE_ACTION ||
MacroActionMacro::Action::DISABLE_ACTION || action == MacroActionMacro::Action::ENABLE_ACTION ||
_entryData->_action == action == MacroActionMacro::Action::TOGGLE_ACTION;
MacroActionMacro::Action::ENABLE_ACTION || _actionSelectionType->setVisible(isModifyingActionState);
_entryData->_action == MacroActionMacro::Action::TOGGLE_ACTION; _actionIndex->setVisible(
_actionIndex->setVisible(isModifyingActionState); isModifyingActionState &&
actionSelectionType == MacroActionMacro::SelectionType::INDEX);
_label->setVisible(isModifyingActionState &&
actionSelectionType ==
MacroActionMacro::SelectionType::LABEL);
_regex->setVisible(isModifyingActionState &&
actionSelectionType ==
MacroActionMacro::SelectionType::LABEL);
_actionTypes->setVisible(isModifyingActionState &&
actionSelectionType ==
MacroActionMacro::SelectionType::ID);
SetLayoutVisible(_conditionLayout, SetLayoutVisible(_conditionLayout,
_entryData->_action == action == MacroActionMacro::Action::RUN_ACTIONS);
MacroActionMacro::Action::RUN_ACTIONS);
const bool needsAdditionalConditionWidgets = const bool needsAdditionalConditionWidgets =
_entryData->_action == MacroActionMacro::Action::RUN_ACTIONS && action == MacroActionMacro::Action::RUN_ACTIONS &&
_entryData->_runOptions.logic != _entryData->_runOptions.logic !=
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS; MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS;
_conditionMacros->setVisible(needsAdditionalConditionWidgets); _conditionMacros->setVisible(needsAdditionalConditionWidgets);
SetLayoutVisible(_reevaluateConditionStateLayout, SetLayoutVisible(_reevaluateConditionStateLayout,
needsAdditionalConditionWidgets); needsAdditionalConditionWidgets);
SetLayoutVisible(_setInputsLayout, SetLayoutVisible(_setInputsLayout,
_entryData->_action == action == MacroActionMacro::Action::RUN_ACTIONS);
MacroActionMacro::Action::RUN_ACTIONS); _inputs->setVisible(action == MacroActionMacro::Action::RUN_ACTIONS &&
_inputs->setVisible(_entryData->_action ==
MacroActionMacro::Action::RUN_ACTIONS &&
_entryData->_runOptions.setInputs); _entryData->_runOptions.setInputs);
HighlightMacroSettingsButton( HighlightMacroSettingsButton(
_entryData->_action == MacroActionMacro::Action::RUN_ACTIONS && action == MacroActionMacro::Action::RUN_ACTIONS &&
_entryData->_runOptions.setInputs && _entryData->_runOptions.setInputs &&
!_inputs->HasInputsToSet()); !_inputs->HasInputsToSet());
_actionTypes->setVisible(_entryData->_action == _actionSections->setVisible(
MacroActionMacro::Action::RUN_ACTIONS); action == MacroActionMacro::Action::RUN_ACTIONS ||
_skipWhenPaused->setVisible(_entryData->_action == isModifyingActionState);
_skipWhenPaused->setVisible(action ==
MacroActionMacro::Action::RUN_ACTIONS); MacroActionMacro::Action::RUN_ACTIONS);
_nestedMacro->setVisible(_entryData->_action == _nestedMacro->setVisible(action ==
MacroActionMacro::Action::NESTED_MACRO); MacroActionMacro::Action::NESTED_MACRO);
_macros->setVisible(_entryData->_action != _macros->setVisible(action != MacroActionMacro::Action::NESTED_MACRO);
MacroActionMacro::Action::NESTED_MACRO); SetResizingEnabled(action == MacroActionMacro::Action::NESTED_MACRO);
SetResizingEnabled(_entryData->_action ==
MacroActionMacro::Action::NESTED_MACRO);
if (_nestedMacro->IsEmpty()) { if (_nestedMacro->IsEmpty()) {
_nestedMacro->ShowAllMacroSections(); _nestedMacro->ShowAllMacroSections();

View File

@@ -5,7 +5,9 @@
#include "macro-input.hpp" #include "macro-input.hpp"
#include "macro-selection.hpp" #include "macro-selection.hpp"
#include "macro-segment-selection.hpp" #include "macro-segment-selection.hpp"
#include "regex-config.hpp"
#include "resizable-widget.hpp" #include "resizable-widget.hpp"
#include "variable-line-edit.hpp"
#include <QCheckBox> #include <QCheckBox>
#include <QHBoxLayout> #include <QHBoxLayout>
@@ -55,14 +57,23 @@ public:
TOGGLE_PAUSE, TOGGLE_PAUSE,
NESTED_MACRO, NESTED_MACRO,
}; };
enum class SelectionType { INDEX, LABEL, ID };
Action _action = Action::NESTED_MACRO; Action _action = Action::NESTED_MACRO;
SelectionType _actionSelectionType = SelectionType::INDEX;
bool _useElseSection = false;
IntVariable _actionIndex = 1; IntVariable _actionIndex = 1;
StringVariable _label = "Custom label";
std::string _actionId;
RegexConfig _regex;
RunOptions _runOptions = {}; RunOptions _runOptions = {};
std::shared_ptr<Macro> _nestedMacro = std::make_shared<Macro>(); std::shared_ptr<Macro> _nestedMacro = std::make_shared<Macro>();
int _customWidgetHeight = 0; int _customWidgetHeight = 0;
private: private:
void RunActions(Macro *actionMacro) const; void RunActions(Macro *actionMacro) const;
void AdjustActionState(Macro *) const;
static bool _registered; static bool _registered;
static const std::string id; static const std::string id;
@@ -82,11 +93,15 @@ public:
private slots: private slots:
void MacroChanged(const QString &text); void MacroChanged(const QString &text);
void ActionChanged(int value); void ActionChanged(int value);
void ActionSelectionTypeChanged(int value);
void ActionIndexChanged(const IntVariable &value); void ActionIndexChanged(const IntVariable &value);
void LabelChanged();
void ActionTypeChanged(int value);
void RegexChanged(const RegexConfig &);
void ConditionMacroChanged(const QString &text); void ConditionMacroChanged(const QString &text);
void ConditionBehaviorChanged(int value); void ConditionBehaviorChanged(int value);
void ReevaluateConditionStateChanged(int value); void ReevaluateConditionStateChanged(int value);
void ActionTypeChanged(int value); void ActionSectionChanged(int value);
void SkipWhenPausedChanged(int value); void SkipWhenPausedChanged(int value);
void SetInputsChanged(int value); void SetInputsChanged(int value);
void InputsChanged(const StringList &); void InputsChanged(const StringList &);
@@ -98,13 +113,17 @@ private:
void SetWidgetVisibility(); void SetWidgetVisibility();
void SetupMacroInput(Macro *) const; void SetupMacroInput(Macro *) const;
MacroSelection *_macros;
MacroSegmentSelection *_actionIndex;
QComboBox *_actions; QComboBox *_actions;
MacroSelection *_macros;
QComboBox *_actionSelectionType;
MacroSegmentSelection *_actionIndex;
VariableLineEdit *_label;
FilterComboBox *_actionTypes;
RegexConfigWidget *_regex;
MacroSelection *_conditionMacros; MacroSelection *_conditionMacros;
QComboBox *_conditionBehaviors; QComboBox *_conditionBehaviors;
QCheckBox *_reevaluateConditionState; QCheckBox *_reevaluateConditionState;
QComboBox *_actionTypes; QComboBox *_actionSections;
QCheckBox *_skipWhenPaused; QCheckBox *_skipWhenPaused;
QCheckBox *_setInputs; QCheckBox *_setInputs;
MacroInputEdit *_inputs; MacroInputEdit *_inputs;

View File

@@ -239,7 +239,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
(*_entryData)->SetIndex(idx); (*_entryData)->SetIndex(idx);
(*_entryData)->SetLogicType(logic); (*_entryData)->SetLogicType(logic);
(*_entryData)->PostLoad(); (*_entryData)->PostLoad();
RunPostLoadSteps(); RunAndClearPostLoadSteps();
} }
auto widget = auto widget =
MacroConditionFactory::CreateWidget(id, this, *_entryData); MacroConditionFactory::CreateWidget(id, this, *_entryData);

View File

@@ -102,7 +102,7 @@ bool MacroConditionMacro::CheckActionStateCondition()
if (!macro) { if (!macro) {
return false; return false;
} }
if (!IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1, false)) { if (!IsValidActionIndex(macro.get(), _actionIndex - 1)) {
return false; return false;
} }
if (_type == Type::ACTION_DISABLED) { if (_type == Type::ACTION_DISABLED) {

View File

@@ -1080,7 +1080,7 @@ void MacroEdit::AddMacroAction(Macro *macro, int idx, const std::string &id,
macro->Actions().at(idx)->Load(data); macro->Actions().at(idx)->Load(data);
} }
macro->Actions().at(idx)->PostLoad(); macro->Actions().at(idx)->PostLoad();
RunPostLoadSteps(); RunAndClearPostLoadSteps();
macro->UpdateActionIndices(); macro->UpdateActionIndices();
ui->actionsList->Insert( ui->actionsList->Insert(
idx, idx,
@@ -1383,7 +1383,7 @@ void MacroEdit::AddMacroElseAction(Macro *macro, int idx, const std::string &id,
macro->ElseActions().at(idx)->Load(data); macro->ElseActions().at(idx)->Load(data);
} }
macro->ElseActions().at(idx)->PostLoad(); macro->ElseActions().at(idx)->PostLoad();
RunPostLoadSteps(); RunAndClearPostLoadSteps();
macro->UpdateElseActionIndices(); macro->UpdateElseActionIndices();
ui->elseActionsList->Insert( ui->elseActionsList->Insert(
idx, new MacroActionEdit( idx, new MacroActionEdit(
@@ -1583,7 +1583,7 @@ void MacroEdit::AddMacroCondition(Macro *macro, int idx, const std::string &id,
macro->Conditions().at(idx)->Load(data); macro->Conditions().at(idx)->Load(data);
} }
macro->Conditions().at(idx)->PostLoad(); macro->Conditions().at(idx)->PostLoad();
RunPostLoadSteps(); RunAndClearPostLoadSteps();
(*cond)->SetLogicType(logic); (*cond)->SetLogicType(logic);
macro->UpdateConditionIndices(); macro->UpdateConditionIndices();
ui->conditionsList->Insert( ui->conditionsList->Insert(

View File

@@ -1,5 +1,6 @@
#include "macro-helpers.hpp" #include "macro-helpers.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "macro-action-macro.hpp"
#include "plugin-state-helpers.hpp" #include "plugin-state-helpers.hpp"
namespace advss { namespace advss {
@@ -8,6 +9,60 @@ static std::atomic_bool abortMacroWait = {false};
static std::atomic_bool macroSceneSwitched = {false}; static std::atomic_bool macroSceneSwitched = {false};
static std::atomic_int shutdownConditionCount = {0}; static std::atomic_int shutdownConditionCount = {0};
static void appendNestedMacros(std::deque<std::shared_ptr<Macro>> &macros,
Macro *macro)
{
if (!macro) {
return;
}
const auto iterate = [&macros](const std::deque<
std::shared_ptr<MacroAction>> &actions) {
for (const auto &action : actions) {
const auto nestedMacroAction =
dynamic_cast<MacroActionMacro *>(action.get());
if (!nestedMacroAction) {
continue;
}
macros.push_back(nestedMacroAction->_nestedMacro);
appendNestedMacros(
macros, nestedMacroAction->_nestedMacro.get());
}
};
iterate(macro->Actions());
iterate(macro->ElseActions());
}
std::deque<std::shared_ptr<Macro>> &GetTopLevelMacros()
{
static std::deque<std::shared_ptr<Macro>> macros;
return macros;
}
std::deque<std::shared_ptr<Macro>> &GetTemporaryMacros()
{
static std::deque<std::shared_ptr<Macro>> tempMacros;
return tempMacros;
}
std::deque<std::shared_ptr<Macro>> GetAllMacros()
{
auto macros = GetTopLevelMacros();
for (const auto &topLevelMacro : macros) {
appendNestedMacros(macros, topLevelMacro.get());
}
const auto &tempMacros = GetTemporaryMacros();
macros.insert(macros.end(), tempMacros.begin(), tempMacros.end());
for (const auto &tempMacro : tempMacros) {
appendNestedMacros(macros, tempMacro.get());
}
return macros;
}
std::optional<std::deque<std::shared_ptr<MacroAction>>> std::optional<std::deque<std::shared_ptr<MacroAction>>>
GetMacroActions(Macro *macro) GetMacroActions(Macro *macro)
{ {
@@ -17,6 +72,15 @@ GetMacroActions(Macro *macro)
return macro->Actions(); return macro->Actions();
} }
std::optional<std::deque<std::shared_ptr<MacroAction>>>
GetMacroElseActions(Macro *macro)
{
if (!macro) {
return {};
}
return macro->ElseActions();
}
std::optional<std::deque<std::shared_ptr<MacroCondition>>> std::optional<std::deque<std::shared_ptr<MacroCondition>>>
GetMacroConditions(Macro *macro) GetMacroConditions(Macro *macro)
{ {
@@ -144,20 +208,42 @@ void ResetMacroRunCount(Macro *macro)
macro->ResetRunCount(); macro->ResetRunCount();
} }
bool IsValidMacroSegmentIndex(const Macro *m, const int idx, bool isCondition) bool IsValidActionIndex(const Macro *m, const int idx)
{ {
if (!m || idx < 0) { if (!m || idx < 0) {
return false; return false;
} }
if (isCondition) {
if (idx >= (int)m->Conditions().size()) { if (idx >= (int)m->Actions().size()) {
return false; return false;
}
} else {
if (idx >= (int)m->Actions().size()) {
return false;
}
} }
return true;
}
bool IsValidElseActionIndex(const Macro *m, const int idx)
{
if (!m || idx < 0) {
return false;
}
if (idx >= (int)m->ElseActions().size()) {
return false;
}
return true;
}
bool IsValidConditionIndex(const Macro *m, const int idx)
{
if (!m || idx < 0) {
return false;
}
if (idx >= (int)m->Conditions().size()) {
return false;
}
return true; return true;
} }

View File

@@ -18,10 +18,14 @@ class Macro;
class MacroAction; class MacroAction;
class MacroCondition; class MacroCondition;
EXPORT std::deque<std::shared_ptr<Macro>> &GetMacros(); EXPORT std::deque<std::shared_ptr<Macro>> &GetTopLevelMacros();
std::deque<std::shared_ptr<Macro>> &GetTemporaryMacros();
EXPORT std::deque<std::shared_ptr<Macro>> GetAllMacros();
EXPORT std::optional<std::deque<std::shared_ptr<MacroAction>>> EXPORT std::optional<std::deque<std::shared_ptr<MacroAction>>>
GetMacroActions(Macro *); GetMacroActions(Macro *);
EXPORT std::optional<std::deque<std::shared_ptr<MacroAction>>>
GetMacroElseActions(Macro *);
EXPORT std::optional<std::deque<std::shared_ptr<MacroCondition>>> EXPORT std::optional<std::deque<std::shared_ptr<MacroCondition>>>
GetMacroConditions(Macro *); GetMacroConditions(Macro *);
@@ -68,6 +72,8 @@ EXPORT void InvalidateMacroTempVarValues();
EXPORT void ResetMacroConditionTimers(Macro *); EXPORT void ResetMacroConditionTimers(Macro *);
EXPORT void ResetMacroRunCount(Macro *); EXPORT void ResetMacroRunCount(Macro *);
bool IsValidMacroSegmentIndex(const Macro *m, const int idx, bool isCondition); bool IsValidActionIndex(const Macro *m, const int idx);
bool IsValidElseActionIndex(const Macro *m, const int idx);
bool IsValidConditionIndex(const Macro *m, const int idx);
} // namespace advss } // namespace advss

View File

@@ -73,35 +73,46 @@ void MacroSegmentSelection::MacroSegmentOrderChanged()
} }
static QString GetMacroSegmentDescription(Macro *macro, int idx, static QString GetMacroSegmentDescription(Macro *macro, int idx,
bool isCondition) MacroSegmentSelection::Type type)
{ {
if (!macro) { if (!macro) {
return ""; return "";
} }
if (!IsValidMacroSegmentIndex(macro, idx, isCondition)) {
MacroSegment *segment;
switch (type) {
case MacroSegmentSelection::Type::CONDITION:
if (!IsValidConditionIndex(macro, idx)) {
return "";
}
segment = GetMacroConditions(macro)->at(idx).get();
break;
case MacroSegmentSelection::Type::ACTION:
if (!IsValidActionIndex(macro, idx)) {
return "";
}
segment = GetMacroActions(macro)->at(idx).get();
break;
case MacroSegmentSelection::Type::ELSE_ACTION:
if (!IsValidElseActionIndex(macro, idx)) {
return "";
}
segment = GetMacroElseActions(macro)->at(idx).get();
break;
default:
return ""; return "";
} }
MacroSegment *segment; const auto idToName = type == MacroSegmentSelection::Type::CONDITION
if (isCondition) { ? MacroConditionFactory::GetConditionName
segment = GetMacroConditions(macro)->at(idx).get(); : MacroActionFactory::GetActionName;
} else { const QString typeStr =
segment = GetMacroActions(macro)->at(idx).get(); obs_module_text(idToName(segment->GetId()).c_str());
} const QString description =
QString::fromStdString(segment->GetShortDesc());
QString description = QString::fromStdString(segment->GetShortDesc()); QString result = typeStr;
QString type;
if (isCondition) {
type = obs_module_text(MacroConditionFactory::GetConditionName(
segment->GetId())
.c_str());
} else {
type = obs_module_text(
MacroActionFactory::GetActionName(segment->GetId())
.c_str());
}
QString result = type;
if (!description.isEmpty()) { if (!description.isEmpty()) {
result += ": " + description; result += ": " + description;
} }
@@ -123,11 +134,25 @@ void MacroSegmentSelection::SetupDescription() const
return; return;
} }
bool validIndex = false;
switch (_type) {
case Type::CONDITION:
validIndex = IsValidConditionIndex(_macro, index - 1);
break;
case Type::ACTION:
validIndex = IsValidActionIndex(_macro, index - 1);
break;
case Type::ELSE_ACTION:
validIndex = IsValidElseActionIndex(_macro, index - 1);
break;
default:
break;
}
QString description; QString description;
if (IsValidMacroSegmentIndex(_macro, index - 1, if (validIndex) {
_type == Type::CONDITION)) { description =
description = GetMacroSegmentDescription( GetMacroSegmentDescription(_macro, index - 1, _type);
_macro, index - 1, _type == Type::CONDITION);
} else { } else {
description = obs_module_text( description = obs_module_text(
"AdvSceneSwitcher.macroSegmentSelection.invalid"); "AdvSceneSwitcher.macroSegmentSelection.invalid");
@@ -165,8 +190,23 @@ void MacroSegmentSelection::MarkSelectedSegment()
if (index.GetType() == IntVariable::Type::VARIABLE) { if (index.GetType() == IntVariable::Type::VARIABLE) {
return; return;
} }
if (!IsValidMacroSegmentIndex(_macro, index - 1,
_type == Type::CONDITION)) { bool validIndex = false;
switch (_type) {
case Type::CONDITION:
validIndex = IsValidConditionIndex(_macro, index - 1);
break;
case Type::ACTION:
validIndex = IsValidActionIndex(_macro, index - 1);
break;
case Type::ELSE_ACTION:
validIndex = IsValidElseActionIndex(_macro, index - 1);
break;
default:
break;
}
if (!validIndex) {
return; return;
} }

View File

@@ -8,7 +8,7 @@ class Macro;
class MacroSegmentSelection : public QWidget { class MacroSegmentSelection : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
enum class Type { CONDITION, ACTION }; enum class Type { CONDITION, ACTION, ELSE_ACTION };
MacroSegmentSelection(QWidget *parent, Type type, MacroSegmentSelection(QWidget *parent, Type type,
bool allowVariables = true); bool allowVariables = true);

View File

@@ -14,7 +14,7 @@ MacroSelection::MacroSelection(QWidget *parent)
: FilterComboBox(parent, : FilterComboBox(parent,
obs_module_text("AdvSceneSwitcher.selectMacro")) obs_module_text("AdvSceneSwitcher.selectMacro"))
{ {
for (const auto &m : GetMacros()) { for (const auto &m : GetTopLevelMacros()) {
if (m->IsGroup()) { if (m->IsGroup()) {
continue; continue;
} }

View File

@@ -150,7 +150,7 @@ static void addGroupSubitems(std::vector<std::shared_ptr<Macro>> &macros,
subitems.reserve(group->GroupSize()); subitems.reserve(group->GroupSize());
// Find all subitems // Find all subitems
auto allMacros = GetMacros(); auto allMacros = GetTopLevelMacros();
for (auto it = allMacros.begin(); it < allMacros.end(); it++) { for (auto it = allMacros.begin(); it < allMacros.end(); it++) {
if ((*it)->Name() != group->Name()) { if ((*it)->Name() != group->Name()) {
continue; continue;
@@ -410,13 +410,17 @@ void AdvSceneSwitcher::ImportMacros()
int groupSize = 0; int groupSize = 0;
std::shared_ptr<Macro> group; std::shared_ptr<Macro> group;
std::vector<std::shared_ptr<Macro>> importedMacros; std::vector<std::shared_ptr<Macro>> importedMacros;
auto &tempMacros = GetTemporaryMacros();
auto lock = LockContext(); auto lock = LockContext();
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
tempMacros.clear();
OBSDataAutoRelease array_obj = obs_data_array_item(array, i); OBSDataAutoRelease array_obj = obs_data_array_item(array, i);
auto macro = std::make_shared<Macro>(); auto macro = std::make_shared<Macro>();
tempMacros.emplace_back(macro);
macro->Load(array_obj); macro->Load(array_obj);
RunPostLoadSteps(); RunAndClearPostLoadSteps();
if (macroNameExists(macro->Name()) && if (macroNameExists(macro->Name()) &&
!ResolveMacroImportNameConflict(macro)) { !ResolveMacroImportNameConflict(macro)) {
@@ -425,7 +429,7 @@ void AdvSceneSwitcher::ImportMacros()
} }
importedMacros.emplace_back(macro); importedMacros.emplace_back(macro);
GetMacros().emplace_back(macro); GetTopLevelMacros().emplace_back(macro);
if (groupSize > 0 && !macro->IsGroup()) { if (groupSize > 0 && !macro->IsGroup()) {
Macro::PrepareMoveToGroup(group, macro); Macro::PrepareMoveToGroup(group, macro);
groupSize--; groupSize--;
@@ -444,9 +448,10 @@ void AdvSceneSwitcher::ImportMacros()
for (const auto &macro : importedMacros) { for (const auto &macro : importedMacros) {
macro->PostLoad(); macro->PostLoad();
} }
RunPostLoadSteps(); RunAndClearPostLoadSteps();
tempMacros.clear();
ui->macros->Reset(GetMacros(), ui->macros->Reset(GetTopLevelMacros(),
GetGlobalMacroSettings()._highlightExecuted); GetGlobalMacroSettings()._highlightExecuted);
disableAddButtonHighlight(); disableAddButtonHighlight();
} }
@@ -633,7 +638,7 @@ void AdvSceneSwitcher::SetupMacroTab()
{ {
ui->macros->installEventFilter(this); ui->macros->installEventFilter(this);
if (GetMacros().size() == 0 && !switcher->disableHints) { if (GetTopLevelMacros().size() == 0 && !switcher->disableHints) {
addPulse = HighlightWidget(ui->macroAdd, QColor(Qt::green)); addPulse = HighlightWidget(ui->macroAdd, QColor(Qt::green));
} }
@@ -641,7 +646,7 @@ void AdvSceneSwitcher::SetupMacroTab()
{ui->macroUp, ui->macroDown}}); {ui->macroUp, ui->macroDown}});
ui->macroControlLayout->addWidget(macroControls); ui->macroControlLayout->addWidget(macroControls);
ui->macros->Reset(GetMacros(), ui->macros->Reset(GetTopLevelMacros(),
GetGlobalMacroSettings()._highlightExecuted); GetGlobalMacroSettings()._highlightExecuted);
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this, connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
SLOT(MacroSelectionChanged())); SLOT(MacroSelectionChanged()));
@@ -752,7 +757,7 @@ void AdvSceneSwitcher::CopyMacro()
newMacro->Load(data); newMacro->Load(data);
newMacro->PostLoad(); newMacro->PostLoad();
newMacro->SetName(name); newMacro->SetName(name);
RunPostLoadSteps(); RunAndClearPostLoadSteps();
Macro::PrepareMoveToGroup(macro->Parent(), newMacro); Macro::PrepareMoveToGroup(macro->Parent(), newMacro);
ui->macros->Add(newMacro, macro); ui->macros->Add(newMacro, macro);

View File

@@ -1184,7 +1184,7 @@ bool MacroTree::SelectionEmpty() const
bool MacroTree::GroupsExist() const bool MacroTree::GroupsExist() const
{ {
for (const auto &macro : GetMacros()) { for (const auto &macro : GetTopLevelMacros()) {
if (macro->IsGroup()) { if (macro->IsGroup()) {
return true; return true;
} }
@@ -1306,7 +1306,7 @@ void MacroTree::UngroupSelectedGroups()
void MacroTree::ExpandAll() void MacroTree::ExpandAll()
{ {
for (const auto &macro : GetMacros()) { for (const auto &macro : GetTopLevelMacros()) {
if (!macro->IsGroup()) { if (!macro->IsGroup()) {
continue; continue;
} }
@@ -1316,7 +1316,7 @@ void MacroTree::ExpandAll()
void MacroTree::CollapseAll() void MacroTree::CollapseAll()
{ {
for (const auto &macro : GetMacros()) { for (const auto &macro : GetTopLevelMacros()) {
if (!macro->IsGroup()) { if (!macro->IsGroup()) {
continue; continue;
} }

View File

@@ -17,8 +17,6 @@
namespace advss { namespace advss {
static std::deque<std::shared_ptr<Macro>> macros;
Macro::Macro(const std::string &name) : _dockSettings(this) Macro::Macro(const std::string &name) : _dockSettings(this)
{ {
SetName(name); SetName(name);
@@ -59,6 +57,7 @@ Macro::CreateGroup(const std::string &name,
void Macro::RemoveGroup(std::shared_ptr<Macro> group) void Macro::RemoveGroup(std::shared_ptr<Macro> group)
{ {
auto &macros = GetTopLevelMacros();
auto it = std::find(macros.begin(), macros.end(), group); auto it = std::find(macros.begin(), macros.end(), group);
if (it == macros.end()) { if (it == macros.end()) {
return; return;
@@ -75,6 +74,7 @@ void Macro::RemoveGroup(std::shared_ptr<Macro> group)
void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr<Macro> item) void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr<Macro> item)
{ {
auto &macros = GetTopLevelMacros();
for (const auto &m : macros) { for (const auto &m : macros) {
if (m.get() == group) { if (m.get() == group) {
PrepareMoveToGroup(m, item); PrepareMoveToGroup(m, item);
@@ -1114,7 +1114,7 @@ void Macro::SetHotkeysDesc() const
void SaveMacros(obs_data_t *obj) void SaveMacros(obs_data_t *obj)
{ {
obs_data_array_t *macroArray = obs_data_array_create(); obs_data_array_t *macroArray = obs_data_array_create();
for (const auto &m : macros) { for (const auto &m : GetTopLevelMacros()) {
obs_data_t *array_obj = obs_data_create(); obs_data_t *array_obj = obs_data_create();
m->Save(array_obj); m->Save(array_obj);
@@ -1128,7 +1128,9 @@ void SaveMacros(obs_data_t *obj)
void LoadMacros(obs_data_t *obj) void LoadMacros(obs_data_t *obj)
{ {
auto &macros = GetTopLevelMacros();
macros.clear(); macros.clear();
obs_data_array_t *macroArray = obs_data_get_array(obj, "macros"); obs_data_array_t *macroArray = obs_data_get_array(obj, "macros");
size_t count = obs_data_array_count(macroArray); size_t count = obs_data_array_count(macroArray);
@@ -1178,15 +1180,10 @@ void LoadMacros(obs_data_t *obj)
} }
} }
std::deque<std::shared_ptr<Macro>> &GetMacros()
{
return macros;
}
bool CheckMacros() bool CheckMacros()
{ {
bool matchFound = false; bool matchFound = false;
for (const auto &m : macros) { for (const auto &m : GetTopLevelMacros()) {
if (!m->ConditionsShouldBeChecked()) { if (!m->ConditionsShouldBeChecked()) {
vblog(LOG_INFO, vblog(LOG_INFO,
"skipping condition check for macro \"%s\" " "skipping condition check for macro \"%s\" "
@@ -1213,7 +1210,7 @@ bool RunMacros()
// reordered while macros are currently being executed. // reordered while macros are currently being executed.
// For example, this can happen if a macro is performing a wait action, // For example, this can happen if a macro is performing a wait action,
// as the main lock will be unlocked during this time. // as the main lock will be unlocked during this time.
auto runPhaseMacros = macros; auto runPhaseMacros = GetTopLevelMacros();
// Avoid deadlocks when opening settings window and calling frontend // Avoid deadlocks when opening settings window and calling frontend
// API functions at the same time. // API functions at the same time.
@@ -1253,14 +1250,14 @@ bool RunMacros()
void StopAllMacros() void StopAllMacros()
{ {
for (const auto &m : macros) { for (const auto &m : GetAllMacros()) {
m->Stop(); m->Stop();
} }
} }
Macro *GetMacroByName(const char *name) Macro *GetMacroByName(const char *name)
{ {
for (const auto &m : macros) { for (const auto &m : GetTopLevelMacros()) {
if (m->Name() == name) { if (m->Name() == name) {
return m.get(); return m.get();
} }
@@ -1276,7 +1273,7 @@ Macro *GetMacroByQString(const QString &name)
std::weak_ptr<Macro> GetWeakMacroByName(const char *name) std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
{ {
for (const auto &m : macros) { for (const auto &m : GetTopLevelMacros()) {
if (m->Name() == name) { if (m->Name() == name) {
return m; return m;
} }
@@ -1287,7 +1284,7 @@ std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
void InvalidateMacroTempVarValues() void InvalidateMacroTempVarValues()
{ {
for (const auto &m : macros) { for (const auto &m : GetTopLevelMacros()) {
// Do not invalidate the temp vars set during condition checks // Do not invalidate the temp vars set during condition checks
// or action executions running in parallel to the "main" macro // or action executions running in parallel to the "main" macro
// loop, as otherwise access to the information stored in those // loop, as otherwise access to the information stored in those
@@ -1302,6 +1299,8 @@ void InvalidateMacroTempVarValues()
std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval() std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval()
{ {
auto &macros = GetTopLevelMacros();
if (macros.empty()) { if (macros.empty()) {
return {}; return {};
} }

View File

@@ -217,7 +217,6 @@ private:
void LoadMacros(obs_data_t *obj); void LoadMacros(obs_data_t *obj);
void SaveMacros(obs_data_t *obj); void SaveMacros(obs_data_t *obj);
std::deque<std::shared_ptr<Macro>> &GetMacros();
bool CheckMacros(); bool CheckMacros();
bool RunMacros(); bool RunMacros();
void StopAllMacros(); void StopAllMacros();

View File

@@ -113,7 +113,7 @@ void ActionQueue::Add(const std::shared_ptr<MacroAction> &action)
action->Save(data); action->Save(data);
copy->Load(data); copy->Load(data);
copy->PostLoad(); copy->PostLoad();
RunPostLoadSteps(); RunAndClearPostLoadSteps();
copy->ResolveVariablesToFixedValues(); copy->ResolveVariablesToFixedValues();
_actions.emplace_back(copy); _actions.emplace_back(copy);
} else { } else {

View File

@@ -113,12 +113,13 @@ void RunLoadSteps(obs_data_t *obj)
} }
} }
void RunPostLoadSteps() void RunAndClearPostLoadSteps()
{ {
std::lock_guard<std::mutex> lock(postLoadMutex); std::lock_guard<std::mutex> lock(postLoadMutex);
for (const auto &func : getPostLoadSteps()) { for (const auto &func : getPostLoadSteps()) {
func(); func();
} }
getPostLoadSteps().clear();
} }
void ClearPostLoadSteps() void ClearPostLoadSteps()

View File

@@ -14,7 +14,7 @@ EXPORT void AddPostLoadStep(std::function<void()>);
EXPORT void AddIntervalResetStep(std::function<void()>); EXPORT void AddIntervalResetStep(std::function<void()>);
void RunSaveSteps(obs_data_t *); void RunSaveSteps(obs_data_t *);
void RunLoadSteps(obs_data_t *); void RunLoadSteps(obs_data_t *);
EXPORT void RunPostLoadSteps(); EXPORT void RunAndClearPostLoadSteps();
void ClearPostLoadSteps(); void ClearPostLoadSteps();
EXPORT void AddPluginInitStep(std::function<void()>); EXPORT void AddPluginInitStep(std::function<void()>);

View File

@@ -239,22 +239,26 @@ void SceneSelection::ResolveVariables()
_type = Type::SCENE; _type = Type::SCENE;
} }
SceneSelection SceneSelectionWidget::CurrentSelection() static obs_weak_canvas_t *getWeakRefToMainCanvas()
{ {
SceneSelection s; static auto canvas = obs_get_main_canvas();
static auto weakCanvas = obs_canvas_get_weak_canvas(canvas);
static auto mainCanvas = obs_get_main_canvas();
static auto mainCanvasWeak = obs_canvas_get_weak_canvas(mainCanvas);
[[maybe_unused]] static const bool _ = []() { [[maybe_unused]] static const bool _ = []() {
// Let's just hope we don't have to deal with selecting scenes // Let's just hope we don't have to deal with selecting scenes
// when the OBS main canvas gets deleted and release the // when the OBS main canvas gets deleted and release the
// references here already to avoid reporting leaks on shutdown // references here already to avoid reporting leaks on shutdown
obs_canvas_release(mainCanvas); obs_canvas_release(canvas);
obs_weak_canvas_release(mainCanvasWeak); obs_weak_canvas_release(weakCanvas);
return true; return true;
}(); }();
return weakCanvas;
}
s._canvas = _forceMainCanvas ? OBSWeakCanvas(mainCanvasWeak) SceneSelection SceneSelectionWidget::CurrentSelection()
{
SceneSelection s;
s._canvas = _forceMainCanvas ? OBSWeakCanvas(getWeakRefToMainCanvas())
: _canvas->GetCanvas(); : _canvas->GetCanvas();
const int idx = _scenes->currentIndex(); const int idx = _scenes->currentIndex();
@@ -330,6 +334,7 @@ static QStringList getCanvasScenesList(obs_weak_canvas_t *weakCanvas)
QStringList list; QStringList list;
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &list); obs_canvas_enum_scenes(canvas, enumCanvasScenes, &list);
list.sort();
return list; return list;
} }
@@ -342,6 +347,10 @@ void SceneSelectionWidget::Reset()
void SceneSelectionWidget::PopulateSceneSelection(obs_weak_canvas_t *canvas) void SceneSelectionWidget::PopulateSceneSelection(obs_weak_canvas_t *canvas)
{ {
if (_forceMainCanvas) {
canvas = getWeakRefToMainCanvas();
}
_scenes->clear(); _scenes->clear();
if ((_current || _previous)) { if ((_current || _previous)) {
const bool isMain = IsMainCanvas(canvas); const bool isMain = IsMainCanvas(canvas);
@@ -418,7 +427,7 @@ SceneSelectionWidget::SceneSelectionWidget(QWidget *parent, bool variables,
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
if (GetCanvasCount() <= 1) { if (GetCanvasCount() <= 1) {
_canvas->hide(); LockToMainCanvas();
} }
Resize(); Resize();

View File

@@ -199,7 +199,17 @@ std::chrono::high_resolution_clock::time_point GetLastSceneChangeTime()
OBSWeakSource GetCurrentScene() OBSWeakSource GetCurrentScene()
{ {
return switcher->currentScene; if (switcher->currentScene) {
return switcher->currentScene;
}
// If there wasn't any scene switch yet switcher->currentScene will be
// null and we must use obs_frontend_get_current_scene() instead
OBSSourceAutoRelease currentSceneSource =
obs_frontend_get_current_scene();
OBSWeakSourceAutoRelease currentSceneWeakSource =
obs_source_get_weak_source(currentSceneSource);
return currentSceneWeakSource.Get();
} }
OBSWeakSource GetPreviousScene() OBSWeakSource GetPreviousScene()

View File

@@ -190,29 +190,6 @@ static bool isMatchingNestedMacroAction(MacroAction *action, const Macro *macro)
return nestedMacroAction->_nestedMacro.get() == macro; return nestedMacroAction->_nestedMacro.get() == macro;
} }
static void appendNestedMacros(std::deque<std::shared_ptr<Macro>> &macros,
Macro *macro)
{
if (!macro) {
return;
}
for (const auto &action : macro->Actions()) {
const auto nestedMacroAction =
dynamic_cast<MacroActionMacro *>(action.get());
if (nestedMacroAction) {
macros.push_back(nestedMacroAction->_nestedMacro);
}
}
for (const auto &action : macro->ElseActions()) {
const auto nestedMacroAction =
dynamic_cast<MacroActionMacro *>(action.get());
if (nestedMacroAction) {
macros.push_back(nestedMacroAction->_nestedMacro);
}
}
}
static Macro *getParentMacro(const Macro *targetMacro, static Macro *getParentMacro(const Macro *targetMacro,
const std::vector<Macro *> &macros) const std::vector<Macro *> &macros)
{ {
@@ -263,8 +240,10 @@ static Macro *getParentMacro(const Macro *targetMacro,
static Macro *getParentMacro(const Macro *macro) static Macro *getParentMacro(const Macro *macro)
{ {
const auto &topLevelMacros = GetTopLevelMacros();
std::vector<Macro *> macros; std::vector<Macro *> macros;
for (const auto &macro : GetMacros()) { macros.reserve(topLevelMacros.size());
for (const auto &macro : topLevelMacros) {
macros.emplace_back(macro.get()); macros.emplace_back(macro.get());
} }
return getParentMacro(macro, macros); return getParentMacro(macro, macros);
@@ -301,8 +280,9 @@ void TempVariableRef::Save(obs_data_t *obj, Macro *macro,
void TempVariableRef::Load(obs_data_t *obj, Macro *macroPtr, const char *name) void TempVariableRef::Load(obs_data_t *obj, Macro *macroPtr, const char *name)
{ {
const auto macros = GetAllMacros();
std::weak_ptr<Macro> macro; std::weak_ptr<Macro> macro;
for (const auto &macroShared : GetMacros()) { for (const auto &macroShared : macros) {
if (macroShared.get() == macroPtr) { if (macroShared.get() == macroPtr) {
macro = macroShared; macro = macroShared;
break; break;
@@ -340,9 +320,9 @@ void TempVariableRef::PostLoad(int idx, SegmentType type,
return; return;
} }
Macro *macro = nullptr; auto macro = childMacro.get();
for (int i = 0; i < _depth; i++) { for (int i = 0; i < _depth; i++) {
macro = getParentMacro(childMacro.get()); macro = getParentMacro(macro);
} }
if (!macro) { if (!macro) {
@@ -486,15 +466,9 @@ void TempVariableSelection::MacroSegmentsChanged()
SetVariable(currentSelection); SetVariable(currentSelection);
} }
void TempVariableSelection::SegmentTempVarsChanged(MacroSegment *segment) void TempVariableSelection::SegmentTempVarsChanged(MacroSegment *)
{ {
const auto currentSegment = GetSegment(); MacroSegmentsChanged();
const auto currentMacro = currentSegment ? currentSegment->GetMacro()
: nullptr;
const auto changeMacro = segment ? segment->GetMacro() : nullptr;
if (currentMacro == changeMacro) {
MacroSegmentsChanged();
}
} }
void TempVariableSelection::HighlightChanged(int idx) void TempVariableSelection::HighlightChanged(int idx)

View File

@@ -75,7 +75,7 @@ private:
void PostLoad(int idx, SegmentType, const std::weak_ptr<Macro> &); void PostLoad(int idx, SegmentType, const std::weak_ptr<Macro> &);
std::string _id = ""; std::string _id = "";
std::weak_ptr<MacroSegment> _segment; std::weak_ptr<MacroSegment> _segment = {};
int _depth = 0; int _depth = 0;
friend TempVariable; friend TempVariable;

View File

@@ -252,6 +252,7 @@ MacroConditionSlideshowEdit::MacroConditionSlideshowEdit(
setToolTip(obs_module_text( setToolTip(obs_module_text(
"AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip")); "AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip"));
_index->setMinimum(1); _index->setMinimum(1);
_index->setMaximum(9999);
populateConditionSelection(_conditions); populateConditionSelection(_conditions);
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,

View File

@@ -10,6 +10,12 @@ if(OS_MACOS)
endif() endif()
find_package(OpenSSL) find_package(OpenSSL)
get_cmake_property(_variableNames VARIABLES)
list(SORT _variableNames)
foreach(_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
find_package(PahoMqttCpp) find_package(PahoMqttCpp)
if(NOT PahoMqttCpp_FOUND) if(NOT PahoMqttCpp_FOUND)
message(WARNING "PahoMqttCpp not found!\n" message(WARNING "PahoMqttCpp not found!\n"