mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-11-15 03:36:53 -06:00
Support nested macro groups in data model
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <limits>
|
||||
#undef max
|
||||
@@ -62,11 +63,23 @@ Macro::CreateGroup(const std::string &name,
|
||||
{
|
||||
auto group = std::make_shared<Macro>(name);
|
||||
group->_registerHotkeys = false;
|
||||
for (auto &c : children) {
|
||||
c->SetParent(group);
|
||||
}
|
||||
group->_isGroup = true;
|
||||
group->_groupSize = children.size();
|
||||
|
||||
if (!children.empty()) {
|
||||
const auto parent = children.front()->Parent();
|
||||
const bool haveSameParent = std::all_of(
|
||||
children.begin(), children.end(),
|
||||
[&parent](const std::shared_ptr<Macro> &child) {
|
||||
return child->Parent() == parent;
|
||||
});
|
||||
if (haveSameParent) {
|
||||
PrepareMoveToGroup(parent, group);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &child : children) {
|
||||
PrepareMoveToGroup(group, child);
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -78,11 +91,11 @@ void Macro::RemoveGroup(std::shared_ptr<Macro> group)
|
||||
return;
|
||||
}
|
||||
|
||||
auto size = group->GroupSize();
|
||||
for (uint32_t i = 1; i <= size; i++) {
|
||||
auto m = std::next(it, i);
|
||||
(*m)->SetParent(nullptr);
|
||||
const auto parent = group->Parent();
|
||||
for (const auto &child : GetGroupChildren(group.get())) {
|
||||
child->SetParent(parent);
|
||||
}
|
||||
AddToGroupSizes(parent, -1);
|
||||
|
||||
macros.erase(it);
|
||||
}
|
||||
@@ -106,15 +119,72 @@ void Macro::PrepareMoveToGroup(std::shared_ptr<Macro> group,
|
||||
return;
|
||||
}
|
||||
|
||||
// Potentially remove from old group
|
||||
auto oldGroup = item->Parent();
|
||||
if (oldGroup) {
|
||||
oldGroup->_groupSize--;
|
||||
if (group &&
|
||||
(group == item || IsMacroInGroup(group.get(), item.get()))) {
|
||||
blog(LOG_WARNING, "cannot move \"%s\" into itself",
|
||||
item->Name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
const int count = 1 + (int)item->_groupSize;
|
||||
AddToGroupSizes(item->Parent(), -count);
|
||||
item->SetParent(group);
|
||||
if (group) {
|
||||
group->_groupSize++;
|
||||
AddToGroupSizes(group, count);
|
||||
}
|
||||
|
||||
void Macro::AddToGroupSizes(std::shared_ptr<Macro> group, int count)
|
||||
{
|
||||
for (; group; group = group->Parent()) {
|
||||
assert((int)group->_groupSize + count >= 0);
|
||||
group->_groupSize += count;
|
||||
}
|
||||
}
|
||||
|
||||
void Macro::RestoreGroupHierarchy(
|
||||
const std::deque<std::shared_ptr<Macro>> ¯os)
|
||||
{
|
||||
struct OpenGroup {
|
||||
std::shared_ptr<Macro> group;
|
||||
uint32_t remaining;
|
||||
};
|
||||
std::vector<OpenGroup> openGroups;
|
||||
|
||||
for (size_t i = 0; i < macros.size(); i++) {
|
||||
const auto ¯o = macros[i];
|
||||
while (!openGroups.empty() &&
|
||||
openGroups.back().remaining == 0) {
|
||||
openGroups.pop_back();
|
||||
}
|
||||
|
||||
macro->SetParent(openGroups.empty() ? nullptr
|
||||
: openGroups.back().group);
|
||||
for (auto &openGroup : openGroups) {
|
||||
openGroup.remaining--;
|
||||
}
|
||||
|
||||
if (!macro->IsGroup()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto maxSize = openGroups.empty()
|
||||
? (uint32_t)(macros.size() - i - 1)
|
||||
: openGroups.back().remaining;
|
||||
auto size = macro->_groupSize;
|
||||
if (size > maxSize) {
|
||||
blog(LOG_WARNING,
|
||||
"invalid group size detected for \"%s\" - "
|
||||
"reducing size from %u to %u",
|
||||
macro->Name().c_str(), size, maxSize);
|
||||
size = maxSize;
|
||||
}
|
||||
openGroups.push_back({macro, size});
|
||||
}
|
||||
|
||||
for (const auto ¯o : macros) {
|
||||
macro->_groupSize = 0;
|
||||
}
|
||||
for (const auto ¯o : macros) {
|
||||
AddToGroupSizes(macro->Parent(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,8 +409,7 @@ bool Macro::PerformActions(bool match, bool forceParallel, bool ignorePause)
|
||||
}
|
||||
|
||||
_lastExecutionTime = std::chrono::high_resolution_clock::now();
|
||||
auto group = _parent.lock();
|
||||
if (group) {
|
||||
for (auto group = _parent.lock(); group; group = group->Parent()) {
|
||||
group->_lastExecutionTime = _lastExecutionTime;
|
||||
}
|
||||
if (_runCount != std::numeric_limits<int>::max()) {
|
||||
@@ -1250,42 +1319,10 @@ void LoadMacros(obs_data_t *obj)
|
||||
}
|
||||
obs_data_array_release(macroArray);
|
||||
|
||||
int groupCount = 0;
|
||||
std::shared_ptr<Macro> group;
|
||||
std::vector<std::shared_ptr<Macro>> invalidGroups;
|
||||
Macro::RestoreGroupHierarchy(macros);
|
||||
for (const auto &m : macros) {
|
||||
if (groupCount && m->IsGroup()) {
|
||||
blog(LOG_ERROR,
|
||||
"nested group detected - will delete \"%s\"",
|
||||
m->Name().c_str());
|
||||
invalidGroups.emplace_back(m);
|
||||
continue;
|
||||
}
|
||||
if (groupCount) {
|
||||
m->SetParent(group);
|
||||
groupCount--;
|
||||
}
|
||||
if (m->IsGroup()) {
|
||||
groupCount = m->GroupSize();
|
||||
group = m;
|
||||
}
|
||||
m->PostLoad();
|
||||
}
|
||||
|
||||
if (groupCount) {
|
||||
blog(LOG_ERROR,
|
||||
"invalid group size detected - will delete \"%s\"",
|
||||
group->Name().c_str());
|
||||
invalidGroups.emplace_back(group);
|
||||
}
|
||||
|
||||
for (auto &m : invalidGroups) {
|
||||
auto it = std::find(macros.begin(), macros.end(), m);
|
||||
if (it == macros.end()) {
|
||||
continue;
|
||||
}
|
||||
macros.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckMacros()
|
||||
|
||||
Reference in New Issue
Block a user