From bf5d8ca19e5ca54368d4990bfb9a9b6e9c9a6853 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 11 Mar 2023 19:04:39 +0100 Subject: [PATCH] Add option to assign value of math expressions to variable --- data/locale/de-DE.ini | 2 +- data/locale/en-US.ini | 4 +- data/locale/zh-CN.ini | 2 +- src/macro-core/macro-action-variable.cpp | 71 +++++++++++++++++++++--- src/macro-core/macro-action-variable.hpp | 11 +++- 5 files changed, 77 insertions(+), 13 deletions(-) diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index a7ec06d8..46562e0f 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -587,7 +587,7 @@ AdvSceneSwitcher.action.variable.invalidSelection="Ungültige Auswahl!" AdvSceneSwitcher.action.variable.actionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Aktionen wird nicht unterstützt!" AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!" AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:" -AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}" +AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}" ; Transition Tab diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index ef55da27..adcb66ee 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -610,6 +610,8 @@ AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value" AdvSceneSwitcher.action.variable.type.roundToInt="Round to nearest integer" AdvSceneSwitcher.action.variable.type.subString="Set to substring of current value" AdvSceneSwitcher.action.variable.type.findAndReplace="Find and replace in current value" +AdvSceneSwitcher.action.variable.type.mathExpression="Mathematical expression" +AdvSceneSwitcher.action.variable.mathExpression.example="( 1 + 2 * 3 ) / 4" AdvSceneSwitcher.action.variable.findAndReplace.find="Text to find" AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with" AdvSceneSwitcher.action.variable.subString.begin="Beginning" @@ -618,7 +620,7 @@ 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}}" +AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}" AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}} Substring size:{{subStringSize}}" AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:" AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index 8a93efd5..26272fc1 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -541,7 +541,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}}{{segmentIndex}}" +AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}" ; Transition Tab diff --git a/src/macro-core/macro-action-variable.cpp b/src/macro-core/macro-action-variable.cpp index 7b6a9f8f..3fc20c0f 100644 --- a/src/macro-core/macro-action-variable.cpp +++ b/src/macro-core/macro-action-variable.cpp @@ -1,6 +1,7 @@ #include "macro-action-variable.hpp" #include "advanced-scene-switcher.hpp" #include "macro-condition-edit.hpp" +#include "math-helpers.hpp" #include "utility.hpp" const std::string MacroActionVariable::id = "variable"; @@ -31,6 +32,8 @@ static std::map actionTypes = { "AdvSceneSwitcher.action.variable.type.subString"}, {MacroActionVariable::Type::FIND_AND_REPLACE, "AdvSceneSwitcher.action.variable.type.findAndReplace"}, + {MacroActionVariable::Type::MATH_EXPRESSION, + "AdvSceneSwitcher.action.variable.type.mathExpression"}, }; static void apppend(Variable &var, const std::string &value) @@ -41,14 +44,14 @@ static void apppend(Variable &var, const std::string &value) static void modifyNumValue(Variable &var, double val, const bool increment) { - double current; - if (!var.DoubleValue(current)) { + auto current = var.DoubleValue(); + if (!current.has_value()) { return; } if (increment) { - var.SetValue(current + val); + var.SetValue(*current + val); } else { - var.SetValue(current - val); + var.SetValue(*current - val); } } @@ -104,6 +107,16 @@ void MacroActionVariable::HandleFindAndReplace(Variable *var) var->SetValue(value); } +void MacroActionVariable::HandleMathExpression(Variable *var) +{ + auto result = EvalMathExpression(_mathExpression); + if (std::holds_alternative(result)) { + blog(LOG_WARNING, "%s", std::get(result).c_str()); + return; + } + var->SetValue(std::get(result)); +} + bool MacroActionVariable::PerformAction() { auto var = GetVariableByName(_variableName); @@ -149,11 +162,11 @@ bool MacroActionVariable::PerformAction() break; } case Type::ROUND_TO_INT: { - double curValue; - if (!var->DoubleValue(curValue)) { + auto curValue = var->DoubleValue(); + if (!curValue.has_value()) { return true; } - var->SetValue(std::to_string(int(std::round(curValue)))); + var->SetValue(std::to_string(int(std::round(*curValue)))); return true; } case Type::SUBSTRING: { @@ -168,6 +181,10 @@ bool MacroActionVariable::PerformAction() HandleFindAndReplace(var); return true; } + case Type::MATH_EXPRESSION: { + HandleMathExpression(var); + return true; + } } return true; @@ -189,6 +206,7 @@ bool MacroActionVariable::Save(obs_data_t *obj) const obs_data_set_string(obj, "findStr", _findStr.c_str()); obs_data_set_string(obj, "replaceStr", _replaceStr.c_str()); _regex.Save(obj); + _mathExpression.Save(obj, "mathExpression"); return true; } @@ -208,6 +226,7 @@ bool MacroActionVariable::Load(obs_data_t *obj) _regexMatchIdx = obs_data_get_int(obj, "regexMatchIdx"); _findStr = obs_data_get_string(obj, "findStr"); _replaceStr = obs_data_get_string(obj, "replaceStr"); + _mathExpression.Load(obj, "mathExpression"); return true; } @@ -323,7 +342,9 @@ MacroActionVariableEdit::MacroActionVariableEdit( _regexMatchIdx(new QSpinBox()), _findReplaceLayout(new QHBoxLayout()), _findStr(new ResizingPlainTextEdit(this, 10, 1, 1)), - _replaceStr(new ResizingPlainTextEdit(this, 10, 1, 1)) + _replaceStr(new ResizingPlainTextEdit(this, 10, 1, 1)), + _mathExpression(new VariableLineEdit(this)), + _mathExpressionResult(new QLabel()) { _numValue->setMinimum(-9999999999); _numValue->setMaximum(9999999999); @@ -372,6 +393,8 @@ MacroActionVariableEdit::MacroActionVariableEdit( SLOT(FindStrValueChanged())); QWidget::connect(_replaceStr, SIGNAL(textChanged()), this, SLOT(ReplaceStrValueChanged())); + QWidget::connect(_mathExpression, SIGNAL(editingFinished()), this, + SLOT(MathExpressionChanged())); std::unordered_map widgetPlaceholders = { {"{{variables}}", _variables}, @@ -385,6 +408,7 @@ MacroActionVariableEdit::MacroActionVariableEdit( {"{{regexMatchIdx}}", _regexMatchIdx}, {"{{findStr}}", _findStr}, {"{{replaceStr}}", _replaceStr}, + {"{{mathExpression}}", _mathExpression}, }; auto entryLayout = new QHBoxLayout; placeWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"), @@ -420,6 +444,7 @@ MacroActionVariableEdit::MacroActionVariableEdit( layout->addWidget(_segmentValueStatus); layout->addWidget(_segmentValue); layout->addLayout(_findReplaceLayout); + layout->addWidget(_mathExpressionResult); setLayout(layout); _entryData = entryData; @@ -453,6 +478,7 @@ void MacroActionVariableEdit::UpdateEntryData() _findStr->setPlainText(QString::fromStdString(_entryData->_findStr)); _replaceStr->setPlainText( QString::fromStdString(_entryData->_replaceStr)); + _mathExpression->setText(_entryData->_mathExpression); SetWidgetVisibility(); } @@ -502,6 +528,7 @@ void MacroActionVariableEdit::StrValueChanged() std::lock_guard lock(switcher->m); _entryData->_strValue = _strValue->toPlainText().toStdString(); adjustSize(); + updateGeometry(); } void MacroActionVariableEdit::NumValueChanged(double val) @@ -658,6 +685,7 @@ void MacroActionVariableEdit::RegexPatternChanged() std::lock_guard lock(switcher->m); _entryData->_regexPattern = _regexPattern->toPlainText().toStdString(); adjustSize(); + updateGeometry(); } void MacroActionVariableEdit::RegexMatchIdxChanged(int val) @@ -679,6 +707,7 @@ void MacroActionVariableEdit::FindStrValueChanged() std::lock_guard lock(switcher->m); _entryData->_findStr = _findStr->toPlainText().toStdString(); adjustSize(); + updateGeometry(); } void MacroActionVariableEdit::ReplaceStrValueChanged() @@ -690,6 +719,29 @@ void MacroActionVariableEdit::ReplaceStrValueChanged() std::lock_guard lock(switcher->m); _entryData->_replaceStr = _replaceStr->toPlainText().toStdString(); adjustSize(); + updateGeometry(); +} + +void MacroActionVariableEdit::MathExpressionChanged() +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_mathExpression = _mathExpression->text().toStdString(); + + // In case of invalid expression display an error + auto result = EvalMathExpression(_entryData->_mathExpression); + auto hasError = std::holds_alternative(result); + if (hasError) { + _mathExpressionResult->setText( + QString::fromStdString(std::get(result))); + } + _mathExpressionResult->setVisible(hasError); + + adjustSize(); + updateGeometry(); } void MacroActionVariableEdit::MarkSelectedSegment() @@ -770,6 +822,9 @@ void MacroActionVariableEdit::SetWidgetVisibility() setLayoutVisible(_findReplaceLayout, _entryData->_type == MacroActionVariable::Type::FIND_AND_REPLACE); + _mathExpression->setVisible(_entryData->_type == + MacroActionVariable::Type::MATH_EXPRESSION); + _mathExpressionResult->hide(); adjustSize(); updateGeometry(); diff --git a/src/macro-core/macro-action-variable.hpp b/src/macro-core/macro-action-variable.hpp index 3a919991..ae811bb4 100644 --- a/src/macro-core/macro-action-variable.hpp +++ b/src/macro-core/macro-action-variable.hpp @@ -1,8 +1,8 @@ #pragma once #include "macro-action-edit.hpp" -#include "resizing-text-edit.hpp" #include "regex-config.hpp" -#include "variable.hpp" +#include "resizing-text-edit.hpp" +#include "variable-line-edit.hpp" class MacroActionVariable : public MacroAction { public: @@ -32,6 +32,7 @@ public: ROUND_TO_INT, SUBSTRING, FIND_AND_REPLACE, + MATH_EXPRESSION, }; Type _type = Type::SET_FIXED_VALUE; @@ -48,12 +49,15 @@ public: "AdvSceneSwitcher.action.variable.findAndReplace.find"); std::string _replaceStr = obs_module_text( "AdvSceneSwitcher.action.variable.findAndReplace.replace"); + StringVariable _mathExpression = obs_module_text( + "AdvSceneSwitcher.action.variable.mathExpression.example"); private: void DecrementCurrentSegmentVariableRef(); void HandleIndexSubString(Variable *); void HandleRegexSubString(Variable *); void HandleFindAndReplace(Variable *); + void HandleMathExpression(Variable *); std::weak_ptr _macroSegment; int _segmentIdxLoadValue = -1; @@ -93,6 +97,7 @@ private slots: void RegexMatchIdxChanged(int val); void FindStrValueChanged(); void ReplaceStrValueChanged(); + void MathExpressionChanged(); signals: void HeaderInfoChanged(const QString &); @@ -117,6 +122,8 @@ protected: QHBoxLayout *_findReplaceLayout; ResizingPlainTextEdit *_findStr; ResizingPlainTextEdit *_replaceStr; + VariableLineEdit *_mathExpression; + QLabel *_mathExpressionResult; std::shared_ptr _entryData; private: