mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Add action trigger modes
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
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
* always -> same as old behavior, if "on change" was disabled * results changes -> same as old behavior, if "on change" was enabled * any condition changes * any condition changes and evaluates to true
This commit is contained in:
parent
d4425df694
commit
be8744f0d0
|
|
@ -76,7 +76,6 @@ AdvSceneSwitcher.macroTab.name="Name:"
|
||||||
AdvSceneSwitcher.macroTab.run="Makro ausführen"
|
AdvSceneSwitcher.macroTab.run="Makro ausführen"
|
||||||
AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt.\nSoll die aktuelle Ausführung gestoppt werden?"
|
AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt.\nSoll die aktuelle Ausführung gestoppt werden?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen"
|
AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen"
|
||||||
AdvSceneSwitcher.macroTab.onChange="Nur bei Änderung ausführen"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Gruppe %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Gruppe %1"
|
||||||
AdvSceneSwitcher.macroTab.removeGroupPopup.text="Sicher, dass \"%1\" und alle zugehörigen Elemente gelöscht werden?"
|
AdvSceneSwitcher.macroTab.removeGroupPopup.text="Sicher, dass \"%1\" und alle zugehörigen Elemente gelöscht werden?"
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,12 @@ AdvSceneSwitcher.macroTab.run.tooltip="Run all macro actions regardless of condi
|
||||||
AdvSceneSwitcher.macroTab.runElse="Run macro (else)"
|
AdvSceneSwitcher.macroTab.runElse="Run macro (else)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="Running \"%1\" failed!\nEither one of the actions failed or the macro is running already.\nDo you want to stop it?"
|
AdvSceneSwitcher.macroTab.runFail="Running \"%1\" failed!\nEither one of the actions failed or the macro is running already.\nDo you want to stop it?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Run macro in parallel to other macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Run macro in parallel to other macros"
|
||||||
AdvSceneSwitcher.macroTab.onChange="Perform actions only on condition change"
|
AdvSceneSwitcher.macroTab.actionTriggerMode.label="Perform actions:"
|
||||||
|
AdvSceneSwitcher.macroTab.actionTriggerMode.tooltip="Controls when the actions of this macro are performed.\n\n\"Always\" - actions are performed every time the conditions are met.\n\"Macro result changed\" - actions are only performed when the macro transitions between matching and not matching.\n\"Any condition changed\" - actions are only performed when any individual condition changes its result.\n\"Any condition triggered\" - actions are only performed when any individual condition changes from false to true."
|
||||||
|
AdvSceneSwitcher.macroTab.actionTriggerMode.always="always"
|
||||||
|
AdvSceneSwitcher.macroTab.actionTriggerMode.onOverallChange="only when result changes"
|
||||||
|
AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionChange="only when any condition changes"
|
||||||
|
AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionTriggered="only when any condition becomes true"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="The name \"%1\" is already used by a macro."
|
AdvSceneSwitcher.macroTab.macroNameExists="The name \"%1\" is already used by a macro."
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ AdvSceneSwitcher.macroTab.add="Agregar nueva macro"
|
||||||
AdvSceneSwitcher.macroTab.name="Nombre:"
|
AdvSceneSwitcher.macroTab.name="Nombre:"
|
||||||
AdvSceneSwitcher.macroTab.run="Ejecutar macro"
|
AdvSceneSwitcher.macroTab.run="Ejecutar macro"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
|
||||||
AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.copy="Crear copia"
|
AdvSceneSwitcher.macroTab.copy="Crear copia"
|
||||||
AdvSceneSwitcher.macroTab.expandAll="Expandir todo"
|
AdvSceneSwitcher.macroTab.expandAll="Expandir todo"
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,6 @@ AdvSceneSwitcher.macroTab.add="Ajouter une nouvelle macro"
|
||||||
AdvSceneSwitcher.macroTab.name="Nom :"
|
AdvSceneSwitcher.macroTab.name="Nom :"
|
||||||
AdvSceneSwitcher.macroTab.run="Exécuter la macro"
|
AdvSceneSwitcher.macroTab.run="Exécuter la macro"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Exécuter la macro en parallèle avec d'autres macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Exécuter la macro en parallèle avec d'autres macros"
|
||||||
AdvSceneSwitcher.macroTab.onChange="Exécuter des actions uniquement en cas de changement de condition"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Groupe %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Groupe %1"
|
||||||
AdvSceneSwitcher.macroTab.removeSingleMacroPopup.text="Êtes-vous sûr de vouloir supprimer \"%1\" ?"
|
AdvSceneSwitcher.macroTab.removeSingleMacroPopup.text="Êtes-vous sûr de vouloir supprimer \"%1\" ?"
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,6 @@ AdvSceneSwitcher.macroTab.run.tooltip="条件に関係なくすべてのマク
|
||||||
AdvSceneSwitcher.macroTab.runElse="マクロ実行(else)"
|
AdvSceneSwitcher.macroTab.runElse="マクロ実行(else)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="\"%1\" の実行に失敗しました!\nいずれかのアクションが失敗したか、マクロがすでに実行されています。\n停止しますか?"
|
AdvSceneSwitcher.macroTab.runFail="\"%1\" の実行に失敗しました!\nいずれかのアクションが失敗したか、マクロがすでに実行されています。\n停止しますか?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="他のマクロと並行してマクロを実行する"
|
AdvSceneSwitcher.macroTab.runInParallel="他のマクロと並行してマクロを実行する"
|
||||||
AdvSceneSwitcher.macroTab.onChange="条件変更時のみアクションを実行"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="マクロ %1"
|
AdvSceneSwitcher.macroTab.defaultname="マクロ %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="グループ %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="グループ %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="名前 \"%1\" は既にマクロで使用されています。"
|
AdvSceneSwitcher.macroTab.macroNameExists="名前 \"%1\" は既にマクロで使用されています。"
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,6 @@ AdvSceneSwitcher.macroTab.run.tooltip="Execute todas as ações da macro indepen
|
||||||
AdvSceneSwitcher.macroTab.runElse="Executar macro (alternativa)"
|
AdvSceneSwitcher.macroTab.runElse="Executar macro (alternativa)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="Falha ao executar \"%1\"!\nUma das ações falhou ou a macro já está em execução.\nDeseja interrompê-la?"
|
AdvSceneSwitcher.macroTab.runFail="Falha ao executar \"%1\"!\nUma das ações falhou ou a macro já está em execução.\nDeseja interrompê-la?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Executar macro em paralelo com outras macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Executar macro em paralelo com outras macros"
|
||||||
AdvSceneSwitcher.macroTab.onChange="Executar ações apenas quando houver mudança na condição"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Grupo %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Grupo %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="O nome \"%1\" já está em uso por uma macro."
|
AdvSceneSwitcher.macroTab.macroNameExists="O nome \"%1\" já está em uso por uma macro."
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ AdvSceneSwitcher.macroTab.add="Yeni Makro ekle"
|
||||||
AdvSceneSwitcher.macroTab.name="İsim:"
|
AdvSceneSwitcher.macroTab.name="İsim:"
|
||||||
AdvSceneSwitcher.macroTab.run="Makro Çalıştırma"
|
AdvSceneSwitcher.macroTab.run="Makro Çalıştırma"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Makroyu diğer makrolara paralel olarak çalıştırın"
|
AdvSceneSwitcher.macroTab.runInParallel="Makroyu diğer makrolara paralel olarak çalıştırın"
|
||||||
AdvSceneSwitcher.macroTab.onChange="Eylemleri yalnızca koşul değişikliğinde gerçekleştirin"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
||||||
AdvSceneSwitcher.macroTab.copy="Kopya oluştur"
|
AdvSceneSwitcher.macroTab.copy="Kopya oluştur"
|
||||||
AdvSceneSwitcher.macroTab.expandAll="Hepsini Genişlet"
|
AdvSceneSwitcher.macroTab.expandAll="Hepsini Genişlet"
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,6 @@ AdvSceneSwitcher.macroTab.run.tooltip="无论条件如何,都运行所有宏
|
||||||
AdvSceneSwitcher.macroTab.runElse="运行宏(不满足条件)"
|
AdvSceneSwitcher.macroTab.runElse="运行宏(不满足条件)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n要么其中一个操作失败,要么宏已在运行中.\n你想停止它吗?"
|
AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n要么其中一个操作失败,要么宏已在运行中.\n你想停止它吗?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="与其他宏并行运行宏"
|
AdvSceneSwitcher.macroTab.runInParallel="与其他宏并行运行宏"
|
||||||
AdvSceneSwitcher.macroTab.onChange="仅在条件结果发生变化时执行操作(条件结果不变时只执行一次操作)"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="宏 %1"
|
AdvSceneSwitcher.macroTab.defaultname="宏 %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="分组 %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="分组 %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="名称 \"%1\" 已被宏使用."
|
AdvSceneSwitcher.macroTab.macroNameExists="名称 \"%1\" 已被宏使用."
|
||||||
|
|
|
||||||
|
|
@ -793,25 +793,19 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="runMacroOnChange">
|
<widget class="QLabel" name="label_18">
|
||||||
<property name="toolTip">
|
|
||||||
<string>AdvSceneSwitcher.macroTab.onChange</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string>AdvSceneSwitcher.macroTab.actionTriggerMode.label</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_18">
|
<widget class="QComboBox" name="actionTriggerMode">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>AdvSceneSwitcher.macroTab.onChange</string>
|
<string>AdvSceneSwitcher.macroTab.actionTriggerMode.tooltip</string>
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>AdvSceneSwitcher.macroTab.onChange</string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -4125,7 +4119,7 @@
|
||||||
<tabstop>macroName</tabstop>
|
<tabstop>macroName</tabstop>
|
||||||
<tabstop>runMacro</tabstop>
|
<tabstop>runMacro</tabstop>
|
||||||
<tabstop>runMacroInParallel</tabstop>
|
<tabstop>runMacroInParallel</tabstop>
|
||||||
<tabstop>runMacroOnChange</tabstop>
|
<tabstop>actionTriggerMode</tabstop>
|
||||||
<tabstop>macroSettings</tabstop>
|
<tabstop>macroSettings</tabstop>
|
||||||
<tabstop>macroEdit</tabstop>
|
<tabstop>macroEdit</tabstop>
|
||||||
<tabstop>sceneGroups</tabstop>
|
<tabstop>sceneGroups</tabstop>
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ public slots:
|
||||||
void on_macroDown_clicked() const;
|
void on_macroDown_clicked() const;
|
||||||
void on_macroName_editingFinished();
|
void on_macroName_editingFinished();
|
||||||
void on_runMacroInParallel_stateChanged(int value) const;
|
void on_runMacroInParallel_stateChanged(int value) const;
|
||||||
void on_runMacroOnChange_stateChanged(int value) const;
|
void on_actionTriggerMode_currentIndexChanged(int index) const;
|
||||||
void MacroSelectionChanged();
|
void MacroSelectionChanged();
|
||||||
void ShowMacroContextMenu(const QPoint &);
|
void ShowMacroContextMenu(const QPoint &);
|
||||||
void CopyMacro();
|
void CopyMacro();
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,17 @@ MacroCondition::MacroCondition(Macro *m, bool supportsVariableValue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroCondition::EvaluateCondition()
|
||||||
|
{
|
||||||
|
bool newValue = CheckCondition();
|
||||||
|
_changed = _previousValue.has_value() && (*_previousValue != newValue);
|
||||||
|
const bool negate = _logic.IsNegationType(GetLogicType());
|
||||||
|
_risingEdge = _changed &&
|
||||||
|
((!negate && newValue) || (negate && !newValue));
|
||||||
|
_previousValue = newValue;
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroCondition::Save(obs_data_t *obj) const
|
bool MacroCondition::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroSegment::Save(obj);
|
MacroSegment::Save(obj);
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,19 @@
|
||||||
#include "duration-modifier.hpp"
|
#include "duration-modifier.hpp"
|
||||||
#include "macro-ref.hpp"
|
#include "macro-ref.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class EXPORT MacroCondition : public MacroSegment {
|
class EXPORT MacroCondition : public MacroSegment {
|
||||||
public:
|
public:
|
||||||
MacroCondition(Macro *m, bool supportsVariableValue = false);
|
MacroCondition(Macro *m, bool supportsVariableValue = false);
|
||||||
virtual ~MacroCondition() = default;
|
virtual ~MacroCondition() = default;
|
||||||
virtual bool CheckCondition() = 0;
|
|
||||||
|
bool EvaluateCondition();
|
||||||
|
bool HasChanged() const { return _changed; }
|
||||||
|
bool IsRisingEdge() const { return _risingEdge; }
|
||||||
|
|
||||||
virtual bool Save(obs_data_t *obj) const = 0;
|
virtual bool Save(obs_data_t *obj) const = 0;
|
||||||
virtual bool Load(obs_data_t *obj) = 0;
|
virtual bool Load(obs_data_t *obj) = 0;
|
||||||
|
|
||||||
|
|
@ -28,9 +34,15 @@ public:
|
||||||
|
|
||||||
static std::string_view GetDefaultID();
|
static std::string_view GetDefaultID();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool CheckCondition() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logic _logic = Logic(Logic::Type::ROOT_NONE);
|
Logic _logic = Logic(Logic::Type::ROOT_NONE);
|
||||||
DurationModifier _durationModifier;
|
DurationModifier _durationModifier;
|
||||||
|
std::optional<bool> _previousValue;
|
||||||
|
bool _changed = false;
|
||||||
|
bool _risingEdge = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EXPORT MacroRefCondition : virtual public MacroCondition {
|
class EXPORT MacroRefCondition : virtual public MacroCondition {
|
||||||
|
|
|
||||||
|
|
@ -474,14 +474,17 @@ void AdvSceneSwitcher::on_runMacroInParallel_stateChanged(int value) const
|
||||||
macro->SetRunInParallel(value);
|
macro->SetRunInParallel(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_runMacroOnChange_stateChanged(int value) const
|
void AdvSceneSwitcher::on_actionTriggerMode_currentIndexChanged(int index) const
|
||||||
{
|
{
|
||||||
auto macro = GetSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
macro->SetMatchOnChange(value);
|
const auto mode = static_cast<Macro::ActionTriggerMode>(
|
||||||
|
ui->actionTriggerMode->itemData(index).toInt());
|
||||||
|
macro->SetActionTriggerMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable) const
|
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable) const
|
||||||
|
|
@ -489,7 +492,7 @@ void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable) const
|
||||||
ui->macroName->setDisabled(disable);
|
ui->macroName->setDisabled(disable);
|
||||||
ui->runMacro->setDisabled(disable);
|
ui->runMacro->setDisabled(disable);
|
||||||
ui->runMacroInParallel->setDisabled(disable);
|
ui->runMacroInParallel->setDisabled(disable);
|
||||||
ui->runMacroOnChange->setDisabled(disable);
|
ui->actionTriggerMode->setDisabled(disable);
|
||||||
ui->macroEdit->SetControlsDisabled(disable);
|
ui->macroEdit->SetControlsDisabled(disable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -519,10 +522,12 @@ void AdvSceneSwitcher::MacroSelectionChanged()
|
||||||
{
|
{
|
||||||
const QSignalBlocker b1(ui->macroName);
|
const QSignalBlocker b1(ui->macroName);
|
||||||
const QSignalBlocker b2(ui->runMacroInParallel);
|
const QSignalBlocker b2(ui->runMacroInParallel);
|
||||||
const QSignalBlocker b3(ui->runMacroOnChange);
|
const QSignalBlocker b3(ui->actionTriggerMode);
|
||||||
ui->macroName->setText(macro->Name().c_str());
|
ui->macroName->setText(macro->Name().c_str());
|
||||||
ui->runMacroInParallel->setChecked(macro->RunInParallel());
|
ui->runMacroInParallel->setChecked(macro->RunInParallel());
|
||||||
ui->runMacroOnChange->setChecked(macro->MatchOnChange());
|
ui->actionTriggerMode->setCurrentIndex(
|
||||||
|
ui->actionTriggerMode->findData(static_cast<int>(
|
||||||
|
macro->GetActionTriggerMode())));
|
||||||
}
|
}
|
||||||
|
|
||||||
macro->ResetUIHelpers();
|
macro->ResetUIHelpers();
|
||||||
|
|
@ -552,9 +557,9 @@ void AdvSceneSwitcher::HighlightOnChange() const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (macro->OnChangePreventedActionsSince(
|
if (macro->ActionTriggerModePreventedActionsSince(
|
||||||
lastOnChangeHighlightCheckTime)) {
|
lastOnChangeHighlightCheckTime)) {
|
||||||
HighlightWidget(ui->runMacroOnChange, Qt::yellow,
|
HighlightWidget(ui->actionTriggerMode, Qt::yellow,
|
||||||
Qt::transparent, true);
|
Qt::transparent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -682,6 +687,24 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||||
ui->macroSearchRegex,
|
ui->macroSearchRegex,
|
||||||
ui->macroSearchShowSettings,
|
ui->macroSearchShowSettings,
|
||||||
[this]() { ui->macros->RefreshFilter(); });
|
[this]() { ui->macros->RefreshFilter(); });
|
||||||
|
|
||||||
|
static const std::vector<
|
||||||
|
std::pair<Macro::ActionTriggerMode, const char *>>
|
||||||
|
actionTriggerModes = {
|
||||||
|
{Macro::ActionTriggerMode::ALWAYS,
|
||||||
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.always"},
|
||||||
|
{Macro::ActionTriggerMode::MACRO_RESULT_CHANGED,
|
||||||
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.onOverallChange"},
|
||||||
|
{Macro::ActionTriggerMode::ANY_CONDITION_CHANGED,
|
||||||
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionChange"},
|
||||||
|
{Macro::ActionTriggerMode::ANY_CONDITION_TRIGGERED,
|
||||||
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionTriggered"},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &[mode, name] : actionTriggerModes) {
|
||||||
|
ui->actionTriggerMode->addItem(obs_module_text(name),
|
||||||
|
static_cast<int>(mode));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,8 @@ void MacroTreeItem::HighlightIfExecuted()
|
||||||
|
|
||||||
if (!wasHighlighted &&
|
if (!wasHighlighted &&
|
||||||
_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
||||||
_macro->OnChangePreventedActionsSince(_lastHighlightCheckTime)) {
|
_macro->ActionTriggerModePreventedActionsSince(
|
||||||
|
_lastHighlightCheckTime)) {
|
||||||
HighlightWidget(this, Qt::yellow, QColor(0, 0, 0, 0), true);
|
HighlightWidget(this, Qt::yellow, QColor(0, 0, 0, 0), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ static bool checkCondition(const std::shared_ptr<MacroCondition> &condition)
|
||||||
const auto startTime = std::chrono::high_resolution_clock::now();
|
const auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
bool conditionMatched = false;
|
bool conditionMatched = false;
|
||||||
condition->WithLock([&condition, &conditionMatched]() {
|
condition->WithLock([&condition, &conditionMatched]() {
|
||||||
conditionMatched = condition->CheckCondition();
|
conditionMatched = condition->EvaluateCondition();
|
||||||
});
|
});
|
||||||
const auto endTime = std::chrono::high_resolution_clock::now();
|
const auto endTime = std::chrono::high_resolution_clock::now();
|
||||||
const auto timeSpent = endTime - startTime;
|
const auto timeSpent = endTime - startTime;
|
||||||
|
|
@ -241,12 +241,36 @@ bool Macro::CheckConditions(bool ignorePause)
|
||||||
|
|
||||||
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
||||||
|
|
||||||
_conditionSateChanged = _lastMatched != _matched;
|
_actionModeMatch = false;
|
||||||
|
switch (_actionTriggerMode) {
|
||||||
|
case Macro::ActionTriggerMode::ALWAYS:
|
||||||
|
_actionModeMatch = true;
|
||||||
|
break;
|
||||||
|
case Macro::ActionTriggerMode::MACRO_RESULT_CHANGED:
|
||||||
|
_actionModeMatch = _lastMatched != _matched;
|
||||||
|
break;
|
||||||
|
case Macro::ActionTriggerMode::ANY_CONDITION_CHANGED:
|
||||||
|
for (const auto &condition : _conditions) {
|
||||||
|
if (condition->HasChanged()) {
|
||||||
|
_actionModeMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Macro::ActionTriggerMode::ANY_CONDITION_TRIGGERED:
|
||||||
|
for (const auto &condition : _conditions) {
|
||||||
|
if (condition->IsRisingEdge()) {
|
||||||
|
_actionModeMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const bool hasActionsToExecute = _matched ? (_actions.size() > 0)
|
const bool hasActionsToExecute = _matched ? (_actions.size() > 0)
|
||||||
: (_elseActions.size() > 0);
|
: (_elseActions.size() > 0);
|
||||||
if (!_conditionSateChanged && _performActionsOnChange &&
|
if (!_actionModeMatch && hasActionsToExecute) {
|
||||||
hasActionsToExecute) {
|
_lastActionRunModePreventTime =
|
||||||
_lastOnChangeActionsPreventedTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,9 +330,9 @@ bool Macro::WasExecutedSince(const TimePoint &time) const
|
||||||
return _lastExecutionTime > time;
|
return _lastExecutionTime > time;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Macro::OnChangePreventedActionsSince(const TimePoint &time) const
|
bool Macro::ActionTriggerModePreventedActionsSince(const TimePoint &time) const
|
||||||
{
|
{
|
||||||
return _lastOnChangeActionsPreventedTime > time;
|
return _lastActionRunModePreventTime > time;
|
||||||
}
|
}
|
||||||
|
|
||||||
Macro::TimePoint Macro::GetLastExecutionTime() const
|
Macro::TimePoint Macro::GetLastExecutionTime() const
|
||||||
|
|
@ -342,10 +366,9 @@ bool Macro::ShouldRunActions() const
|
||||||
|
|
||||||
const bool hasActionsToExecute =
|
const bool hasActionsToExecute =
|
||||||
!_paused && (_matched || _elseActions.size() > 0) &&
|
!_paused && (_matched || _elseActions.size() > 0) &&
|
||||||
(!_performActionsOnChange || _conditionSateChanged);
|
_actionModeMatch;
|
||||||
|
|
||||||
if (VerboseLoggingEnabled() && _performActionsOnChange &&
|
if (VerboseLoggingEnabled() && !_actionModeMatch) {
|
||||||
!_conditionSateChanged) {
|
|
||||||
if (_matched && _actions.size() > 0) {
|
if (_matched && _actions.size() > 0) {
|
||||||
blog(LOG_INFO, "skip actions for Macro %s (on change)",
|
blog(LOG_INFO, "skip actions for Macro %s (on change)",
|
||||||
_name.c_str());
|
_name.c_str());
|
||||||
|
|
@ -376,6 +399,16 @@ void Macro::ResetTimers()
|
||||||
_lastExecutionTime = {};
|
_lastExecutionTime = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Macro::SetActionTriggerMode(ActionTriggerMode mode)
|
||||||
|
{
|
||||||
|
_actionTriggerMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Macro::ActionTriggerMode Macro::GetActionTriggerMode() const
|
||||||
|
{
|
||||||
|
return _actionTriggerMode;
|
||||||
|
}
|
||||||
|
|
||||||
bool Macro::RunActionsHelper(
|
bool Macro::RunActionsHelper(
|
||||||
const std::deque<std::shared_ptr<MacroAction>> &actionsToRun,
|
const std::deque<std::shared_ptr<MacroAction>> &actionsToRun,
|
||||||
bool ignorePause)
|
bool ignorePause)
|
||||||
|
|
@ -433,11 +466,6 @@ bool Macro::WasPausedSince(const TimePoint &time) const
|
||||||
return _lastUnpauseTime > time;
|
return _lastUnpauseTime > time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Macro::SetMatchOnChange(bool onChange)
|
|
||||||
{
|
|
||||||
_performActionsOnChange = onChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetStopActionsIfNotDone(bool stopActionsIfNotDone)
|
void Macro::SetStopActionsIfNotDone(bool stopActionsIfNotDone)
|
||||||
{
|
{
|
||||||
_stopActionsIfNotDone = stopActionsIfNotDone;
|
_stopActionsIfNotDone = stopActionsIfNotDone;
|
||||||
|
|
@ -758,7 +786,8 @@ bool Macro::Save(obs_data_t *obj, bool saveForCopy) const
|
||||||
obs_data_set_bool(obj, "pause", _paused);
|
obs_data_set_bool(obj, "pause", _paused);
|
||||||
obs_data_set_bool(obj, "parallel", _runInParallel);
|
obs_data_set_bool(obj, "parallel", _runInParallel);
|
||||||
obs_data_set_bool(obj, "checkConditionsInParallel", _checkInParallel);
|
obs_data_set_bool(obj, "checkConditionsInParallel", _checkInParallel);
|
||||||
obs_data_set_bool(obj, "onChange", _performActionsOnChange);
|
obs_data_set_int(obj, "actionTriggerMode",
|
||||||
|
static_cast<int>(_actionTriggerMode));
|
||||||
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
||||||
obs_data_set_bool(obj, "stopActionsIfNotDone", _stopActionsIfNotDone);
|
obs_data_set_bool(obj, "stopActionsIfNotDone", _stopActionsIfNotDone);
|
||||||
obs_data_set_bool(obj, "useShortCircuitEvaluation",
|
obs_data_set_bool(obj, "useShortCircuitEvaluation",
|
||||||
|
|
@ -844,7 +873,15 @@ bool Macro::Load(obs_data_t *obj)
|
||||||
}
|
}
|
||||||
_runInParallel = obs_data_get_bool(obj, "parallel");
|
_runInParallel = obs_data_get_bool(obj, "parallel");
|
||||||
_checkInParallel = obs_data_get_bool(obj, "checkConditionsInParallel");
|
_checkInParallel = obs_data_get_bool(obj, "checkConditionsInParallel");
|
||||||
_performActionsOnChange = obs_data_get_bool(obj, "onChange");
|
if (obs_data_has_user_value(obj, "onChange")) {
|
||||||
|
const bool onChange = obs_data_get_bool(obj, "onChange");
|
||||||
|
_actionTriggerMode =
|
||||||
|
onChange ? ActionTriggerMode::MACRO_RESULT_CHANGED
|
||||||
|
: ActionTriggerMode::ALWAYS;
|
||||||
|
} else {
|
||||||
|
_actionTriggerMode = static_cast<ActionTriggerMode>(
|
||||||
|
obs_data_get_int(obj, "actionTriggerMode"));
|
||||||
|
}
|
||||||
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
||||||
_stopActionsIfNotDone = obs_data_get_bool(obj, "stopActionsIfNotDone");
|
_stopActionsIfNotDone = obs_data_get_bool(obj, "stopActionsIfNotDone");
|
||||||
_useShortCircuitEvaluation =
|
_useShortCircuitEvaluation =
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,16 @@ class Macro {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class PauseStateSaveBehavior { PERSIST, PAUSE, UNPAUSE };
|
enum class PauseStateSaveBehavior { PERSIST, PAUSE, UNPAUSE };
|
||||||
|
enum class ActionTriggerMode {
|
||||||
|
// Trigger always
|
||||||
|
ALWAYS,
|
||||||
|
// Trigger when macro match result flips
|
||||||
|
MACRO_RESULT_CHANGED,
|
||||||
|
// Trigger when any individual condition changes
|
||||||
|
ANY_CONDITION_CHANGED,
|
||||||
|
// Trigger when any individual condition evaluates to true
|
||||||
|
ANY_CONDITION_TRIGGERED,
|
||||||
|
};
|
||||||
|
|
||||||
Macro(const std::string &name = "");
|
Macro(const std::string &name = "");
|
||||||
Macro(const std::string &name, const GlobalMacroSettings &settings);
|
Macro(const std::string &name, const GlobalMacroSettings &settings);
|
||||||
|
|
@ -54,8 +64,8 @@ public:
|
||||||
bool GetStop() const { return _stop; }
|
bool GetStop() const { return _stop; }
|
||||||
void ResetTimers();
|
void ResetTimers();
|
||||||
|
|
||||||
void SetMatchOnChange(bool onChange);
|
void SetActionTriggerMode(ActionTriggerMode);
|
||||||
bool MatchOnChange() const { return _performActionsOnChange; }
|
ActionTriggerMode GetActionTriggerMode() const;
|
||||||
|
|
||||||
void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; }
|
void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; }
|
||||||
bool SkipExecOnStart() const { return _skipExecOnStart; }
|
bool SkipExecOnStart() const { return _skipExecOnStart; }
|
||||||
|
|
@ -137,7 +147,7 @@ public:
|
||||||
const QList<int> &GetElseActionSplitterPosition() const;
|
const QList<int> &GetElseActionSplitterPosition() const;
|
||||||
bool HasValidSplitterPositions() const;
|
bool HasValidSplitterPositions() const;
|
||||||
bool WasExecutedSince(const TimePoint &) const;
|
bool WasExecutedSince(const TimePoint &) const;
|
||||||
bool OnChangePreventedActionsSince(const TimePoint &) const;
|
bool ActionTriggerModePreventedActionsSince(const TimePoint &) const;
|
||||||
TimePoint GetLastExecutionTime() const;
|
TimePoint GetLastExecutionTime() const;
|
||||||
void ResetUIHelpers();
|
void ResetUIHelpers();
|
||||||
|
|
||||||
|
|
@ -169,7 +179,7 @@ private:
|
||||||
TimePoint _lastCheckTime{};
|
TimePoint _lastCheckTime{};
|
||||||
TimePoint _lastUnpauseTime{};
|
TimePoint _lastUnpauseTime{};
|
||||||
TimePoint _lastExecutionTime{};
|
TimePoint _lastExecutionTime{};
|
||||||
TimePoint _lastOnChangeActionsPreventedTime{};
|
TimePoint _lastActionRunModePreventTime{};
|
||||||
std::vector<std::thread> _helperThreads;
|
std::vector<std::thread> _helperThreads;
|
||||||
|
|
||||||
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
||||||
|
|
@ -184,14 +194,13 @@ private:
|
||||||
bool _useShortCircuitEvaluation = false;
|
bool _useShortCircuitEvaluation = false;
|
||||||
bool _useCustomConditionCheckInterval = false;
|
bool _useCustomConditionCheckInterval = false;
|
||||||
Duration _customConditionCheckInterval = 0.3;
|
Duration _customConditionCheckInterval = 0.3;
|
||||||
bool _conditionSateChanged = false;
|
bool _actionModeMatch = false;
|
||||||
|
|
||||||
bool _runInParallel = false;
|
bool _runInParallel = false;
|
||||||
bool _checkInParallel = false;
|
bool _checkInParallel = false;
|
||||||
bool _matched = false;
|
bool _matched = false;
|
||||||
std::future<void> _conditionCheckFuture;
|
std::future<void> _conditionCheckFuture;
|
||||||
bool _lastMatched = false;
|
bool _lastMatched = false;
|
||||||
bool _performActionsOnChange = true;
|
|
||||||
bool _skipExecOnStart = false;
|
bool _skipExecOnStart = false;
|
||||||
bool _stopActionsIfNotDone = false;
|
bool _stopActionsIfNotDone = false;
|
||||||
bool _paused = false;
|
bool _paused = false;
|
||||||
|
|
@ -201,6 +210,9 @@ private:
|
||||||
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
|
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||||
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
|
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||||
|
|
||||||
|
ActionTriggerMode _actionTriggerMode =
|
||||||
|
ActionTriggerMode::MACRO_RESULT_CHANGED;
|
||||||
|
|
||||||
PauseStateSaveBehavior _pauseSaveBehavior =
|
PauseStateSaveBehavior _pauseSaveBehavior =
|
||||||
PauseStateSaveBehavior::PERSIST;
|
PauseStateSaveBehavior::PERSIST;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user