Refactor to support loading macro properties on import

This commit is contained in:
WarmUpTill 2025-10-31 22:01:26 +01:00 committed by WarmUpTill
parent e1020a1909
commit 0d56de11d1
9 changed files with 92 additions and 69 deletions

View File

@ -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());
}

View File

@ -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<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) {
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 &topLevelMacro : tempMacros) {
appendNestedMacros(macros, topLevelMacro.get());
}
return macros;
}
std::optional<std::deque<std::shared_ptr<MacroAction>>>
GetMacroActions(Macro *macro)
{

View File

@ -18,7 +18,9 @@ class Macro;
class MacroAction;
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>>>
GetMacroActions(Macro *);

View File

@ -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;
}

View File

@ -150,7 +150,7 @@ static void addGroupSubitems(std::vector<std::shared_ptr<Macro>> &macros,
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<Macro> group;
std::vector<std::shared_ptr<Macro>> 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<Macro>();
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()));

View File

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

View File

@ -17,8 +17,6 @@
namespace advss {
static std::deque<std::shared_ptr<Macro>> 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<Macro> group)
{
auto &macros = 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<Macro> group)
void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr<Macro> item)
{
auto &macros = 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 &macros = 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<std::shared_ptr<Macro>> &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<Macro> 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<Macro> 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<Macro> GetMacroWithInvalidConditionInterval()
{
auto &macros = GetTopLevelMacros();
if (macros.empty()) {
return {};
}

View File

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

View File

@ -190,33 +190,6 @@ static bool isMatchingNestedMacroAction(MacroAction *action, const Macro *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);
appendNestedMacros(
macros, nestedMacroAction->_nestedMacro.get());
}
}
for (const auto &action : macro->ElseActions()) {
const auto nestedMacroAction =
dynamic_cast<MacroActionMacro *>(action.get());
if (nestedMacroAction) {
macros.push_back(nestedMacroAction->_nestedMacro);
appendNestedMacros(
macros, nestedMacroAction->_nestedMacro.get());
}
}
}
static Macro *getParentMacro(const Macro *targetMacro,
const std::vector<Macro *> &macros)
{
@ -267,8 +240,10 @@ static Macro *getParentMacro(const Macro *targetMacro,
static Macro *getParentMacro(const Macro *macro)
{
const auto &topLevelMacros = GetTopLevelMacros();
std::vector<Macro *> macros;
for (const auto &macro : GetMacros()) {
macros.reserve(topLevelMacros.size());
for (const auto &macro : 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<std::shared_ptr<Macro>> allMacros = GetMacros();
for (const auto &topLevelMacro : GetMacros()) {
appendNestedMacros(allMacros, topLevelMacro.get());
}
const auto macros = GetAllMacros();
std::weak_ptr<Macro> macro;
for (const auto &macroShared : allMacros) {
for (const auto &macroShared : 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)