diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 6b45f142..502dd90f 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -126,13 +126,17 @@ AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Automated scene chan AdvSceneSwitcher.condition.pluginState.entry="{{condition}}" AdvSceneSwitcher.condition.interval="Interval" AdvSceneSwitcher.condition.interval.entry="{{duration}} have passed" -AdvSceneSwitcher.condition.counter="Count" -AdvSceneSwitcher.condition.counter.type.below="Less than" -AdvSceneSwitcher.condition.counter.type.above="More than" -AdvSceneSwitcher.condition.counter.type.equal="Exactly" -AdvSceneSwitcher.condition.counter.reset="Reset" -AdvSceneSwitcher.condition.counter.entry.line1="{{macros}} was executed {{conditions}} {{count}} times" -AdvSceneSwitcher.condition.counter.entry.line2="Current count: {{currentCount}} {{resetCount}}" +AdvSceneSwitcher.condition.macro="Macro" +AdvSceneSwitcher.condition.macro.type.count="Count" +AdvSceneSwitcher.condition.macro.type.state="State" +AdvSceneSwitcher.condition.macro.type.selection="Condition type: {{types}}" +AdvSceneSwitcher.condition.macro.count.type.below="Less than" +AdvSceneSwitcher.condition.macro.count.type.above="More than" +AdvSceneSwitcher.condition.macro.count.type.equal="Exactly" +AdvSceneSwitcher.condition.macro.count.reset="Reset" +AdvSceneSwitcher.condition.macro.state.entry="Conditions of {{macros}} are true" +AdvSceneSwitcher.condition.macro.count.entry.line1="{{macros}} was executed {{conditions}} {{count}} times" +AdvSceneSwitcher.condition.macro.count.entry.line2="Current count: {{currentCount}} {{resetCount}}" AdvSceneSwitcher.condition.source="Source" AdvSceneSwitcher.condition.source.type.active="Is active" AdvSceneSwitcher.condition.source.type.showing="Is showing" diff --git a/src/headers/macro-condition-macro.hpp b/src/headers/macro-condition-macro.hpp index e02bc646..c9de17cd 100644 --- a/src/headers/macro-condition-macro.hpp +++ b/src/headers/macro-condition-macro.hpp @@ -6,13 +6,18 @@ #include #include +enum class MacroConditionMacroType { + COUNT, + STATE, +}; + enum class CounterCondition { BELOW, ABOVE, EQUAL, }; -class MacroConditionCounter : public MacroRefCondition { +class MacroConditionMacro : public MacroRefCondition { public: bool CheckCondition(); bool Save(obs_data_t *obj); @@ -20,36 +25,41 @@ public: std::string GetId() { return id; }; static std::shared_ptr Create() { - return std::make_shared(); + return std::make_shared(); } - CounterCondition _condition = CounterCondition::BELOW; + MacroConditionMacroType _type = MacroConditionMacroType::STATE; + CounterCondition _counterCondition = CounterCondition::BELOW; int _count = 0; private: + bool CheckCountCondition(); + bool CheckStateCondition(); + static bool _registered; static const std::string id; }; -class MacroConditionCounterEdit : public QWidget { +class MacroConditionMacroEdit : public QWidget { Q_OBJECT public: - MacroConditionCounterEdit( + MacroConditionMacroEdit( QWidget *parent, - std::shared_ptr cond = nullptr); + std::shared_ptr cond = nullptr); void UpdateEntryData(); static QWidget *Create(QWidget *parent, std::shared_ptr cond) { - return new MacroConditionCounterEdit( + return new MacroConditionMacroEdit( parent, - std::dynamic_pointer_cast(cond)); + std::dynamic_pointer_cast(cond)); } private slots: void MacroChanged(const QString &text); void MacroRemove(const QString &name); + void TypeChanged(int type); void CountChanged(int value); void ConditionChanged(int cond); void ResetClicked(); @@ -57,14 +67,20 @@ private slots: protected: MacroSelection *_macros; - QComboBox *_conditions; + QComboBox *_types; + QComboBox *_counterConditions; QSpinBox *_count; QLabel *_currentCount; QPushButton *_resetCount; + QHBoxLayout *_settingsLine1; + QHBoxLayout *_settingsLine2; std::unique_ptr _timer; - std::shared_ptr _entryData; + std::shared_ptr _entryData; private: + void ClearLayouts(); + void SetupStateWidgets(); + void SetupCountWidgets(); void ResetTimer(); bool _loading = true; }; diff --git a/src/macro-condition-macro.cpp b/src/macro-condition-macro.cpp index b738784e..c56b681b 100644 --- a/src/macro-condition-macro.cpp +++ b/src/macro-condition-macro.cpp @@ -3,29 +3,46 @@ #include "headers/utility.hpp" #include "headers/advanced-scene-switcher.hpp" -const std::string MacroConditionCounter::id = "counter"; +const std::string MacroConditionMacro::id = "macro"; -bool MacroConditionCounter::_registered = MacroConditionFactory::Register( - MacroConditionCounter::id, - {MacroConditionCounter::Create, MacroConditionCounterEdit::Create, - "AdvSceneSwitcher.condition.counter"}); +bool MacroConditionMacro::_registered = MacroConditionFactory::Register( + MacroConditionMacro::id, + {MacroConditionMacro::Create, MacroConditionMacroEdit::Create, + "AdvSceneSwitcher.condition.macro"}); + +// TODO: Remove in future version - just added for backward compatibility +static std::string idOld = "counter"; +static bool oldRegisterd = MacroConditionFactory::Register( + idOld, {MacroConditionMacro::Create, MacroConditionMacroEdit::Create, + "AdvSceneSwitcher.condition.macro"}); + +static std::map macroConditionTypes = { + {MacroConditionMacroType::COUNT, + "AdvSceneSwitcher.condition.macro.type.count"}, + {MacroConditionMacroType::STATE, + "AdvSceneSwitcher.condition.macro.type.state"}, +}; static std::map counterConditionTypes = { {CounterCondition::BELOW, - "AdvSceneSwitcher.condition.counter.type.below"}, + "AdvSceneSwitcher.condition.macro.count.type.below"}, {CounterCondition::ABOVE, - "AdvSceneSwitcher.condition.counter.type.above"}, + "AdvSceneSwitcher.condition.macro.count.type.above"}, {CounterCondition::EQUAL, - "AdvSceneSwitcher.condition.counter.type.equal"}, + "AdvSceneSwitcher.condition.macro.count.type.equal"}, }; -bool MacroConditionCounter::CheckCondition() +bool MacroConditionMacro::CheckStateCondition() { - if (!_macro.get()) { - return false; - } + // Note: + // Depending on the order the macro conditions are checked Matched() might + // still return the state of the previous interval + return _macro->Matched(); +} - switch (_condition) { +bool MacroConditionMacro::CheckCountCondition() +{ + switch (_counterCondition) { case CounterCondition::BELOW: return _macro->GetCount() < _count; case CounterCondition::ABOVE: @@ -39,25 +56,55 @@ bool MacroConditionCounter::CheckCondition() return false; } -bool MacroConditionCounter::Save(obs_data_t *obj) +bool MacroConditionMacro::CheckCondition() +{ + if (!_macro.get()) { + return false; + } + + switch (_type) { + case MacroConditionMacroType::STATE: + return CheckStateCondition(); + break; + case MacroConditionMacroType::COUNT: + return CheckCountCondition(); + break; + default: + break; + } + + return false; +} + +bool MacroConditionMacro::Save(obs_data_t *obj) { MacroCondition::Save(obj); _macro.Save(obj); - obs_data_set_int(obj, "condition", static_cast(_condition)); + obs_data_set_int(obj, "type", static_cast(_type)); + obs_data_set_int(obj, "condition", static_cast(_counterCondition)); obs_data_set_int(obj, "count", _count); return true; } -bool MacroConditionCounter::Load(obs_data_t *obj) +bool MacroConditionMacro::Load(obs_data_t *obj) { MacroCondition::Load(obj); _macro.Load(obj); - _condition = static_cast( + _type = static_cast( + obs_data_get_int(obj, "type")); + _counterCondition = static_cast( obs_data_get_int(obj, "condition")); _count = obs_data_get_int(obj, "count"); return true; } +static inline void populateTypeSelection(QComboBox *list) +{ + for (auto entry : macroConditionTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + static inline void populateConditionSelection(QComboBox *list) { for (auto entry : counterConditionTypes) { @@ -65,49 +112,48 @@ static inline void populateConditionSelection(QComboBox *list) } } -MacroConditionCounterEdit::MacroConditionCounterEdit( - QWidget *parent, std::shared_ptr entryData) +MacroConditionMacroEdit::MacroConditionMacroEdit( + QWidget *parent, std::shared_ptr entryData) : QWidget(parent) { _macros = new MacroSelection(parent); - _conditions = new QComboBox(); - _count = new QSpinBox(); - _currentCount = new QLabel(); - _resetCount = new QPushButton( - obs_module_text("AdvSceneSwitcher.condition.counter.reset")); + _types = new QComboBox(parent); + _counterConditions = new QComboBox(parent); + _count = new QSpinBox(parent); + _currentCount = new QLabel(parent); + _resetCount = new QPushButton(obs_module_text( + "AdvSceneSwitcher.condition.macro.count.reset")); _count->setMaximum(10000000); - populateConditionSelection(_conditions); + populateTypeSelection(_types); + populateConditionSelection(_counterConditions); QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)), this, SLOT(MacroChanged(const QString &))); QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this, SLOT(MacroRemove(const QString &))); - QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this, - SLOT(ConditionChanged(int))); + QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this, + SLOT(TypeChanged(int))); + QWidget::connect(_counterConditions, SIGNAL(currentIndexChanged(int)), + this, SLOT(ConditionChanged(int))); QWidget::connect(_count, SIGNAL(valueChanged(int)), this, SLOT(CountChanged(int))); QWidget::connect(_resetCount, SIGNAL(clicked()), this, SLOT(ResetClicked())); - QVBoxLayout *mainLayout = new QVBoxLayout; - QHBoxLayout *line1Layout = new QHBoxLayout; - QHBoxLayout *line2Layout = new QHBoxLayout; + auto typesLayout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { - {"{{macros}}", _macros}, - {"{{conditions}}", _conditions}, - {"{{count}}", _count}, - {"{{currentCount}}", _currentCount}, - {"{{resetCount}}", _resetCount}, + {"{{types}}", _types}, }; placeWidgets(obs_module_text( - "AdvSceneSwitcher.condition.counter.entry.line1"), - line1Layout, widgetPlaceholders); - placeWidgets(obs_module_text( - "AdvSceneSwitcher.condition.counter.entry.line2"), - line2Layout, widgetPlaceholders); - mainLayout->addLayout(line1Layout); - mainLayout->addLayout(line2Layout); + "AdvSceneSwitcher.condition.macro.type.selection"), + typesLayout, widgetPlaceholders); + _settingsLine1 = new QHBoxLayout; + _settingsLine2 = new QHBoxLayout; + auto mainLayout = new QVBoxLayout; + mainLayout->addLayout(typesLayout); + mainLayout->addLayout(_settingsLine1); + mainLayout->addLayout(_settingsLine2); setLayout(mainLayout); _entryData = entryData; @@ -115,19 +161,84 @@ MacroConditionCounterEdit::MacroConditionCounterEdit( _loading = false; } -void MacroConditionCounterEdit::UpdateEntryData() +void MacroConditionMacroEdit::ClearLayouts() +{ + _settingsLine1->removeWidget(_macros); + _settingsLine1->removeWidget(_counterConditions); + _settingsLine1->removeWidget(_count); + _settingsLine2->removeWidget(_currentCount); + _settingsLine2->removeWidget(_resetCount); + clearLayout(_settingsLine1); + clearLayout(_settingsLine2); +} + +void MacroConditionMacroEdit::SetupStateWidgets() +{ + ClearLayouts(); + + _counterConditions->hide(); + _count->hide(); + _currentCount->hide(); + _resetCount->hide(); + + std::unordered_map widgetPlaceholders = { + {"{{macros}}", _macros}, + }; + placeWidgets( + obs_module_text("AdvSceneSwitcher.condition.macro.state.entry"), + _settingsLine1, widgetPlaceholders); + adjustSize(); +} + +void MacroConditionMacroEdit::SetupCountWidgets() +{ + ClearLayouts(); + + std::unordered_map widgetPlaceholders = { + {"{{macros}}", _macros}, + {"{{conditions}}", _counterConditions}, + {"{{count}}", _count}, + {"{{currentCount}}", _currentCount}, + {"{{resetCount}}", _resetCount}, + }; + placeWidgets( + obs_module_text( + "AdvSceneSwitcher.condition.macro.count.entry.line1"), + _settingsLine1, widgetPlaceholders); + placeWidgets( + obs_module_text( + "AdvSceneSwitcher.condition.macro.count.entry.line2"), + _settingsLine2, widgetPlaceholders); + + _counterConditions->show(); + _count->show(); + _currentCount->show(); + _resetCount->show(); + + adjustSize(); +} + +void MacroConditionMacroEdit::UpdateEntryData() { if (!_entryData) { return; } + if (_entryData->_type == MacroConditionMacroType::STATE) { + SetupStateWidgets(); + } else { + SetupCountWidgets(); + } + _macros->SetCurrentMacro(_entryData->_macro.get()); - _conditions->setCurrentIndex(static_cast(_entryData->_condition)); + _types->setCurrentIndex(static_cast(_entryData->_type)); + _counterConditions->setCurrentIndex( + static_cast(_entryData->_counterCondition)); _count->setValue(_entryData->_count); ResetTimer(); } -void MacroConditionCounterEdit::MacroChanged(const QString &text) +void MacroConditionMacroEdit::MacroChanged(const QString &text) { if (_loading || !_entryData) { return; @@ -138,7 +249,7 @@ void MacroConditionCounterEdit::MacroChanged(const QString &text) ResetTimer(); } -void MacroConditionCounterEdit::CountChanged(int value) +void MacroConditionMacroEdit::CountChanged(int value) { if (_loading || !_entryData) { return; @@ -148,17 +259,17 @@ void MacroConditionCounterEdit::CountChanged(int value) _entryData->_count = value; } -void MacroConditionCounterEdit::ConditionChanged(int cond) +void MacroConditionMacroEdit::ConditionChanged(int cond) { if (_loading || !_entryData) { return; } std::lock_guard lock(switcher->m); - _entryData->_condition = static_cast(cond); + _entryData->_counterCondition = static_cast(cond); } -void MacroConditionCounterEdit::MacroRemove(const QString &name) +void MacroConditionMacroEdit::MacroRemove(const QString &name) { UNUSED_PARAMETER(name); if (_entryData) { @@ -166,7 +277,22 @@ void MacroConditionCounterEdit::MacroRemove(const QString &name) } } -void MacroConditionCounterEdit::ResetClicked() +void MacroConditionMacroEdit::TypeChanged(int type) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_type = static_cast(type); + if (_entryData->_type == MacroConditionMacroType::STATE) { + SetupStateWidgets(); + } else { + SetupCountWidgets(); + } +} + +void MacroConditionMacroEdit::ResetClicked() { if (_loading || !_entryData || !_entryData->_macro.get()) { return; @@ -176,7 +302,7 @@ void MacroConditionCounterEdit::ResetClicked() ResetTimer(); } -void MacroConditionCounterEdit::UpdateCount() +void MacroConditionMacroEdit::UpdateCount() { if (_entryData && _entryData->_macro.get()) { _currentCount->setText( @@ -186,7 +312,7 @@ void MacroConditionCounterEdit::UpdateCount() } } -void MacroConditionCounterEdit::ResetTimer() +void MacroConditionMacroEdit::ResetTimer() { _timer.reset(new QTimer(this)); connect(_timer.get(), SIGNAL(timeout()), this, SLOT(UpdateCount()));