From df8e84dd09ebc4aec881863e817c7343cdb47f21 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 7 Jan 2023 03:11:45 +0100 Subject: [PATCH] Add option to set variable value based on condition or action --- data/locale/en-US.ini | 10 +- data/locale/zh-CN.ini | 2 +- src/macro-core/macro-action-variable.cpp | 357 ++++++++++++++++++++--- src/macro-core/macro-action-variable.hpp | 24 +- 4 files changed, 344 insertions(+), 49 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 0c5d58c5..d136f430 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -574,12 +574,18 @@ AdvSceneSwitcher.action.http.type.post="POST" AdvSceneSwitcher.action.http.entry.line1="Send {{method}} to {{url}}" AdvSceneSwitcher.action.http.entry.line2="Timeout: {{timeout}} seconds" AdvSceneSwitcher.action.variable="Variable" -AdvSceneSwitcher.action.variable.type.set="Set" +AdvSceneSwitcher.action.variable.type.set="Set to fixed value" AdvSceneSwitcher.action.variable.type.append="Append" AdvSceneSwitcher.action.variable.type.appendVar="Append variable" AdvSceneSwitcher.action.variable.type.increment="Increment" AdvSceneSwitcher.action.variable.type.decrement="Decrement" -AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}" +AdvSceneSwitcher.action.variable.type.setActionValue="Set to action value" +AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value" +AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!" +AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!" +AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!" +AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:" +AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}" ; Transition Tab diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index 841f5212..c409852a 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -542,7 +542,7 @@ AdvSceneSwitcher.action.variable.type.append="追加" AdvSceneSwitcher.action.variable.type.appendVar="追加变量" AdvSceneSwitcher.action.variable.type.increment="增加" AdvSceneSwitcher.action.variable.type.decrement="减少" -AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}" +AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}" ; Transition Tab diff --git a/src/macro-core/macro-action-variable.cpp b/src/macro-core/macro-action-variable.cpp index 2ccb4187..67ded2ee 100644 --- a/src/macro-core/macro-action-variable.cpp +++ b/src/macro-core/macro-action-variable.cpp @@ -1,5 +1,6 @@ #include "macro-action-variable.hpp" #include "advanced-scene-switcher.hpp" +#include "macro-condition-edit.hpp" #include "utility.hpp" const std::string MacroActionVariable::id = "variable"; @@ -9,8 +10,8 @@ bool MacroActionVariable::_registered = MacroActionFactory::Register( {MacroActionVariable::Create, MacroActionVariableEdit::Create, "AdvSceneSwitcher.action.variable"}); -static std::map waitTypes = { - {MacroActionVariable::Type::SET, +static std::map actionTypes = { + {MacroActionVariable::Type::SET_FIXED_VALUE, "AdvSceneSwitcher.action.variable.type.set"}, {MacroActionVariable::Type::APPEND, "AdvSceneSwitcher.action.variable.type.append"}, @@ -20,6 +21,10 @@ static std::map waitTypes = { "AdvSceneSwitcher.action.variable.type.increment"}, {MacroActionVariable::Type::DECREMENT, "AdvSceneSwitcher.action.variable.type.decrement"}, + {MacroActionVariable::Type::SET_CONDITION_VALUE, + "AdvSceneSwitcher.action.variable.type.setConditionValue"}, + {MacroActionVariable::Type::SET_ACTION_VALUE, + "AdvSceneSwitcher.action.variable.type.setActionValue"}, }; static void apppend(Variable &var, const std::string &value) @@ -41,6 +46,11 @@ static void modifyNumValue(Variable &var, double val, const bool increment) } } +MacroActionVariable::~MacroActionVariable() +{ + DecrementCurrentSegmentVariableRef(); +} + bool MacroActionVariable::PerformAction() { auto var = GetVariableByName(_variableName); @@ -49,13 +59,13 @@ bool MacroActionVariable::PerformAction() } switch (_type) { - case MacroActionVariable::Type::SET: + case Type::SET_FIXED_VALUE: var->SetValue(_strValue); break; - case MacroActionVariable::Type::APPEND: + case Type::APPEND: apppend(*var, _strValue); break; - case MacroActionVariable::Type::APPEND_VAR: { + case Type::APPEND_VAR: { auto var2 = GetVariableByName(_variable2Name); if (!var2) { return true; @@ -63,12 +73,28 @@ bool MacroActionVariable::PerformAction() apppend(*var, var2->Value()); break; } - case MacroActionVariable::Type::INCREMENT: + case Type::INCREMENT: modifyNumValue(*var, _numValue, true); break; - case MacroActionVariable::Type::DECREMENT: + case Type::DECREMENT: modifyNumValue(*var, _numValue, false); break; + case Type::SET_CONDITION_VALUE: + case Type::SET_ACTION_VALUE: { + auto m = GetMacro(); + if (!m) { + return true; + } + if (GetSegmentIndexValue() == -1) { + return true; + } + auto segment = _macroSegment.lock(); + if (!segment) { + return true; + } + var->SetValue(segment->GetVariableValue()); + break; + } } return true; @@ -82,6 +108,7 @@ bool MacroActionVariable::Save(obs_data_t *obj) const obs_data_set_string(obj, "strValue", _strValue.c_str()); obs_data_set_double(obj, "numValue", _numValue); obs_data_set_int(obj, "condition", static_cast(_type)); + obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue()); return true; } @@ -93,6 +120,13 @@ bool MacroActionVariable::Load(obs_data_t *obj) _strValue = obs_data_get_string(obj, "strValue"); _numValue = obs_data_get_double(obj, "numValue"); _type = static_cast(obs_data_get_int(obj, "condition")); + _segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx"); + return true; +} + +bool MacroActionVariable::PostLoad() +{ + SetSegmentIndexValue(_segmentIdxLoadValue); return true; } @@ -101,9 +135,82 @@ std::string MacroActionVariable::GetShortDesc() const return _variableName; } +void MacroActionVariable::SetSegmentIndexValue(int value) +{ + DecrementCurrentSegmentVariableRef(); + + auto m = GetMacro(); + if (!m) { + _macroSegment.reset(); + return; + } + + if (value < 0) { + _macroSegment.reset(); + return; + } + + std::shared_ptr segment; + if (_type == Type::SET_CONDITION_VALUE) { + if (value < m->Conditions().size()) { + segment = m->Conditions().at(value); + } + } else if (_type == Type::SET_ACTION_VALUE) { + if (value < m->Actions().size()) { + segment = m->Actions().at(value); + } + } + + _macroSegment = segment; + if (segment) { + segment->IncrementVariableRef(); + } +} + +int MacroActionVariable::GetSegmentIndexValue() const +{ + auto m = GetMacro(); + if (!m) { + return -1; + } + + auto segment = _macroSegment.lock(); + if (!segment) { + return -1; + } + + if (_type == Type::SET_CONDITION_VALUE) { + auto it = std::find(m->Conditions().begin(), + m->Conditions().end(), segment); + if (it != m->Conditions().end()) { + return std::distance(m->Conditions().begin(), it); + } + return -1; + } else if (_type == Type::SET_ACTION_VALUE) { + auto it = std::find(m->Actions().begin(), m->Actions().end(), + segment); + if (it != m->Actions().end()) { + return std::distance(m->Actions().begin(), it); + } + return -1; + } + + return -1; +} + +void MacroActionVariable::DecrementCurrentSegmentVariableRef() +{ + auto segment = _macroSegment.lock(); + if (!segment) { + return; + } + + segment->DecrementVariableRef(); +} + static inline void populateTypeSelection(QComboBox *list) { - for (auto entry : waitTypes) { + for (auto entry : actionTypes) { list->addItem(obs_module_text(entry.second.c_str())); } } @@ -115,10 +222,17 @@ MacroActionVariableEdit::MacroActionVariableEdit( _variables2(new VariableSelection(this)), _actions(new QComboBox()), _strValue(new ResizingPlainTextEdit(this, 5, 1, 1)), - _numValue(new QDoubleSpinBox()) + _numValue(new QDoubleSpinBox()), + _segmentIdx(new QSpinBox()), + _segmentValueStatus(new QLabel()), + _segmentValue(new ResizingPlainTextEdit(this)) { _numValue->setMinimum(-9999999999); _numValue->setMaximum(9999999999); + _segmentIdx->setMinimum(0); + _segmentIdx->setMaximum(99); + _segmentIdx->setSpecialValueText("-"); + _segmentValue->setReadOnly(true); populateTypeSelection(_actions); QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)), @@ -131,21 +245,36 @@ MacroActionVariableEdit::MacroActionVariableEdit( SLOT(StrValueChanged())); QWidget::connect(_numValue, SIGNAL(valueChanged(double)), this, SLOT(NumValueChanged(double))); + QWidget::connect(_segmentIdx, SIGNAL(valueChanged(int)), this, + SLOT(SegmentIndexChanged(int))); + QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this, + SLOT(MacroSegmentOrderChanged())); std::unordered_map widgetPlaceholders = { - {"{{variables}}", _variables}, {"{{variables2}}", _variables2}, - {"{{actions}}", _actions}, {"{{strValue}}", _strValue}, + {"{{variables}}", _variables}, + {"{{variables2}}", _variables2}, + {"{{actions}}", _actions}, + {"{{strValue}}", _strValue}, {"{{numValue}}", _numValue}, + {"{{segmentIndex}}", _segmentIdx}, }; - - auto mainLayout = new QHBoxLayout; + auto entryLayout = new QHBoxLayout; placeWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"), - mainLayout, widgetPlaceholders); - setLayout(mainLayout); + entryLayout, widgetPlaceholders); + + auto layout = new QVBoxLayout; + layout->addLayout(entryLayout); + layout->addWidget(_segmentValueStatus); + layout->addWidget(_segmentValue); + setLayout(layout); _entryData = entryData; UpdateEntryData(); _loading = false; + + connect(&_timer, SIGNAL(timeout()), this, + SLOT(UpdateSegmentVariableValue())); + _timer.start(1500); } void MacroActionVariableEdit::UpdateEntryData() @@ -159,6 +288,7 @@ void MacroActionVariableEdit::UpdateEntryData() _actions->setCurrentIndex(static_cast(_entryData->_type)); _strValue->setPlainText(QString::fromStdString(_entryData->_strValue)); _numValue->setValue(_entryData->_numValue); + _segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1); SetWidgetVisibility(); } @@ -191,6 +321,12 @@ void MacroActionVariableEdit::ActionChanged(int value) std::lock_guard lock(switcher->m); _entryData->_type = static_cast(value); SetWidgetVisibility(); + + if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE || + _entryData->_type == + MacroActionVariable::Type::SET_CONDITION_VALUE) { + MarkSelectedSegment(); + } } void MacroActionVariableEdit::StrValueChanged() @@ -214,40 +350,175 @@ void MacroActionVariableEdit::NumValueChanged(double val) _entryData->_numValue = val; } +void MacroActionVariableEdit::SegmentIndexChanged(int val) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->SetSegmentIndexValue(val - 1); + MarkSelectedSegment(); +} + +void MacroActionVariableEdit::SetSegmentValueError(const QString &text) +{ + _segmentValueStatus->setText(text); + _segmentValue->setPlainText(""); + _segmentValue->hide(); + + adjustSize(); + updateGeometry(); +} + +void MacroActionVariableEdit::UpdateSegmentVariableValue() +{ + if (!_entryData || + !(_entryData->_type == + MacroActionVariable::Type::SET_CONDITION_VALUE || + _entryData->_type == + MacroActionVariable::Type::SET_ACTION_VALUE)) { + return; + } + + auto m = _entryData->GetMacro(); + if (!m) { + return; + } + + int index = _entryData->GetSegmentIndexValue(); + if (index < 0) { + SetSegmentValueError(obs_module_text( + "AdvSceneSwitcher.action.variable.invalidSelection")); + const QSignalBlocker b(_segmentIdx); + _segmentIdx->setValue(index); + return; + } + + std::shared_ptr segment; + if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) { + const auto &actions = m->Actions(); + if (index < actions.size()) { + segment = actions.at(index); + } + } else if (_entryData->_type == + MacroActionVariable::Type::SET_CONDITION_VALUE) { + const auto &conditions = m->Conditions(); + if (index < conditions.size()) { + segment = conditions.at(index); + } + } + + if (!segment) { + SetSegmentValueError(obs_module_text( + "AdvSceneSwitcher.action.variable.invalidSelection")); + return; + } + + if (!segment->SupportsVariableValue()) { + std::string type; + QString fmt; + + if (_entryData->_type == + MacroActionVariable::Type::SET_ACTION_VALUE) { + type = MacroActionFactory::GetActionName( + segment->GetId()); + fmt = QString(obs_module_text( + "AdvSceneSwitcher.action.variable.actionNoVariableSupport")); + } else if (_entryData->_type == + MacroActionVariable::Type::SET_CONDITION_VALUE) { + type = MacroConditionFactory::GetConditionName( + segment->GetId()); + fmt = QString(obs_module_text( + "AdvSceneSwitcher.action.variable.conditionNoVariableSupport")); + } + SetSegmentValueError( + fmt.arg(QString(obs_module_text(type.c_str())))); + return; + } + + _segmentValueStatus->setText(obs_module_text( + "AdvSceneSwitcher.action.variable.currentSegmentValue")); + _segmentValue->show(); + _segmentValue->setPlainText( + QString::fromStdString(segment->GetVariableValue())); + + adjustSize(); + updateGeometry(); +} + +void MacroActionVariableEdit::MacroSegmentOrderChanged() +{ + const QSignalBlocker b(_segmentIdx); + _segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1); +} + +void MacroActionVariableEdit::MarkSelectedSegment() +{ + if (switcher->disableHints) { + return; + } + + auto m = _entryData->GetMacro(); + if (!m) { + return; + } + + int index = _entryData->GetSegmentIndexValue(); + if (index < 0) { + return; + } + + if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) { + const auto &actions = m->Actions(); + if (index >= actions.size()) { + return; + } + AdvSceneSwitcher::window->HighlightAction( + index, QColor(Qt::lightGray)); + } else { + const auto &conditions = m->Conditions(); + if (index >= conditions.size()) { + return; + } + AdvSceneSwitcher::window->HighlightCondition( + index, QColor(Qt::lightGray)); + } + + PulseWidget(_segmentIdx, QColor(Qt::lightGray), QColor(0, 0, 0, 0), + true); +} + void MacroActionVariableEdit::SetWidgetVisibility() { if (!_entryData) { return; } - auto type = _entryData->_type; - switch (type) { - case MacroActionVariable::Type::SET: - _variables2->hide(); - _strValue->show(); - _numValue->hide(); - break; - case MacroActionVariable::Type::APPEND: - _variables2->hide(); - _strValue->show(); - _numValue->hide(); - break; - case MacroActionVariable::Type::APPEND_VAR: - _variables2->show(); - _strValue->hide(); - _numValue->hide(); - break; - case MacroActionVariable::Type::INCREMENT: - _variables2->hide(); - _strValue->hide(); - _numValue->show(); - break; - case MacroActionVariable::Type::DECREMENT: - _variables2->hide(); - _strValue->hide(); - _numValue->show(); - break; - } + _variables2->setVisible(_entryData->_type == + MacroActionVariable::Type::APPEND_VAR); + _strValue->setVisible( + _entryData->_type == + MacroActionVariable::Type::SET_FIXED_VALUE || + _entryData->_type == MacroActionVariable::Type::APPEND); + _numValue->setVisible( + _entryData->_type == MacroActionVariable::Type::INCREMENT || + _entryData->_type == MacroActionVariable::Type::DECREMENT); + _segmentValueStatus->setVisible( + _entryData->_type == + MacroActionVariable::Type::SET_ACTION_VALUE || + _entryData->_type == + MacroActionVariable::Type::SET_CONDITION_VALUE); + _segmentValue->setVisible( + _entryData->_type == + MacroActionVariable::Type::SET_ACTION_VALUE || + _entryData->_type == + MacroActionVariable::Type::SET_CONDITION_VALUE); + _segmentIdx->setVisible( + _entryData->_type == + MacroActionVariable::Type::SET_ACTION_VALUE || + _entryData->_type == + MacroActionVariable::Type::SET_CONDITION_VALUE); adjustSize(); updateGeometry(); diff --git a/src/macro-core/macro-action-variable.hpp b/src/macro-core/macro-action-variable.hpp index 56117ea1..488194a3 100644 --- a/src/macro-core/macro-action-variable.hpp +++ b/src/macro-core/macro-action-variable.hpp @@ -6,32 +6,41 @@ class MacroActionVariable : public MacroAction { public: MacroActionVariable(Macro *m) : MacroAction(m) {} + ~MacroActionVariable(); bool PerformAction(); bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); + bool PostLoad() override; std::string GetShortDesc() const; std::string GetId() const { return id; }; static std::shared_ptr Create(Macro *m) { return std::make_shared(m); } + void SetSegmentIndexValue(int); + int GetSegmentIndexValue() const; enum class Type { - SET, + SET_FIXED_VALUE, APPEND, APPEND_VAR, INCREMENT, DECREMENT, - //... + SET_CONDITION_VALUE, + SET_ACTION_VALUE, }; - Type _type = Type::SET; + Type _type = Type::SET_FIXED_VALUE; std::string _variableName = ""; std::string _variable2Name = ""; std::string _strValue = ""; double _numValue = 0; private: + void DecrementCurrentSegmentVariableRef(); + + std::weak_ptr _macroSegment; + int _segmentIdxLoadValue = -1; static bool _registered; static const std::string id; }; @@ -58,6 +67,9 @@ private slots: void ActionChanged(int); void StrValueChanged(); void NumValueChanged(double); + void SegmentIndexChanged(int val); + void UpdateSegmentVariableValue(); + void MacroSegmentOrderChanged(); signals: void HeaderInfoChanged(const QString &); @@ -67,11 +79,17 @@ protected: VariableSelection *_variables2; QComboBox *_actions; ResizingPlainTextEdit *_strValue; + QSpinBox *_segmentIdx; QDoubleSpinBox *_numValue; + QLabel *_segmentValueStatus; + ResizingPlainTextEdit *_segmentValue; std::shared_ptr _entryData; private: + void MarkSelectedSegment(); void SetWidgetVisibility(); + void SetSegmentValueError(const QString &); + QTimer _timer; bool _loading = true; };