mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-26 19:26:04 -05:00
Add support for "else" action block
* Changed the "on change" match behaviour Previously macros with true conditions but "on change" enabled would be considered to be evaluating to false. Now they are considered to be evaluating to true and the "on change" option only has an effect on if the actions are performed or not. This could have effects on user which use the "Macro" condition type to check what other macros' conditions evaluate to. * The splitter position separating the conditions, actions, and else-actions are not saved and restored based on which macro is being selected.
This commit is contained in:
@@ -71,6 +71,7 @@ AdvSceneSwitcher.macroTab.priorityWarning="Note: It is recommended to configure
|
||||
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
|
||||
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define Macro conditions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new condition."
|
||||
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define Macro actions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new action."
|
||||
AdvSceneSwitcher.macroTab.editElseActionHelp="This section allows you to define Macro actions, which are executed if the conditions are *not* met.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new action."
|
||||
AdvSceneSwitcher.macroTab.edit="Edit macro"
|
||||
AdvSceneSwitcher.macroTab.edit.logic="Logic type:"
|
||||
AdvSceneSwitcher.macroTab.edit.condition="Condition type:"
|
||||
|
||||
@@ -84,10 +84,13 @@ public:
|
||||
void SetEditMacro(Macro &m);
|
||||
void SetMacroEditAreaDisabled(bool);
|
||||
void HighlightAction(int idx, QColor color = QColor(Qt::green));
|
||||
void HighlightElseAction(int idx, QColor color = QColor(Qt::green));
|
||||
void HighlightCondition(int idx, QColor color = QColor(Qt::green));
|
||||
void PopulateMacroActions(Macro &m, uint32_t afterIdx = 0);
|
||||
void PopulateMacroElseActions(Macro &m, uint32_t afterIdx = 0);
|
||||
void PopulateMacroConditions(Macro &m, uint32_t afterIdx = 0);
|
||||
void SetActionData(Macro &m);
|
||||
void SetElseActionData(Macro &m);
|
||||
void SetConditionData(Macro &m);
|
||||
void SwapActions(Macro *m, int pos1, int pos2);
|
||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||
@@ -113,29 +116,50 @@ public slots:
|
||||
void on_actionUp_clicked();
|
||||
void on_actionDown_clicked();
|
||||
void on_actionBottom_clicked();
|
||||
void on_elseActionAdd_clicked();
|
||||
void on_elseActionRemove_clicked();
|
||||
void on_elseActionTop_clicked();
|
||||
void on_elseActionUp_clicked();
|
||||
void on_elseActionDown_clicked();
|
||||
void on_elseActionBottom_clicked();
|
||||
void MacroSelectionAboutToChange();
|
||||
void MacroSelectionChanged();
|
||||
void UpMacroSegementHotkey();
|
||||
void DownMacroSegementHotkey();
|
||||
void DeleteMacroSegementHotkey();
|
||||
void ShowMacroContextMenu(const QPoint &);
|
||||
void ShowMacroActionsContextMenu(const QPoint &);
|
||||
void ShowMacroElseActionsContextMenu(const QPoint &);
|
||||
void ShowMacroConditionsContextMenu(const QPoint &);
|
||||
void CopyMacro();
|
||||
void RenameCurrentMacro();
|
||||
void ExportMacros();
|
||||
void ImportMacros();
|
||||
void ExpandAllActions();
|
||||
void ExpandAllElseActions();
|
||||
void ExpandAllConditions();
|
||||
void CollapseAllActions();
|
||||
void CollapseAllElseActions();
|
||||
void CollapseAllConditions();
|
||||
void MinimizeActions();
|
||||
void MaximizeActions();
|
||||
void MinimizeElseActions();
|
||||
void MaximizeElseActions();
|
||||
void MinimizeConditions();
|
||||
void MaximizeConditions();
|
||||
void MacroActionSelectionChanged(int idx);
|
||||
void MacroActionReorder(int to, int target);
|
||||
void AddMacroAction(int idx);
|
||||
void RemoveMacroAction(int idx);
|
||||
void MoveMacroActionUp(int idx);
|
||||
void MoveMacroActionDown(int idx);
|
||||
void MacroElseActionSelectionChanged(int idx);
|
||||
void MacroElseActionReorder(int to, int target);
|
||||
void AddMacroElseAction(int idx);
|
||||
void RemoveMacroElseAction(int idx);
|
||||
void SwapElseActions(Macro *m, int pos1, int pos2);
|
||||
void MoveMacroElseActionUp(int idx);
|
||||
void MoveMacroElseActionDown(int idx);
|
||||
void MacroConditionSelectionChanged(int idx);
|
||||
void MacroConditionReorder(int to, int target);
|
||||
void AddMacroCondition(int idx);
|
||||
@@ -157,6 +181,7 @@ signals:
|
||||
void MacroSegmentOrderChanged();
|
||||
void HighlightMacrosChanged(bool value);
|
||||
void HighlightActionsChanged(bool value);
|
||||
void HighlightElseActionsChanged(bool value);
|
||||
void HighlightConditionsChanged(bool value);
|
||||
|
||||
void ConnectionAdded(const QString &);
|
||||
@@ -167,16 +192,16 @@ signals:
|
||||
void VariableRemoved(const QString &);
|
||||
|
||||
private:
|
||||
enum class MacroSection { CONDITIONS, ACTIONS, ELSE_ACTIONS };
|
||||
|
||||
void SetupMacroSegmentSelection(MacroSection type, int idx);
|
||||
bool ResolveMacroImportNameConflict(std::shared_ptr<Macro> &);
|
||||
bool MacroTabIsInFocus();
|
||||
|
||||
enum class MacroSection {
|
||||
CONDITIONS,
|
||||
ACTIONS,
|
||||
};
|
||||
MacroSection lastInteracted = MacroSection::CONDITIONS;
|
||||
int currentConditionIdx = -1;
|
||||
int currentActionIdx = -1;
|
||||
int currentElseActionIdx = -1;
|
||||
|
||||
/* --- End of macro tab section --- */
|
||||
|
||||
|
||||
@@ -132,10 +132,9 @@ void AdvSceneSwitcher::closeEvent(QCloseEvent *)
|
||||
}
|
||||
switcher->windowPos = this->pos();
|
||||
switcher->windowSize = this->size();
|
||||
switcher->macroActionConditionSplitterPosition =
|
||||
ui->macroActionConditionSplitter->sizes();
|
||||
switcher->macroListMacroEditSplitterPosition =
|
||||
ui->macroListMacroEditSplitter->sizes();
|
||||
MacroSelectionAboutToChange(); // Trigger saving of splitter states
|
||||
|
||||
obs_frontend_save();
|
||||
}
|
||||
@@ -703,9 +702,7 @@ void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||
obs_data_set_int(obj, "windowWidth", windowSize.width());
|
||||
obs_data_set_int(obj, "windowHeight", windowSize.height());
|
||||
|
||||
saveSplitterPos(macroActionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
saveSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
SaveSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
"macroListMacroEditSplitterPosition");
|
||||
}
|
||||
|
||||
@@ -759,9 +756,8 @@ void SwitcherData::LoadUISettings(obs_data_t *obj)
|
||||
(int)obs_data_get_int(obj, "windowPosY")};
|
||||
windowSize = {(int)obs_data_get_int(obj, "windowWidth"),
|
||||
(int)obs_data_get_int(obj, "windowHeight")};
|
||||
loadSplitterPos(macroActionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
loadSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
|
||||
LoadSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
"macroListMacroEditSplitterPosition");
|
||||
}
|
||||
|
||||
|
||||
@@ -322,6 +322,7 @@ void AdvSceneSwitcher::on_actionUp_clicked()
|
||||
MoveMacroActionUp(currentActionIdx);
|
||||
MacroActionSelectionChanged(currentActionIdx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionDown_clicked()
|
||||
{
|
||||
if (currentActionIdx == -1 ||
|
||||
@@ -342,6 +343,77 @@ void AdvSceneSwitcher::on_actionBottom_clicked()
|
||||
MacroActionSelectionChanged(newIdx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionAdd_clicked()
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentElseActionIdx == -1) {
|
||||
AddMacroElseAction((int)macro->ElseActions().size());
|
||||
} else {
|
||||
AddMacroElseAction(currentElseActionIdx + 1);
|
||||
}
|
||||
if (currentElseActionIdx != -1) {
|
||||
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
|
||||
}
|
||||
ui->elseActionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionRemove_clicked()
|
||||
{
|
||||
if (currentElseActionIdx == -1) {
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
RemoveMacroElseAction((int)macro->Actions().size() - 1);
|
||||
} else {
|
||||
RemoveMacroElseAction(currentElseActionIdx);
|
||||
}
|
||||
MacroElseActionSelectionChanged(-1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionTop_clicked()
|
||||
{
|
||||
if (currentElseActionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
MacroElseActionReorder(0, currentElseActionIdx);
|
||||
MacroElseActionSelectionChanged(0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionUp_clicked()
|
||||
{
|
||||
if (currentElseActionIdx == -1 || currentElseActionIdx == 0) {
|
||||
return;
|
||||
}
|
||||
MoveMacroElseActionUp(currentElseActionIdx);
|
||||
MacroElseActionSelectionChanged(currentElseActionIdx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionDown_clicked()
|
||||
{
|
||||
if (currentElseActionIdx == -1 ||
|
||||
currentElseActionIdx ==
|
||||
ui->elseActionsList->ContentLayout()->count() - 1) {
|
||||
return;
|
||||
}
|
||||
MoveMacroElseActionDown(currentElseActionIdx);
|
||||
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionBottom_clicked()
|
||||
{
|
||||
if (currentElseActionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
const int newIdx = ui->elseActionsList->ContentLayout()->count() - 1;
|
||||
MacroElseActionReorder(newIdx, currentElseActionIdx);
|
||||
MacroElseActionSelectionChanged(newIdx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
||||
{
|
||||
if (pos1 == pos2) {
|
||||
@@ -394,24 +466,158 @@ void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
||||
HighlightAction(idx + 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
||||
void AdvSceneSwitcher::MacroElseActionSelectionChanged(int idx)
|
||||
{
|
||||
SetupMacroSegmentSelection(MacroSection::ELSE_ACTIONS, idx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroElseActionReorder(int to, int from)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui->actionsList->SetSelection(idx);
|
||||
ui->conditionsList->SetSelection(-1);
|
||||
|
||||
if (idx < 0 || (unsigned)idx >= macro->Actions().size()) {
|
||||
currentActionIdx = -1;
|
||||
} else {
|
||||
currentActionIdx = idx;
|
||||
lastInteracted = MacroSection::ACTIONS;
|
||||
if (to == from || from < 0 || from > (int)macro->ElseActions().size() ||
|
||||
to < 0 || to > (int)macro->ElseActions().size()) {
|
||||
return;
|
||||
}
|
||||
currentConditionIdx = -1;
|
||||
HighlightControls();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
auto action = macro->ElseActions().at(from);
|
||||
macro->ElseActions().erase(macro->ElseActions().begin() + from);
|
||||
macro->ElseActions().insert(macro->ElseActions().begin() + to,
|
||||
action);
|
||||
macro->UpdateElseActionIndices();
|
||||
ui->elseActionsList->ContentLayout()->insertItem(
|
||||
to, ui->elseActionsList->ContentLayout()->takeAt(from));
|
||||
SetElseActionData(*macro);
|
||||
}
|
||||
HighlightElseAction(to);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::AddMacroElseAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string id;
|
||||
if (idx - 1 >= 0) {
|
||||
id = macro->ElseActions().at(idx - 1)->GetId();
|
||||
} else {
|
||||
MacroActionSwitchScene temp(nullptr);
|
||||
id = temp.GetId();
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
macro->ElseActions().emplace(
|
||||
macro->ElseActions().begin() + idx,
|
||||
MacroActionFactory::Create(id, macro.get()));
|
||||
if (idx - 1 >= 0) {
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
macro->ElseActions().at(idx - 1)->Save(data);
|
||||
macro->ElseActions().at(idx)->Load(data);
|
||||
}
|
||||
macro->UpdateElseActionIndices();
|
||||
ui->elseActionsList->Insert(
|
||||
idx, new MacroActionEdit(
|
||||
this, ¯o->ElseActions()[idx], id));
|
||||
SetElseActionData(*macro);
|
||||
}
|
||||
HighlightElseAction(idx);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= (int)macro->ElseActions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
ui->elseActionsList->Remove(idx);
|
||||
macro->ElseActions().erase(macro->ElseActions().begin() + idx);
|
||||
switcher->abortMacroWait = true;
|
||||
switcher->macroWaitCv.notify_all();
|
||||
macro->UpdateElseActionIndices();
|
||||
SetActionData(*macro);
|
||||
}
|
||||
MacroElseActionSelectionChanged(-1);
|
||||
lastInteracted = MacroSection::ELSE_ACTIONS;
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SwapElseActions(Macro *m, int pos1, int pos2)
|
||||
{
|
||||
if (pos1 == pos2) {
|
||||
return;
|
||||
}
|
||||
if (pos1 > pos2) {
|
||||
std::swap(pos1, pos2);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
iter_swap(m->ElseActions().begin() + pos1,
|
||||
m->ElseActions().begin() + pos2);
|
||||
m->UpdateElseActionIndices();
|
||||
auto widget1 = static_cast<MacroActionEdit *>(
|
||||
ui->elseActionsList->ContentLayout()->takeAt(pos1)->widget());
|
||||
auto widget2 = static_cast<MacroActionEdit *>(
|
||||
ui->elseActionsList->ContentLayout()
|
||||
->takeAt(pos2 - 1)
|
||||
->widget());
|
||||
ui->elseActionsList->Insert(pos1, widget2);
|
||||
ui->elseActionsList->Insert(pos2, widget1);
|
||||
SetElseActionData(*m);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroElseActionUp(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 1 || idx >= (int)macro->ElseActions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwapElseActions(macro.get(), idx, idx - 1);
|
||||
HighlightElseAction(idx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MoveMacroElseActionDown(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= (int)macro->ElseActions().size() - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwapElseActions(macro.get(), idx, idx + 1);
|
||||
HighlightElseAction(idx + 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
||||
{
|
||||
SetupMacroSegmentSelection(MacroSection::ACTIONS, idx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
||||
|
||||
@@ -564,22 +564,7 @@ void AdvSceneSwitcher::MoveMacroConditionDown(int idx)
|
||||
|
||||
void AdvSceneSwitcher::MacroConditionSelectionChanged(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui->conditionsList->SetSelection(idx);
|
||||
ui->actionsList->SetSelection(-1);
|
||||
|
||||
if (idx < 0 || (unsigned)idx >= macro->Conditions().size()) {
|
||||
currentConditionIdx = -1;
|
||||
} else {
|
||||
currentConditionIdx = idx;
|
||||
lastInteracted = MacroSection::CONDITIONS;
|
||||
}
|
||||
currentActionIdx = -1;
|
||||
HighlightControls();
|
||||
SetupMacroSegmentSelection(MacroSection::CONDITIONS, idx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroConditionReorder(int to, int from)
|
||||
|
||||
@@ -253,6 +253,76 @@ void AdvSceneSwitcher::ExportMacros()
|
||||
MacroExportImportDialog::ExportMacros(exportString);
|
||||
}
|
||||
|
||||
static bool
|
||||
isValidMacroSegmentIdx(const std::deque<std::shared_ptr<MacroSegment>> &list,
|
||||
int idx)
|
||||
{
|
||||
return (idx > 0 || (unsigned)idx < list.size());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupMacroSegmentSelection(MacroSection type, int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
MacroSegmentList *setList, *resetList1, *resetList2;
|
||||
int *setIdx, *resetIdx1, *resetIdx2;
|
||||
std::deque<std::shared_ptr<MacroSegment>> segements;
|
||||
|
||||
switch (type) {
|
||||
case AdvSceneSwitcher::MacroSection::CONDITIONS:
|
||||
setList = ui->conditionsList;
|
||||
setIdx = ¤tConditionIdx;
|
||||
segements = {macro->Conditions().begin(),
|
||||
macro->Conditions().end()};
|
||||
|
||||
resetList1 = ui->actionsList;
|
||||
resetList2 = ui->elseActionsList;
|
||||
resetIdx1 = ¤tActionIdx;
|
||||
resetIdx2 = ¤tElseActionIdx;
|
||||
break;
|
||||
case AdvSceneSwitcher::MacroSection::ACTIONS:
|
||||
setList = ui->actionsList;
|
||||
setIdx = ¤tActionIdx;
|
||||
segements = {macro->Actions().begin(), macro->Actions().end()};
|
||||
|
||||
resetList1 = ui->conditionsList;
|
||||
resetList2 = ui->elseActionsList;
|
||||
resetIdx1 = ¤tConditionIdx;
|
||||
resetIdx2 = ¤tElseActionIdx;
|
||||
break;
|
||||
case AdvSceneSwitcher::MacroSection::ELSE_ACTIONS:
|
||||
setList = ui->elseActionsList;
|
||||
setIdx = ¤tElseActionIdx;
|
||||
segements = {macro->ElseActions().begin(),
|
||||
macro->ElseActions().end()};
|
||||
|
||||
resetList1 = ui->actionsList;
|
||||
resetList2 = ui->conditionsList;
|
||||
resetIdx1 = ¤tActionIdx;
|
||||
resetIdx2 = ¤tConditionIdx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setList->SetSelection(idx);
|
||||
resetList1->SetSelection(-1);
|
||||
resetList2->SetSelection(-1);
|
||||
if (isValidMacroSegmentIdx(segements, idx)) {
|
||||
*setIdx = idx;
|
||||
} else {
|
||||
*setIdx = -1;
|
||||
}
|
||||
*resetIdx1 = -1;
|
||||
*resetIdx2 = -1;
|
||||
|
||||
lastInteracted = type;
|
||||
HighlightControls();
|
||||
}
|
||||
|
||||
bool AdvSceneSwitcher::ResolveMacroImportNameConflict(
|
||||
std::shared_ptr<Macro> ¯o)
|
||||
{
|
||||
@@ -427,6 +497,17 @@ void AdvSceneSwitcher::PopulateMacroActions(Macro &m, uint32_t afterIdx)
|
||||
ui->actionsList->SetHelpMsgVisible(actions.size() == 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::PopulateMacroElseActions(Macro &m, uint32_t afterIdx)
|
||||
{
|
||||
auto &actions = m.ElseActions();
|
||||
for (; afterIdx < actions.size(); afterIdx++) {
|
||||
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
|
||||
actions[afterIdx]->GetId());
|
||||
ui->elseActionsList->Add(newEntry);
|
||||
}
|
||||
ui->elseActionsList->SetHelpMsgVisible(actions.size() == 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx)
|
||||
{
|
||||
bool root = afterIdx == 0;
|
||||
@@ -458,6 +539,23 @@ void AdvSceneSwitcher::SetActionData(Macro &m)
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetElseActionData(Macro &m)
|
||||
{
|
||||
auto &actions = m.ElseActions();
|
||||
for (int idx = 0; idx < ui->elseActionsList->ContentLayout()->count();
|
||||
idx++) {
|
||||
auto item = ui->elseActionsList->ContentLayout()->itemAt(idx);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
auto widget = static_cast<MacroActionEdit *>(item->widget());
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
widget->SetEntryData(&*(actions.begin() + idx));
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetConditionData(Macro &m)
|
||||
{
|
||||
auto &conditions = m.Conditions();
|
||||
@@ -475,6 +573,21 @@ void AdvSceneSwitcher::SetConditionData(Macro &m)
|
||||
}
|
||||
}
|
||||
|
||||
static void maximizeFirstSplitterEntry(QSplitter *splitter)
|
||||
{
|
||||
QList<int> newSizes;
|
||||
newSizes << 999999;
|
||||
for (int i = 0; i < splitter->sizes().size() - 1; i++) {
|
||||
newSizes << 0;
|
||||
}
|
||||
splitter->setSizes(newSizes);
|
||||
}
|
||||
|
||||
static void centerSplitterPosition(QSplitter *splitter)
|
||||
{
|
||||
splitter->setSizes(QList<int>() << 999999 << 999999);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetEditMacro(Macro &m)
|
||||
{
|
||||
{
|
||||
@@ -487,20 +600,38 @@ void AdvSceneSwitcher::SetEditMacro(Macro &m)
|
||||
}
|
||||
ui->conditionsList->Clear();
|
||||
ui->actionsList->Clear();
|
||||
ui->elseActionsList->Clear();
|
||||
|
||||
m.ResetUIHelpers();
|
||||
|
||||
PopulateMacroConditions(m);
|
||||
PopulateMacroActions(m);
|
||||
PopulateMacroElseActions(m);
|
||||
SetMacroEditAreaDisabled(false);
|
||||
|
||||
currentActionIdx = -1;
|
||||
currentElseActionIdx = -1;
|
||||
currentConditionIdx = -1;
|
||||
HighlightControls();
|
||||
|
||||
if (m.IsGroup()) {
|
||||
SetMacroEditAreaDisabled(true);
|
||||
ui->macroName->setEnabled(true);
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
return;
|
||||
}
|
||||
|
||||
currentActionIdx = -1;
|
||||
currentConditionIdx = -1;
|
||||
HighlightControls();
|
||||
if (!m.HasValidSplitterPositions()) {
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
return;
|
||||
}
|
||||
|
||||
ui->macroActionConditionSplitter->setSizes(
|
||||
m.GetActionConditionSplitterPosition());
|
||||
ui->macroElseActionSplitter->setSizes(
|
||||
m.GetElseActionSplitterPosition());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable)
|
||||
@@ -519,6 +650,11 @@ void AdvSceneSwitcher::HighlightAction(int idx, QColor color)
|
||||
ui->actionsList->Highlight(idx, color);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::HighlightElseAction(int idx, QColor color)
|
||||
{
|
||||
ui->elseActionsList->Highlight(idx, color);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::HighlightCondition(int idx, QColor color)
|
||||
{
|
||||
ui->conditionsList->Highlight(idx, color);
|
||||
@@ -534,6 +670,33 @@ std::vector<std::shared_ptr<Macro>> AdvSceneSwitcher::GetSelectedMacros()
|
||||
return ui->macros->GetCurrentMacros();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroSelectionAboutToChange()
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto macro = GetMacroByQString(ui->macroName->text());
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
macro->SetActionConditionSplitterPosition(
|
||||
ui->macroActionConditionSplitter->sizes());
|
||||
|
||||
auto elsePos = ui->macroElseActionSplitter->sizes();
|
||||
// If only conditions are visible maximize the actions to avoid neither
|
||||
// actions nor elseActions being visible when the condition <-> action
|
||||
// splitter is moved
|
||||
if (elsePos[0] == 0 && elsePos[1] == 0) {
|
||||
macro->SetElseActionSplitterPosition(QList<int>()
|
||||
<< 999999 << 0);
|
||||
return;
|
||||
}
|
||||
macro->SetElseActionSplitterPosition(
|
||||
ui->macroElseActionSplitter->sizes());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroSelectionChanged()
|
||||
{
|
||||
if (loading) {
|
||||
@@ -545,8 +708,12 @@ void AdvSceneSwitcher::MacroSelectionChanged()
|
||||
SetMacroEditAreaDisabled(true);
|
||||
ui->conditionsList->Clear();
|
||||
ui->actionsList->Clear();
|
||||
ui->elseActionsList->Clear();
|
||||
ui->conditionsList->SetHelpMsgVisible(true);
|
||||
ui->actionsList->SetHelpMsgVisible(true);
|
||||
ui->elseActionsList->SetHelpMsgVisible(true);
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
return;
|
||||
}
|
||||
SetEditMacro(*macro);
|
||||
@@ -584,8 +751,19 @@ void AdvSceneSwitcher::on_macroProperties_clicked()
|
||||
emit HighlightConditionsChanged(prop._highlightConditions);
|
||||
}
|
||||
|
||||
// Don't restore splitter pos if an element is not visible at all
|
||||
bool shouldResotreSplitterPos(const QList<int> &pos)
|
||||
static void moveControlsToSplitter(QSplitter *splitter, int idx,
|
||||
QLayoutItem *item)
|
||||
{
|
||||
static int splitterHandleWidth = 38;
|
||||
auto handle = splitter->handle(idx);
|
||||
auto layout = item->layout();
|
||||
layout->setContentsMargins(7, 7, 7, 7);
|
||||
handle->setLayout(layout);
|
||||
splitter->setHandleWidth(splitterHandleWidth);
|
||||
splitter->setStyleSheet("QSplitter::handle {background: transparent;}");
|
||||
}
|
||||
|
||||
bool shouldRestoreSplitter(const QList<int> &pos)
|
||||
{
|
||||
if (pos.size() == 0) {
|
||||
return false;
|
||||
@@ -606,6 +784,8 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
}
|
||||
ui->macros->Reset(switcher->macros,
|
||||
switcher->macroProperties._highlightExecuted);
|
||||
connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this,
|
||||
SLOT(MacroSelectionAboutToChange()));
|
||||
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
||||
SLOT(MacroSelectionChanged()));
|
||||
|
||||
@@ -623,12 +803,22 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
connect(ui->actionsList, &MacroSegmentList::Reorder, this,
|
||||
&AdvSceneSwitcher::MacroActionReorder);
|
||||
|
||||
ui->elseActionsList->SetHelpMsg(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.editElseActionHelp"));
|
||||
connect(ui->elseActionsList, &MacroSegmentList::SelectionChagned, this,
|
||||
&AdvSceneSwitcher::MacroElseActionSelectionChanged);
|
||||
connect(ui->elseActionsList, &MacroSegmentList::Reorder, this,
|
||||
&AdvSceneSwitcher::MacroElseActionReorder);
|
||||
|
||||
ui->macros->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->macros, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroContextMenu);
|
||||
ui->actionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->actionsList, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroActionsContextMenu);
|
||||
ui->elseActionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->elseActionsList, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroElseActionsContextMenu);
|
||||
ui->conditionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->conditionsList, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroConditionsContextMenu);
|
||||
@@ -643,16 +833,10 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
onChangeHighlightTimer.start();
|
||||
|
||||
// Move condition controls into splitter handle layout
|
||||
auto handle = ui->macroActionConditionSplitter->handle(1);
|
||||
auto item = ui->macroConditionsLayout->takeAt(1);
|
||||
if (item) {
|
||||
auto layout = item->layout();
|
||||
layout->setContentsMargins(7, 7, 7, 7);
|
||||
handle->setLayout(layout);
|
||||
ui->macroActionConditionSplitter->setHandleWidth(38);
|
||||
}
|
||||
ui->macroActionConditionSplitter->setStyleSheet(
|
||||
"QSplitter::handle {background: transparent;}");
|
||||
moveControlsToSplitter(ui->macroActionConditionSplitter, 1,
|
||||
ui->macroConditionsLayout->takeAt(1));
|
||||
moveControlsToSplitter(ui->macroElseActionSplitter, 1,
|
||||
ui->macroActionsLayout->takeAt(1));
|
||||
|
||||
// Set action and condition control icons
|
||||
const std::string pathPrefix =
|
||||
@@ -660,6 +844,9 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
SetButtonIcon(ui->actionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
||||
SetButtonIcon(ui->actionBottom,
|
||||
(pathPrefix + "DoubleDown.svg").c_str());
|
||||
SetButtonIcon(ui->elseActionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
||||
SetButtonIcon(ui->elseActionBottom,
|
||||
(pathPrefix + "DoubleDown.svg").c_str());
|
||||
SetButtonIcon(ui->conditionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
||||
SetButtonIcon(ui->conditionBottom,
|
||||
(pathPrefix + "DoubleDown.svg").c_str());
|
||||
@@ -668,13 +855,11 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
ui->macroListMacroEditSplitter->setStretchFactor(0, 1);
|
||||
ui->macroListMacroEditSplitter->setStretchFactor(1, 4);
|
||||
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
|
||||
if (switcher->saveWindowGeo) {
|
||||
if (shouldResotreSplitterPos(
|
||||
switcher->macroActionConditionSplitterPosition)) {
|
||||
ui->macroActionConditionSplitter->setSizes(
|
||||
switcher->macroActionConditionSplitterPosition);
|
||||
}
|
||||
if (shouldResotreSplitterPos(
|
||||
if (shouldRestoreSplitter(
|
||||
switcher->macroListMacroEditSplitterPosition)) {
|
||||
ui->macroListMacroEditSplitter->setSizes(
|
||||
switcher->macroListMacroEditSplitterPosition);
|
||||
@@ -732,34 +917,49 @@ void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||
menu.exec(globalPos);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
||||
static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
||||
std::function<void(AdvSceneSwitcher *)> expand,
|
||||
std::function<void(AdvSceneSwitcher *)> collapse,
|
||||
std::function<void(AdvSceneSwitcher *)> maximize,
|
||||
std::function<void(AdvSceneSwitcher *)> minimize)
|
||||
{
|
||||
QPoint globalPos = ui->actionsList->mapToGlobal(pos);
|
||||
QMenu menu;
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
||||
this, &AdvSceneSwitcher::ExpandAllActions);
|
||||
ss, [ss, expand]() { expand(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
|
||||
this, &AdvSceneSwitcher::CollapseAllActions);
|
||||
ss, [ss, collapse]() { collapse(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
|
||||
this, &AdvSceneSwitcher::MinimizeConditions);
|
||||
ss, [ss, maximize]() { maximize(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
|
||||
this, &AdvSceneSwitcher::MinimizeActions);
|
||||
menu.exec(globalPos);
|
||||
ss, [ss, minimize]() { minimize(ss); });
|
||||
menu.exec(pos);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
setupConextMenu(this, ui->actionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllActions,
|
||||
&AdvSceneSwitcher::CollapseAllActions,
|
||||
&AdvSceneSwitcher::MaximizeActions,
|
||||
&AdvSceneSwitcher::MinimizeActions);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroElseActionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
setupConextMenu(this, ui->elseActionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllElseActions,
|
||||
&AdvSceneSwitcher::CollapseAllElseActions,
|
||||
&AdvSceneSwitcher::MaximizeElseActions,
|
||||
&AdvSceneSwitcher::MinimizeElseActions);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroConditionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
QPoint globalPos = ui->conditionsList->mapToGlobal(pos);
|
||||
QMenu menu;
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
||||
this, &AdvSceneSwitcher::ExpandAllConditions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
|
||||
this, &AdvSceneSwitcher::CollapseAllConditions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
|
||||
this, &AdvSceneSwitcher::MinimizeActions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
|
||||
this, &AdvSceneSwitcher::MinimizeConditions);
|
||||
menu.exec(globalPos);
|
||||
setupConextMenu(this, ui->conditionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllConditions,
|
||||
&AdvSceneSwitcher::CollapseAllConditions,
|
||||
&AdvSceneSwitcher::MaximizeConditions,
|
||||
&AdvSceneSwitcher::MinimizeConditions);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CopyMacro()
|
||||
@@ -789,60 +989,103 @@ void AdvSceneSwitcher::CopyMacro()
|
||||
emit MacroAdded(QString::fromStdString(name));
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllActions()
|
||||
void setCollapsedHelper(const std::shared_ptr<Macro> &m, MacroSegmentList *list,
|
||||
bool collapsed)
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
ui->actionsList->SetCollapsed(false);
|
||||
list->SetCollapsed(collapsed);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllActions()
|
||||
{
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->actionsList, false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllElseActions()
|
||||
{
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->elseActionsList, false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllConditions()
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
ui->conditionsList->SetCollapsed(false);
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->conditionsList, false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CollapseAllActions()
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
ui->actionsList->SetCollapsed(true);
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->actionsList, true);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CollapseAllElseActions()
|
||||
{
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->elseActionsList, true);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CollapseAllConditions()
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
ui->conditionsList->SetCollapsed(true);
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->conditionsList, true);
|
||||
}
|
||||
|
||||
static void reduceSizeOfSplitterIdx(QSplitter *splitter, int idx)
|
||||
{
|
||||
auto sizes = splitter->sizes();
|
||||
int sum = sizes[0] + sizes[1];
|
||||
int reducedSize = sum / 10;
|
||||
sizes[idx] = reducedSize;
|
||||
sizes[(idx + 1) % 2] = sum - reducedSize;
|
||||
splitter->setSizes(sizes);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MinimizeActions()
|
||||
{
|
||||
QList<int> sizes = ui->macroActionConditionSplitter->sizes();
|
||||
int sum = sizes[0] + sizes[1];
|
||||
int actionsHeight = sum / 10;
|
||||
sizes[1] = actionsHeight;
|
||||
sizes[0] = sum - actionsHeight;
|
||||
ui->macroActionConditionSplitter->setSizes(sizes);
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
if (macro->ElseActions().size() == 0) {
|
||||
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 1);
|
||||
} else {
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MaximizeActions()
|
||||
{
|
||||
MinimizeElseActions();
|
||||
MinimizeConditions();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MinimizeElseActions()
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
if (macro->ElseActions().size() == 0) {
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
} else {
|
||||
reduceSizeOfSplitterIdx(ui->macroElseActionSplitter, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MaximizeElseActions()
|
||||
{
|
||||
MinimizeConditions();
|
||||
reduceSizeOfSplitterIdx(ui->macroElseActionSplitter, 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MinimizeConditions()
|
||||
{
|
||||
QList<int> sizes = ui->macroActionConditionSplitter->sizes();
|
||||
int sum = sizes[0] + sizes[1];
|
||||
int conditionsHeight = sum / 10;
|
||||
sizes[0] = conditionsHeight;
|
||||
sizes[1] = sum - conditionsHeight;
|
||||
ui->macroActionConditionSplitter->setSizes(sizes);
|
||||
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MaximizeConditions()
|
||||
{
|
||||
MinimizeElseActions();
|
||||
MinimizeActions();
|
||||
}
|
||||
|
||||
bool AdvSceneSwitcher::MacroTabIsInFocus()
|
||||
|
||||
@@ -1260,6 +1260,7 @@ void MacroTree::UngroupSelectedGroups()
|
||||
void MacroTree::SelectionChangedHelper(const QItemSelection &,
|
||||
const QItemSelection &)
|
||||
{
|
||||
emit MacroSelectionAboutToChange();
|
||||
emit MacroSelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +142,7 @@ public slots:
|
||||
const QItemSelection &);
|
||||
|
||||
signals:
|
||||
void MacroSelectionAboutToChange();
|
||||
void MacroSelectionChanged();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -176,14 +176,11 @@ bool Macro::CeckMatch()
|
||||
}
|
||||
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
||||
|
||||
bool matchedBeforeOnChangeCheck = _matched;
|
||||
if (_matched && _matchOnChange && _lastMatched) {
|
||||
vblog(LOG_INFO, "ignore match for Macro %s (on change)",
|
||||
_name.c_str());
|
||||
_matched = false;
|
||||
SetOnChangeHighlight();
|
||||
_conditionSateChanged = _lastMatched != _matched;
|
||||
if (!_conditionSateChanged) {
|
||||
_onPreventedActionExecution = true;
|
||||
}
|
||||
_lastMatched = matchedBeforeOnChangeCheck;
|
||||
_lastMatched = _matched;
|
||||
_lastCheckTime = std::chrono::high_resolution_clock::now();
|
||||
return _matched;
|
||||
}
|
||||
@@ -223,6 +220,28 @@ bool Macro::ExecutedSince(
|
||||
return _lastExecutionTime > time;
|
||||
}
|
||||
|
||||
bool Macro::ShouldRunActions() const
|
||||
{
|
||||
const bool hasActionsToExecute =
|
||||
(_matched || _elseActions.size() > 0) &&
|
||||
(!_performActionsOnChange || _conditionSateChanged);
|
||||
|
||||
if (VerboseLoggingEnabled() && _performActionsOnChange &&
|
||||
!_conditionSateChanged) {
|
||||
if (_matched && _actions.size() > 0) {
|
||||
blog(LOG_INFO, "skip actions for Macro %s (on change)",
|
||||
_name.c_str());
|
||||
}
|
||||
if (!_matched && _elseActions.size() > 0) {
|
||||
blog(LOG_INFO,
|
||||
"skip else actions for Macro %s (on change)",
|
||||
_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return hasActionsToExecute;
|
||||
}
|
||||
|
||||
int64_t Macro::MsSinceLastCheck() const
|
||||
{
|
||||
if (_lastCheckTime.time_since_epoch().count() == 0) {
|
||||
@@ -254,20 +273,24 @@ void Macro::ResetTimers()
|
||||
void Macro::RunActions(bool &retVal, bool ignorePause)
|
||||
{
|
||||
bool ret = true;
|
||||
for (auto &a : _actions) {
|
||||
if (a->Enabled()) {
|
||||
a->LogAction();
|
||||
ret = ret && a->PerformAction();
|
||||
const std::deque<std::shared_ptr<MacroAction>> &actionsToExecute =
|
||||
_matched ? _actions : _elseActions;
|
||||
vblog(LOG_INFO, "running %sactions of %s", _matched ? "" : "else ",
|
||||
_name.c_str());
|
||||
for (auto &action : actionsToExecute) {
|
||||
if (action->Enabled()) {
|
||||
action->LogAction();
|
||||
ret = ret && action->PerformAction();
|
||||
} else {
|
||||
vblog(LOG_INFO, "skipping disabled action %s",
|
||||
a->GetId().c_str());
|
||||
action->GetId().c_str());
|
||||
}
|
||||
if (!ret || (_paused && !ignorePause) || _stop || _die) {
|
||||
retVal = ret;
|
||||
break;
|
||||
}
|
||||
if (a->Enabled()) {
|
||||
a->SetHighlight();
|
||||
if (action->Enabled()) {
|
||||
action->SetHighlight();
|
||||
}
|
||||
}
|
||||
_done = true;
|
||||
@@ -279,16 +302,16 @@ void Macro::RunActions(bool ignorePause)
|
||||
RunActions(unused, ignorePause);
|
||||
}
|
||||
|
||||
void Macro::SetOnChangeHighlight()
|
||||
{
|
||||
_onChangeTriggered = true;
|
||||
}
|
||||
|
||||
bool Macro::DockIsVisible() const
|
||||
{
|
||||
return _dock && _dockAction && _dock->isVisible();
|
||||
}
|
||||
|
||||
void Macro::SetMatchOnChange(bool onChange)
|
||||
{
|
||||
_performActionsOnChange = onChange;
|
||||
}
|
||||
|
||||
void Macro::SetPaused(bool pause)
|
||||
{
|
||||
if (_paused && !pause) {
|
||||
@@ -332,22 +355,39 @@ std::deque<std::shared_ptr<MacroAction>> &Macro::Actions()
|
||||
return _actions;
|
||||
}
|
||||
|
||||
void Macro::UpdateActionIndices()
|
||||
std::deque<std::shared_ptr<MacroAction>> &Macro::ElseActions()
|
||||
{
|
||||
return _elseActions;
|
||||
}
|
||||
|
||||
static void updateIndicesHelper(std::deque<std::shared_ptr<MacroSegment>> &list)
|
||||
{
|
||||
int idx = 0;
|
||||
for (auto a : _actions) {
|
||||
a->SetIndex(idx);
|
||||
for (auto segment : list) {
|
||||
segment->SetIndex(idx);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void Macro::UpdateActionIndices()
|
||||
{
|
||||
std::deque<std::shared_ptr<MacroSegment>> list(_actions.begin(),
|
||||
_actions.end());
|
||||
updateIndicesHelper(list);
|
||||
}
|
||||
|
||||
void Macro::UpdateElseActionIndices()
|
||||
{
|
||||
std::deque<std::shared_ptr<MacroSegment>> list(_elseActions.begin(),
|
||||
_elseActions.end());
|
||||
updateIndicesHelper(list);
|
||||
}
|
||||
|
||||
void Macro::UpdateConditionIndices()
|
||||
{
|
||||
int idx = 0;
|
||||
for (auto c : _conditions) {
|
||||
c->SetIndex(idx);
|
||||
idx++;
|
||||
}
|
||||
std::deque<std::shared_ptr<MacroSegment>> list(_conditions.begin(),
|
||||
_conditions.end());
|
||||
updateIndicesHelper(list);
|
||||
}
|
||||
|
||||
std::shared_ptr<Macro> Macro::Parent() const
|
||||
@@ -360,56 +400,57 @@ bool Macro::Save(obs_data_t *obj) const
|
||||
obs_data_set_string(obj, "name", _name.c_str());
|
||||
obs_data_set_bool(obj, "pause", _paused);
|
||||
obs_data_set_bool(obj, "parallel", _runInParallel);
|
||||
obs_data_set_bool(obj, "onChange", _matchOnChange);
|
||||
obs_data_set_bool(obj, "onChange", _performActionsOnChange);
|
||||
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
||||
|
||||
obs_data_set_bool(obj, "group", _isGroup);
|
||||
if (_isGroup) {
|
||||
auto groupData = obs_data_create();
|
||||
OBSDataAutoRelease groupData = obs_data_create();
|
||||
obs_data_set_bool(groupData, "collapsed", _isCollapsed);
|
||||
obs_data_set_int(groupData, "size", _groupSize);
|
||||
obs_data_set_obj(obj, "groupData", groupData);
|
||||
obs_data_release(groupData);
|
||||
return true;
|
||||
}
|
||||
|
||||
SaveDockSettings(obj);
|
||||
|
||||
SaveSplitterPos(_actionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
SaveSplitterPos(_elseActionSplitterPosition, obj,
|
||||
"macroElseActionSplitterPosition");
|
||||
|
||||
obs_data_set_bool(obj, "registerHotkeys", _registerHotkeys);
|
||||
obs_data_array_t *pauseHotkey = obs_hotkey_save(_pauseHotkey);
|
||||
OBSDataArrayAutoRelease pauseHotkey = obs_hotkey_save(_pauseHotkey);
|
||||
obs_data_set_array(obj, "pauseHotkey", pauseHotkey);
|
||||
obs_data_array_release(pauseHotkey);
|
||||
obs_data_array_t *unpauseHotkey = obs_hotkey_save(_unpauseHotkey);
|
||||
OBSDataArrayAutoRelease unpauseHotkey = obs_hotkey_save(_unpauseHotkey);
|
||||
obs_data_set_array(obj, "unpauseHotkey", unpauseHotkey);
|
||||
obs_data_array_release(unpauseHotkey);
|
||||
obs_data_array_t *togglePauseHotkey =
|
||||
OBSDataArrayAutoRelease togglePauseHotkey =
|
||||
obs_hotkey_save(_togglePauseHotkey);
|
||||
obs_data_set_array(obj, "togglePauseHotkey", togglePauseHotkey);
|
||||
obs_data_array_release(togglePauseHotkey);
|
||||
|
||||
obs_data_array_t *conditions = obs_data_array_create();
|
||||
OBSDataArrayAutoRelease conditions = obs_data_array_create();
|
||||
for (auto &c : _conditions) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
c->Save(array_obj);
|
||||
obs_data_array_push_back(conditions, array_obj);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
OBSDataAutoRelease arrayObj = obs_data_create();
|
||||
c->Save(arrayObj);
|
||||
obs_data_array_push_back(conditions, arrayObj);
|
||||
}
|
||||
obs_data_set_array(obj, "conditions", conditions);
|
||||
obs_data_array_release(conditions);
|
||||
|
||||
obs_data_array_t *actions = obs_data_array_create();
|
||||
OBSDataArrayAutoRelease actions = obs_data_array_create();
|
||||
for (auto &a : _actions) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
a->Save(array_obj);
|
||||
obs_data_array_push_back(actions, array_obj);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
OBSDataAutoRelease arrayObj = obs_data_create();
|
||||
a->Save(arrayObj);
|
||||
obs_data_array_push_back(actions, arrayObj);
|
||||
}
|
||||
obs_data_set_array(obj, "actions", actions);
|
||||
obs_data_array_release(actions);
|
||||
|
||||
OBSDataArrayAutoRelease elseActions = obs_data_array_create();
|
||||
for (auto &a : _elseActions) {
|
||||
OBSDataAutoRelease arrayObj = obs_data_create();
|
||||
a->Save(arrayObj);
|
||||
obs_data_array_push_back(elseActions, arrayObj);
|
||||
}
|
||||
obs_data_set_array(obj, "elseActions", elseActions);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -453,73 +494,69 @@ bool Macro::Load(obs_data_t *obj)
|
||||
_name = obs_data_get_string(obj, "name");
|
||||
_paused = obs_data_get_bool(obj, "pause");
|
||||
_runInParallel = obs_data_get_bool(obj, "parallel");
|
||||
_matchOnChange = obs_data_get_bool(obj, "onChange");
|
||||
_performActionsOnChange = obs_data_get_bool(obj, "onChange");
|
||||
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
||||
|
||||
_isGroup = obs_data_get_bool(obj, "group");
|
||||
if (_isGroup) {
|
||||
auto groupData = obs_data_get_obj(obj, "groupData");
|
||||
OBSDataAutoRelease groupData =
|
||||
obs_data_get_obj(obj, "groupData");
|
||||
_isCollapsed = obs_data_get_bool(groupData, "collapsed");
|
||||
_groupSize = obs_data_get_int(groupData, "size");
|
||||
obs_data_release(groupData);
|
||||
return true;
|
||||
}
|
||||
|
||||
LoadDockSettings(obj);
|
||||
|
||||
LoadSplitterPos(_actionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
LoadSplitterPos(_elseActionSplitterPosition, obj,
|
||||
"macroElseActionSplitterPosition");
|
||||
|
||||
obs_data_set_default_bool(obj, "registerHotkeys", true);
|
||||
_registerHotkeys = obs_data_get_bool(obj, "registerHotkeys");
|
||||
if (_registerHotkeys) {
|
||||
SetupHotkeys();
|
||||
}
|
||||
obs_data_array_t *pauseHotkey = obs_data_get_array(obj, "pauseHotkey");
|
||||
OBSDataArrayAutoRelease pauseHotkey =
|
||||
obs_data_get_array(obj, "pauseHotkey");
|
||||
obs_hotkey_load(_pauseHotkey, pauseHotkey);
|
||||
obs_data_array_release(pauseHotkey);
|
||||
obs_data_array_t *unpauseHotkey =
|
||||
OBSDataArrayAutoRelease unpauseHotkey =
|
||||
obs_data_get_array(obj, "unpauseHotkey");
|
||||
obs_hotkey_load(_unpauseHotkey, unpauseHotkey);
|
||||
obs_data_array_release(unpauseHotkey);
|
||||
obs_data_array_t *togglePauseHotkey =
|
||||
OBSDataArrayAutoRelease togglePauseHotkey =
|
||||
obs_data_get_array(obj, "togglePauseHotkey");
|
||||
obs_hotkey_load(_togglePauseHotkey, togglePauseHotkey);
|
||||
obs_data_array_release(togglePauseHotkey);
|
||||
SetHotkeysDesc();
|
||||
|
||||
bool root = true;
|
||||
obs_data_array_t *conditions = obs_data_get_array(obj, "conditions");
|
||||
OBSDataArrayAutoRelease conditions =
|
||||
obs_data_get_array(obj, "conditions");
|
||||
size_t count = obs_data_array_count(conditions);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(conditions, i);
|
||||
|
||||
std::string id = obs_data_get_string(array_obj, "id");
|
||||
|
||||
OBSDataAutoRelease arrayObj =
|
||||
obs_data_array_item(conditions, i);
|
||||
std::string id = obs_data_get_string(arrayObj, "id");
|
||||
auto newEntry = MacroConditionFactory::Create(id, this);
|
||||
if (newEntry) {
|
||||
_conditions.emplace_back(newEntry);
|
||||
auto c = _conditions.back().get();
|
||||
c->Load(array_obj);
|
||||
c->Load(arrayObj);
|
||||
setValidLogic(c, root, _name);
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"discarding condition entry with unknown id (%s) for macro %s",
|
||||
id.c_str(), _name.c_str());
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
root = false;
|
||||
}
|
||||
obs_data_array_release(conditions);
|
||||
UpdateConditionIndices();
|
||||
|
||||
obs_data_array_t *actions = obs_data_get_array(obj, "actions");
|
||||
OBSDataArrayAutoRelease actions = obs_data_get_array(obj, "actions");
|
||||
count = obs_data_array_count(actions);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(actions, i);
|
||||
|
||||
OBSDataAutoRelease array_obj = obs_data_array_item(actions, i);
|
||||
std::string id = obs_data_get_string(array_obj, "id");
|
||||
|
||||
auto newEntry = MacroActionFactory::Create(id, this);
|
||||
if (newEntry) {
|
||||
_actions.emplace_back(newEntry);
|
||||
@@ -529,11 +566,27 @@ bool Macro::Load(obs_data_t *obj)
|
||||
"discarding action entry with unknown id (%s) for macro %s",
|
||||
id.c_str(), _name.c_str());
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(actions);
|
||||
UpdateActionIndices();
|
||||
|
||||
OBSDataArrayAutoRelease elseActions =
|
||||
obs_data_get_array(obj, "elseActions");
|
||||
count = obs_data_array_count(elseActions);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
OBSDataAutoRelease array_obj =
|
||||
obs_data_array_item(elseActions, i);
|
||||
std::string id = obs_data_get_string(array_obj, "id");
|
||||
auto newEntry = MacroActionFactory::Create(id, this);
|
||||
if (newEntry) {
|
||||
_elseActions.emplace_back(newEntry);
|
||||
_elseActions.back()->Load(array_obj);
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"discarding elseAction entry with unknown id (%s) for macro %s",
|
||||
id.c_str(), _name.c_str());
|
||||
}
|
||||
}
|
||||
UpdateElseActionIndices();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -552,7 +605,12 @@ bool Macro::SwitchesScene() const
|
||||
{
|
||||
MacroActionSwitchScene temp(nullptr);
|
||||
auto sceneSwitchId = temp.GetId();
|
||||
for (auto &a : _actions) {
|
||||
for (const auto &a : _actions) {
|
||||
if (a->GetId() == sceneSwitchId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const auto &a : _elseActions) {
|
||||
if (a->GetId() == sceneSwitchId) {
|
||||
return true;
|
||||
}
|
||||
@@ -560,10 +618,36 @@ bool Macro::SwitchesScene() const
|
||||
return false;
|
||||
}
|
||||
|
||||
const QList<int> &Macro::GetActionConditionSplitterPosition() const
|
||||
{
|
||||
return _actionConditionSplitterPosition;
|
||||
}
|
||||
|
||||
void Macro::SetActionConditionSplitterPosition(const QList<int> sizes)
|
||||
{
|
||||
_actionConditionSplitterPosition = sizes;
|
||||
}
|
||||
|
||||
const QList<int> &Macro::GetElseActionSplitterPosition() const
|
||||
{
|
||||
return _elseActionSplitterPosition;
|
||||
}
|
||||
|
||||
void Macro::SetElseActionSplitterPosition(const QList<int> sizes)
|
||||
{
|
||||
_elseActionSplitterPosition = sizes;
|
||||
}
|
||||
|
||||
bool Macro::HasValidSplitterPositions() const
|
||||
{
|
||||
return !_actionConditionSplitterPosition.empty() &&
|
||||
!_elseActionSplitterPosition.empty();
|
||||
}
|
||||
|
||||
bool Macro::OnChangePreventedActionsRecently()
|
||||
{
|
||||
if (_onChangeTriggered) {
|
||||
_onChangeTriggered = false;
|
||||
if (_onPreventedActionExecution) {
|
||||
_onPreventedActionExecution = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -571,7 +655,7 @@ bool Macro::OnChangePreventedActionsRecently()
|
||||
|
||||
void Macro::ResetUIHelpers()
|
||||
{
|
||||
_onChangeTriggered = false;
|
||||
_onPreventedActionExecution = false;
|
||||
for (auto c : _conditions) {
|
||||
c->Highlight();
|
||||
}
|
||||
@@ -1014,7 +1098,7 @@ bool SwitcherData::CheckMacros()
|
||||
{
|
||||
bool ret = false;
|
||||
for (auto &m : macros) {
|
||||
if (m->CeckMatch()) {
|
||||
if (m->CeckMatch() || m->ElseActions().size() > 0) {
|
||||
ret = true;
|
||||
// This has to be performed here for now as actions are
|
||||
// not performed immediately after checking conditions.
|
||||
@@ -1049,7 +1133,7 @@ bool SwitcherData::RunMacros()
|
||||
}
|
||||
|
||||
for (auto &m : runPhaseMacros) {
|
||||
if (!m || !m->Matched()) {
|
||||
if (!m || !m->ShouldRunActions()) {
|
||||
continue;
|
||||
}
|
||||
if (firstInterval && m->SkipExecOnStart()) {
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
bool PerformActions(bool forceParallel = false,
|
||||
bool ignorePause = false);
|
||||
bool Matched() const { return _matched; }
|
||||
bool ShouldRunActions() const;
|
||||
int64_t MsSinceLastCheck() const;
|
||||
std::string Name() const { return _name; }
|
||||
void SetName(const std::string &name);
|
||||
@@ -35,8 +36,8 @@ public:
|
||||
bool RunInParallel() const { return _runInParallel; }
|
||||
void SetPaused(bool pause = true);
|
||||
bool Paused() const { return _paused; }
|
||||
void SetMatchOnChange(bool onChange) { _matchOnChange = onChange; }
|
||||
bool MatchOnChange() const { return _matchOnChange; }
|
||||
void SetMatchOnChange(bool onChange);
|
||||
bool MatchOnChange() const { return _performActionsOnChange; }
|
||||
void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; }
|
||||
bool SkipExecOnStart() const { return _skipExecOnStart; }
|
||||
int RunCount() const { return _runCount; };
|
||||
@@ -48,7 +49,9 @@ public:
|
||||
|
||||
std::deque<std::shared_ptr<MacroCondition>> &Conditions();
|
||||
std::deque<std::shared_ptr<MacroAction>> &Actions();
|
||||
std::deque<std::shared_ptr<MacroAction>> &ElseActions();
|
||||
void UpdateActionIndices();
|
||||
void UpdateElseActionIndices();
|
||||
void UpdateConditionIndices();
|
||||
|
||||
// Group controls
|
||||
@@ -80,6 +83,11 @@ public:
|
||||
bool SwitchesScene() const;
|
||||
|
||||
// UI helpers
|
||||
const QList<int> &GetActionConditionSplitterPosition() const;
|
||||
void SetActionConditionSplitterPosition(const QList<int>);
|
||||
const QList<int> &GetElseActionSplitterPosition() const;
|
||||
void SetElseActionSplitterPosition(const QList<int>);
|
||||
bool HasValidSplitterPositions() const;
|
||||
bool
|
||||
ExecutedSince(const std::chrono::high_resolution_clock::time_point &);
|
||||
bool OnChangePreventedActionsRecently();
|
||||
@@ -115,7 +123,6 @@ private:
|
||||
void SetHotkeysDesc() const;
|
||||
void RunActions(bool &ret, bool ignorePause);
|
||||
void RunActions(bool ignorePause);
|
||||
void SetOnChangeHighlight();
|
||||
bool DockIsVisible() const;
|
||||
void SetDockWidgetName() const;
|
||||
void SaveDockSettings(obs_data_t *obj) const;
|
||||
@@ -133,6 +140,7 @@ private:
|
||||
|
||||
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
||||
std::deque<std::shared_ptr<MacroAction>> _actions;
|
||||
std::deque<std::shared_ptr<MacroAction>> _elseActions;
|
||||
|
||||
std::weak_ptr<Macro> _parent;
|
||||
uint32_t _groupSize = 0;
|
||||
@@ -142,7 +150,8 @@ private:
|
||||
bool _runInParallel = false;
|
||||
bool _matched = false;
|
||||
bool _lastMatched = false;
|
||||
bool _matchOnChange = true;
|
||||
bool _conditionSateChanged = false;
|
||||
bool _performActionsOnChange = true;
|
||||
bool _skipExecOnStart = false;
|
||||
bool _paused = false;
|
||||
int _runCount = 0;
|
||||
@@ -151,7 +160,11 @@ private:
|
||||
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
bool _onChangeTriggered = false;
|
||||
// UI helpers
|
||||
bool _onPreventedActionExecution = false;
|
||||
|
||||
QList<int> _actionConditionSplitterPosition;
|
||||
QList<int> _elseActionSplitterPosition;
|
||||
|
||||
bool _registerDock = false;
|
||||
bool _dockHasRunButton = true;
|
||||
|
||||
@@ -214,7 +214,6 @@ public:
|
||||
bool saveWindowGeo = false;
|
||||
QPoint windowPos = {};
|
||||
QSize windowSize = {};
|
||||
QList<int> macroActionConditionSplitterPosition;
|
||||
QList<int> macroListMacroEditSplitterPosition;
|
||||
|
||||
/* --- End of UI section --- */
|
||||
|
||||
Reference in New Issue
Block a user