From 4a84bede37ce97100bae3ae4715e01275053a961 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 23 May 2021 21:13:50 +0200 Subject: [PATCH] Add macro condition "count" --- CMakeLists.txt | 2 + data/locale/en-US.ini | 7 + src/headers/macro-condition-counter.hpp | 72 +++++++ src/macro-condition-counter.cpp | 240 ++++++++++++++++++++++++ 4 files changed, 321 insertions(+) create mode 100644 src/headers/macro-condition-counter.hpp create mode 100644 src/macro-condition-counter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c4665f57..b83f7edd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ set(advanced-scene-switcher_HEADERS src/headers/macro-action-wait.hpp src/headers/macro-condition-edit.hpp src/headers/macro-condition-audio.hpp + src/headers/macro-condition-counter.hpp src/headers/macro-condition-file.hpp src/headers/macro-condition-idle.hpp src/headers/macro-condition-interval.hpp @@ -158,6 +159,7 @@ set(advanced-scene-switcher_SOURCES src/macro-action-wait.cpp src/macro-condition-edit.cpp src/macro-condition-audio.cpp + src/macro-condition-counter.cpp src/macro-condition-file.cpp src/macro-condition-idle.cpp src/macro-condition-interval.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 4cb31c7d..6256fc22 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -126,6 +126,13 @@ 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}}" ; Macro Actions AdvSceneSwitcher.action.switchScene="Switch scene" diff --git a/src/headers/macro-condition-counter.hpp b/src/headers/macro-condition-counter.hpp new file mode 100644 index 00000000..874116ed --- /dev/null +++ b/src/headers/macro-condition-counter.hpp @@ -0,0 +1,72 @@ +#pragma once +#include "macro.hpp" +#include +#include +#include +#include + +enum class CounterCondition { + BELOW, + ABOVE, + EQUAL, +}; + +class MacroConditionCounter : public MacroCondition { +public: + bool CheckCondition(); + bool Save(obs_data_t *obj); + bool Load(obs_data_t *obj); + std::string GetId() { return id; }; + static std::shared_ptr Create() + { + return std::make_shared(); + } + + Macro *_macro = nullptr; + CounterCondition _condition = CounterCondition::BELOW; + int _count = 0; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroConditionCounterEdit : public QWidget { + Q_OBJECT + +public: + MacroConditionCounterEdit( + QWidget *parent, + std::shared_ptr cond = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr cond) + { + return new MacroConditionCounterEdit( + parent, + std::dynamic_pointer_cast(cond)); + } + +private slots: + void MacroChanged(const QString &text); + void CountChanged(int value); + void ConditionChanged(int cond); + void MacroAdd(const QString &name); + void MacroRemove(const QString &name); + void MacroRename(const QString &oldName, const QString &newName); + void ResetClicked(); + void UpdateCount(); + +protected: + QComboBox *_macros; + QComboBox *_conditions; + QSpinBox *_count; + QLabel *_currentCount; + QPushButton *_resetCount; + std::unique_ptr _timer; + std::shared_ptr _entryData; + +private: + void ResetTimer(); + bool _loading = true; +}; diff --git a/src/macro-condition-counter.cpp b/src/macro-condition-counter.cpp new file mode 100644 index 00000000..cce707bf --- /dev/null +++ b/src/macro-condition-counter.cpp @@ -0,0 +1,240 @@ +#include "headers/macro-condition-edit.hpp" +#include "headers/macro-condition-counter.hpp" +#include "headers/utility.hpp" +#include "headers/advanced-scene-switcher.hpp" + +const std::string MacroConditionCounter::id = "counter"; + +bool MacroConditionCounter::_registered = MacroConditionFactory::Register( + MacroConditionCounter::id, + {MacroConditionCounter::Create, MacroConditionCounterEdit::Create, + "AdvSceneSwitcher.condition.counter"}); + +static std::map counterConditionTypes = { + {CounterCondition::BELOW, + "AdvSceneSwitcher.condition.counter.type.below"}, + {CounterCondition::ABOVE, + "AdvSceneSwitcher.condition.counter.type.above"}, + {CounterCondition::EQUAL, + "AdvSceneSwitcher.condition.counter.type.equal"}, +}; + +bool MacroConditionCounter::CheckCondition() +{ + switch (_condition) { + case CounterCondition::BELOW: + return _macro && _macro->GetCount() < _count; + case CounterCondition::ABOVE: + return _macro && _macro->GetCount() > _count; + case CounterCondition::EQUAL: + return _macro && _macro->GetCount() == _count; + default: + break; + } + + return false; +} + +bool MacroConditionCounter::Save(obs_data_t *obj) +{ + MacroCondition::Save(obj); + if (_macro) { + obs_data_set_string(obj, "macro", _macro->Name().c_str()); + } + obs_data_set_int(obj, "condition", static_cast(_condition)); + obs_data_set_int(obj, "count", _count); + return true; +} + +bool MacroConditionCounter::Load(obs_data_t *obj) +{ + MacroCondition::Load(obj); + _macro = GetMacroByName(obs_data_get_string(obj, "macro")); + _condition = static_cast( + obs_data_get_int(obj, "condition")); + _count = obs_data_get_int(obj, "count"); + return true; +} + +static inline void populateConditionSelection(QComboBox *list) +{ + for (auto entry : counterConditionTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + +static inline void populateMacroSelection(QComboBox *list) +{ + list->addItem(obs_module_text("AdvSceneSwitcher.selectMacro")); + for (auto &m : switcher->macros) { + list->addItem(QString::fromStdString(m.Name())); + } +} + +MacroConditionCounterEdit::MacroConditionCounterEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent) +{ + _macros = new QComboBox(); + _conditions = new QComboBox(); + _count = new QSpinBox(); + _currentCount = new QLabel(); + _resetCount = new QPushButton( + obs_module_text("AdvSceneSwitcher.condition.counter.reset")); + + _count->setMaximum(10000000); + + populateConditionSelection(_conditions); + populateMacroSelection(_macros); + + QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)), + this, SLOT(MacroChanged(const QString &))); + QWidget::connect(_conditions, 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())); + + QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this, + SLOT(MacroAdd(const QString &))); + QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this, + SLOT(MacroRemove(const QString &))); + QWidget::connect(parent, + SIGNAL(MacroRenamed(const QString &, const QString &)), + this, + SLOT(MacroRename(const QString &, const QString &))); + + QVBoxLayout *mainLayout = new QVBoxLayout; + QHBoxLayout *line1Layout = new QHBoxLayout; + QHBoxLayout *line2Layout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{macros}}", _macros}, + {"{{conditions}}", _conditions}, + {"{{count}}", _count}, + {"{{currentCount}}", _currentCount}, + {"{{resetCount}}", _resetCount}, + }; + 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); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroConditionCounterEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + if (_entryData->_macro) { + _macros->setCurrentText( + QString::fromStdString(_entryData->_macro->Name())); + } else { + _macros->setCurrentIndex(0); + } + _conditions->setCurrentIndex(static_cast(_entryData->_condition)); + _count->setValue(_entryData->_count); + ResetTimer(); +} + +void MacroConditionCounterEdit::MacroChanged(const QString &text) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_macro = GetMacroByQString(text); + ResetTimer(); +} + +void MacroConditionCounterEdit::CountChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_count = value; +} + +void MacroConditionCounterEdit::ConditionChanged(int cond) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_condition = static_cast(cond); +} + +void MacroConditionCounterEdit::MacroAdd(const QString &name) +{ + _macros->addItem(name); +} + +void MacroConditionCounterEdit::MacroRemove(const QString &name) +{ + int idx = _macros->findText(name); + if (idx == -1) { + return; + } + _macros->removeItem(idx); + if (_entryData && _entryData->_macro == GetMacroByQString(name)) { + std::lock_guard lock(switcher->m); + _entryData->_macro = nullptr; + } + _macros->setCurrentIndex(0); +} + +void MacroConditionCounterEdit::MacroRename(const QString &oldName, + const QString &newName) +{ + bool renameSelected = _macros->currentText() == oldName; + int idx = _macros->findText(oldName); + if (idx == -1) { + return; + } + _macros->removeItem(idx); + _macros->insertItem(idx, newName); + if (renameSelected) { + _macros->setCurrentIndex(_macros->findText(newName)); + } +} + +void MacroConditionCounterEdit::ResetClicked() +{ + if (_loading || !_entryData || !_entryData->_macro) { + return; + } + + _entryData->_macro->ResetCount(); + ResetTimer(); +} + +void MacroConditionCounterEdit::UpdateCount() +{ + if (_entryData && _entryData->_macro) { + _currentCount->setText( + QString::number(_entryData->_macro->GetCount())); + } else { + _currentCount->setText("-"); + } +} + +void MacroConditionCounterEdit::ResetTimer() +{ + _timer.reset(new QTimer(this)); + connect(_timer.get(), SIGNAL(timeout()), this, SLOT(UpdateCount())); + _timer->start(1000); +}