diff --git a/lib/advanced-scene-switcher.cpp b/lib/advanced-scene-switcher.cpp index 7a02e344..b0d2fb46 100644 --- a/lib/advanced-scene-switcher.cpp +++ b/lib/advanced-scene-switcher.cpp @@ -421,7 +421,7 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene, static void ResetMacros() { - for (auto &m : GetMacros()) { + for (auto &m : GetTopLevelMacros()) { ResetMacroRunCount(m.get()); ResetMacroConditionTimers(m.get()); } diff --git a/lib/macro/macro-helpers.cpp b/lib/macro/macro-helpers.cpp index 8cd9230f..5596d87e 100644 --- a/lib/macro/macro-helpers.cpp +++ b/lib/macro/macro-helpers.cpp @@ -1,5 +1,6 @@ #include "macro-helpers.hpp" #include "macro.hpp" +#include "macro-action-macro.hpp" #include "plugin-state-helpers.hpp" namespace advss { @@ -8,6 +9,58 @@ static std::atomic_bool abortMacroWait = {false}; static std::atomic_bool macroSceneSwitched = {false}; static std::atomic_int shutdownConditionCount = {0}; +static void appendNestedMacros(std::deque> ¯os, + Macro *macro) +{ + if (!macro) { + return; + } + + const auto iterate = [¯os](const std::deque< + std::shared_ptr> &actions) { + for (const auto &action : actions) { + const auto nestedMacroAction = + dynamic_cast(action.get()); + if (nestedMacroAction) { + macros.push_back( + nestedMacroAction->_nestedMacro); + appendNestedMacros( + macros, + nestedMacroAction->_nestedMacro.get()); + } + } + }; + + iterate(macro->Actions()); + iterate(macro->ElseActions()); +} + +std::deque> &GetTopLevelMacros() +{ + static std::deque> macros; + return macros; +} + +std::deque> &GetTemporaryMacros() +{ + static std::deque> tempMacros; + return tempMacros; +} + +std::deque> 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 &topLevelMacro : tempMacros) { + appendNestedMacros(macros, topLevelMacro.get()); + } + return macros; +} + std::optional>> GetMacroActions(Macro *macro) { diff --git a/lib/macro/macro-helpers.hpp b/lib/macro/macro-helpers.hpp index 12678cc6..5d8b62af 100644 --- a/lib/macro/macro-helpers.hpp +++ b/lib/macro/macro-helpers.hpp @@ -18,7 +18,9 @@ class Macro; class MacroAction; class MacroCondition; -EXPORT std::deque> &GetMacros(); +EXPORT std::deque> &GetTopLevelMacros(); +std::deque> &GetTemporaryMacros(); +EXPORT std::deque> GetAllMacros(); EXPORT std::optional>> GetMacroActions(Macro *); diff --git a/lib/macro/macro-selection.cpp b/lib/macro/macro-selection.cpp index 74a85cc7..b6851f99 100644 --- a/lib/macro/macro-selection.cpp +++ b/lib/macro/macro-selection.cpp @@ -14,7 +14,7 @@ MacroSelection::MacroSelection(QWidget *parent) : FilterComboBox(parent, obs_module_text("AdvSceneSwitcher.selectMacro")) { - for (const auto &m : GetMacros()) { + for (const auto &m : GetTopLevelMacros()) { if (m->IsGroup()) { continue; } diff --git a/lib/macro/macro-tab.cpp b/lib/macro/macro-tab.cpp index 852d6f56..452119d0 100644 --- a/lib/macro/macro-tab.cpp +++ b/lib/macro/macro-tab.cpp @@ -150,7 +150,7 @@ static void addGroupSubitems(std::vector> ¯os, subitems.reserve(group->GroupSize()); // Find all subitems - auto allMacros = GetMacros(); + auto allMacros = GetTopLevelMacros(); for (auto it = allMacros.begin(); it < allMacros.end(); it++) { if ((*it)->Name() != group->Name()) { continue; @@ -410,11 +410,15 @@ void AdvSceneSwitcher::ImportMacros() int groupSize = 0; std::shared_ptr group; std::vector> importedMacros; + auto &tempMacros = GetTemporaryMacros(); auto lock = LockContext(); for (size_t i = 0; i < count; i++) { + tempMacros.clear(); + OBSDataAutoRelease array_obj = obs_data_array_item(array, i); auto macro = std::make_shared(); + tempMacros.emplace_back(macro); macro->Load(array_obj); RunAndClearPostLoadSteps(); @@ -425,7 +429,7 @@ void AdvSceneSwitcher::ImportMacros() } importedMacros.emplace_back(macro); - GetMacros().emplace_back(macro); + GetTopLevelMacros().emplace_back(macro); if (groupSize > 0 && !macro->IsGroup()) { Macro::PrepareMoveToGroup(group, macro); groupSize--; @@ -445,8 +449,9 @@ void AdvSceneSwitcher::ImportMacros() macro->PostLoad(); } RunAndClearPostLoadSteps(); + tempMacros.clear(); - ui->macros->Reset(GetMacros(), + ui->macros->Reset(GetTopLevelMacros(), GetGlobalMacroSettings()._highlightExecuted); disableAddButtonHighlight(); } @@ -633,7 +638,7 @@ void AdvSceneSwitcher::SetupMacroTab() { ui->macros->installEventFilter(this); - if (GetMacros().size() == 0 && !switcher->disableHints) { + if (GetTopLevelMacros().size() == 0 && !switcher->disableHints) { addPulse = HighlightWidget(ui->macroAdd, QColor(Qt::green)); } @@ -641,7 +646,7 @@ void AdvSceneSwitcher::SetupMacroTab() {ui->macroUp, ui->macroDown}}); ui->macroControlLayout->addWidget(macroControls); - ui->macros->Reset(GetMacros(), + ui->macros->Reset(GetTopLevelMacros(), GetGlobalMacroSettings()._highlightExecuted); connect(ui->macros, SIGNAL(MacroSelectionChanged()), this, SLOT(MacroSelectionChanged())); diff --git a/lib/macro/macro-tree.cpp b/lib/macro/macro-tree.cpp index c4a2ee82..c51e2c04 100644 --- a/lib/macro/macro-tree.cpp +++ b/lib/macro/macro-tree.cpp @@ -1184,7 +1184,7 @@ bool MacroTree::SelectionEmpty() const bool MacroTree::GroupsExist() const { - for (const auto ¯o : GetMacros()) { + for (const auto ¯o : GetTopLevelMacros()) { if (macro->IsGroup()) { return true; } @@ -1306,7 +1306,7 @@ void MacroTree::UngroupSelectedGroups() void MacroTree::ExpandAll() { - for (const auto ¯o : GetMacros()) { + for (const auto ¯o : GetTopLevelMacros()) { if (!macro->IsGroup()) { continue; } @@ -1316,7 +1316,7 @@ void MacroTree::ExpandAll() void MacroTree::CollapseAll() { - for (const auto ¯o : GetMacros()) { + for (const auto ¯o : GetTopLevelMacros()) { if (!macro->IsGroup()) { continue; } diff --git a/lib/macro/macro.cpp b/lib/macro/macro.cpp index 00e72486..c828b39a 100644 --- a/lib/macro/macro.cpp +++ b/lib/macro/macro.cpp @@ -17,8 +17,6 @@ namespace advss { -static std::deque> macros; - Macro::Macro(const std::string &name) : _dockSettings(this) { SetName(name); @@ -59,6 +57,7 @@ Macro::CreateGroup(const std::string &name, void Macro::RemoveGroup(std::shared_ptr group) { + auto ¯os = GetTopLevelMacros(); auto it = std::find(macros.begin(), macros.end(), group); if (it == macros.end()) { return; @@ -75,6 +74,7 @@ void Macro::RemoveGroup(std::shared_ptr group) void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr item) { + auto ¯os = GetTopLevelMacros(); for (const auto &m : macros) { if (m.get() == group) { PrepareMoveToGroup(m, item); @@ -1114,7 +1114,7 @@ void Macro::SetHotkeysDesc() const void SaveMacros(obs_data_t *obj) { 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(); m->Save(array_obj); @@ -1128,7 +1128,9 @@ void SaveMacros(obs_data_t *obj) void LoadMacros(obs_data_t *obj) { + auto ¯os = GetTopLevelMacros(); macros.clear(); + obs_data_array_t *macroArray = obs_data_get_array(obj, "macros"); size_t count = obs_data_array_count(macroArray); @@ -1178,15 +1180,10 @@ void LoadMacros(obs_data_t *obj) } } -std::deque> &GetMacros() -{ - return macros; -} - bool CheckMacros() { bool matchFound = false; - for (const auto &m : macros) { + for (const auto &m : GetTopLevelMacros()) { if (!m->ConditionsShouldBeChecked()) { vblog(LOG_INFO, "skipping condition check for macro \"%s\" " @@ -1213,7 +1210,7 @@ bool RunMacros() // reordered while macros are currently being executed. // For example, this can happen if a macro is performing a wait action, // 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 // API functions at the same time. @@ -1253,14 +1250,14 @@ bool RunMacros() void StopAllMacros() { - for (const auto &m : macros) { + for (const auto &m : GetAllMacros()) { m->Stop(); } } Macro *GetMacroByName(const char *name) { - for (const auto &m : macros) { + for (const auto &m : GetTopLevelMacros()) { if (m->Name() == name) { return m.get(); } @@ -1276,7 +1273,7 @@ Macro *GetMacroByQString(const QString &name) std::weak_ptr GetWeakMacroByName(const char *name) { - for (const auto &m : macros) { + for (const auto &m : GetTopLevelMacros()) { if (m->Name() == name) { return m; } @@ -1287,7 +1284,7 @@ std::weak_ptr GetWeakMacroByName(const char *name) void InvalidateMacroTempVarValues() { - for (const auto &m : macros) { + for (const auto &m : GetTopLevelMacros()) { // Do not invalidate the temp vars set during condition checks // or action executions running in parallel to the "main" macro // loop, as otherwise access to the information stored in those @@ -1302,6 +1299,8 @@ void InvalidateMacroTempVarValues() std::shared_ptr GetMacroWithInvalidConditionInterval() { + auto ¯os = GetTopLevelMacros(); + if (macros.empty()) { return {}; } diff --git a/lib/macro/macro.hpp b/lib/macro/macro.hpp index ceec43b8..6b9b5db7 100644 --- a/lib/macro/macro.hpp +++ b/lib/macro/macro.hpp @@ -217,7 +217,6 @@ private: void LoadMacros(obs_data_t *obj); void SaveMacros(obs_data_t *obj); -std::deque> &GetMacros(); bool CheckMacros(); bool RunMacros(); void StopAllMacros(); diff --git a/lib/utils/temp-variable.cpp b/lib/utils/temp-variable.cpp index 393b9022..df37c89b 100644 --- a/lib/utils/temp-variable.cpp +++ b/lib/utils/temp-variable.cpp @@ -190,33 +190,6 @@ static bool isMatchingNestedMacroAction(MacroAction *action, const Macro *macro) return nestedMacroAction->_nestedMacro.get() == macro; } -static void appendNestedMacros(std::deque> ¯os, - Macro *macro) -{ - if (!macro) { - return; - } - - for (const auto &action : macro->Actions()) { - const auto nestedMacroAction = - dynamic_cast(action.get()); - if (nestedMacroAction) { - macros.push_back(nestedMacroAction->_nestedMacro); - appendNestedMacros( - macros, nestedMacroAction->_nestedMacro.get()); - } - } - for (const auto &action : macro->ElseActions()) { - const auto nestedMacroAction = - dynamic_cast(action.get()); - if (nestedMacroAction) { - macros.push_back(nestedMacroAction->_nestedMacro); - appendNestedMacros( - macros, nestedMacroAction->_nestedMacro.get()); - } - } -} - static Macro *getParentMacro(const Macro *targetMacro, const std::vector ¯os) { @@ -267,8 +240,10 @@ static Macro *getParentMacro(const Macro *targetMacro, static Macro *getParentMacro(const Macro *macro) { + const auto &topLevelMacros = GetTopLevelMacros(); std::vector macros; - for (const auto ¯o : GetMacros()) { + macros.reserve(topLevelMacros.size()); + for (const auto ¯o : topLevelMacros) { macros.emplace_back(macro.get()); } return getParentMacro(macro, macros); @@ -305,13 +280,9 @@ void TempVariableRef::Save(obs_data_t *obj, Macro *macro, void TempVariableRef::Load(obs_data_t *obj, Macro *macroPtr, const char *name) { - std::deque> allMacros = GetMacros(); - for (const auto &topLevelMacro : GetMacros()) { - appendNestedMacros(allMacros, topLevelMacro.get()); - } - + const auto macros = GetAllMacros(); std::weak_ptr macro; - for (const auto ¯oShared : allMacros) { + for (const auto ¯oShared : macros) { if (macroShared.get() == macroPtr) { macro = macroShared; break; @@ -351,7 +322,7 @@ void TempVariableRef::PostLoad(int idx, SegmentType type, auto macro = childMacro.get(); for (int i = 0; i < _depth; i++) { - macro = getParentMacro(childMacro.get()); + macro = getParentMacro(macro); } if (!macro) { @@ -495,15 +466,9 @@ void TempVariableSelection::MacroSegmentsChanged() SetVariable(currentSelection); } -void TempVariableSelection::SegmentTempVarsChanged(MacroSegment *segment) +void TempVariableSelection::SegmentTempVarsChanged(MacroSegment *) { - const auto currentSegment = GetSegment(); - const auto currentMacro = currentSegment ? currentSegment->GetMacro() - : nullptr; - const auto changeMacro = segment ? segment->GetMacro() : nullptr; - if (currentMacro == changeMacro) { - MacroSegmentsChanged(); - } + MacroSegmentsChanged(); } void TempVariableSelection::HighlightChanged(int idx)