diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 8f8e2886..a0b7b687 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -1078,6 +1078,7 @@ AdvSceneSwitcher.action.variable.type.truncateValue="Truncate current value" AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values" AdvSceneSwitcher.action.variable.type.trim="Trim whitespace" AdvSceneSwitcher.action.variable.type.changeCase="Change case" +AdvSceneSwitcher.action.variable.type.randomNumber="Generate random number" AdvSceneSwitcher.action.variable.case.type.lowerCase="lowercase" AdvSceneSwitcher.action.variable.case.type.upperCase="UPPERCASE" AdvSceneSwitcher.action.variable.case.type.capitalized="Capitalized" @@ -1092,6 +1093,7 @@ AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with" AdvSceneSwitcher.action.variable.findAndReplace.replace.tooltip="Using \1, \2, etc. to represent first, second, etc. capture groups is supported." AdvSceneSwitcher.action.variable.subString.begin="Beginning" AdvSceneSwitcher.action.variable.subString.all="All" +AdvSceneSwitcher.action.variable.generateInteger="Only generate integers" 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!" @@ -1104,6 +1106,7 @@ AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMat AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}" AdvSceneSwitcher.action.variable.entry.userInput.customPrompt="{{useCustomPrompt}}Use custom prompt{{inputPrompt}}" AdvSceneSwitcher.action.variable.entry.userInput.placeholder="{{useInputPlaceholder}}Fill with placeholder{{inputPlaceholder}}" +AdvSceneSwitcher.action.variable.entry.randomNumber="Generate random number in range from{{randomNumberStart}}to{{randomNumberEnd}}" AdvSceneSwitcher.action.projector="Projector" AdvSceneSwitcher.action.projector.type.source="Source" AdvSceneSwitcher.action.projector.type.scene="Scene" diff --git a/lib/macro/macro-action-variable.cpp b/lib/macro/macro-action-variable.cpp index f8ae03de..322cc08b 100644 --- a/lib/macro/macro-action-variable.cpp +++ b/lib/macro/macro-action-variable.cpp @@ -8,6 +8,8 @@ #include "source-helpers.hpp" #include "utility.hpp" +#include + namespace advss { const std::string MacroActionVariable::id = "variable"; @@ -64,6 +66,8 @@ const static std::map actionTypes = { "AdvSceneSwitcher.action.variable.type.trim"}, {MacroActionVariable::Type::CHANGE_CASE, "AdvSceneSwitcher.action.variable.type.changeCase"}, + {MacroActionVariable::Type::RANDOM_NUMBER, + "AdvSceneSwitcher.action.variable.type.randomNumber"}, }; const static std::map caseTypes = { @@ -253,6 +257,27 @@ void MacroActionVariable::SetToSceneItemName(Variable *var) var->SetValue(data.name); } +void MacroActionVariable::GenerateRandomNumber(Variable *var) +{ + static std::random_device rd; + static std::mt19937 gen(rd()); + + double start = _randomNumberStart; + double end = _randomNumberEnd; + + if (start > end) { + std::swap(start, end); + } + + if (_generateInteger) { + std::uniform_int_distribution dis(start, end); + var->SetValue(dis(gen)); + } else { + std::uniform_real_distribution dis(start, end); + var->SetValue(dis(gen)); + } +} + struct AskForInputParams { AskForInputParams(const QString &prompt_, const QString &placeholder_) : prompt(prompt_), @@ -465,6 +490,9 @@ bool MacroActionVariable::PerformAction() case Type::CHANGE_CASE: HandleCaseChange(var.get()); return true; + case Type::RANDOM_NUMBER: + GenerateRandomNumber(var.get()); + return true; } return true; @@ -502,6 +530,9 @@ bool MacroActionVariable::Save(obs_data_t *obj) const _stringLength.Save(obj, "stringLength"); obs_data_set_int(obj, "paddingChar", _paddingChar); obs_data_set_int(obj, "caseType", static_cast(_caseType)); + _randomNumberStart.Save(obj, "randomNumberStart"); + _randomNumberEnd.Save(obj, "randomNumberEnd"); + obs_data_set_bool(obj, "generateInteger", _generateInteger); obs_data_set_int(obj, "version", 1); @@ -555,6 +586,10 @@ bool MacroActionVariable::Load(obs_data_t *obj) _regexMatchIdx.Load(obj, "regexMatchIdx"); } + _randomNumberStart.Load(obj, "randomNumberStart"); + _randomNumberEnd.Load(obj, "randomNumberEnd"); + _generateInteger = obs_data_get_bool(obj, "generateInteger"); + return true; } @@ -734,6 +769,13 @@ MacroActionVariableEdit::MacroActionVariableEdit( _stringLength(new VariableSpinBox(this)), _paddingCharSelection(new SingleCharSelection()), _caseType(new FilterComboBox(this)), + _randomNumberStart(new VariableDoubleSpinBox(this)), + _randomNumberEnd(new VariableDoubleSpinBox(this)), + _generateInteger(new QCheckBox( + obs_module_text( + "AdvSceneSwitcher.action.variable.generateInteger"), + this)), + _randomLayout(new QVBoxLayout()), _entryLayout(new QHBoxLayout()) { _numValue->setMinimum(-9999999999); @@ -759,6 +801,10 @@ MacroActionVariableEdit::MacroActionVariableEdit( populateTypeSelection(_actions); populateDirectionSelection(_direction); populateCaseTypeSelection(_caseType); + _randomNumberStart->setMinimum(-9999999999); + _randomNumberStart->setMaximum(9999999999); + _randomNumberEnd->setMinimum(-9999999999); + _randomNumberEnd->setMaximum(9999999999); QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)), this, SLOT(VariableChanged(const QString &))); @@ -833,6 +879,18 @@ MacroActionVariableEdit::MacroActionVariableEdit( SLOT(CharSelectionChanged(const QString &))); QWidget::connect(_caseType, SIGNAL(currentIndexChanged(int)), this, SLOT(CaseTypeChanged(int))); + QWidget::connect( + _randomNumberStart, + SIGNAL(NumberVariableChanged(const NumberVariable &)), + this, + SLOT(RandomNumberStartChanged(const NumberVariable &))); + QWidget::connect( + _randomNumberEnd, + SIGNAL(NumberVariableChanged(const NumberVariable &)), + this, + SLOT(RandomNumberEndChanged(const NumberVariable &))); + QWidget::connect(_generateInteger, SIGNAL(stateChanged(int)), this, + SLOT(GenerateIntegerChanged(int))); const std::unordered_map widgetPlaceholders = { {"{{variables}}", _variables}, @@ -861,6 +919,9 @@ MacroActionVariableEdit::MacroActionVariableEdit( {"{{stringLength}}", _stringLength}, {"{{paddingCharSelection}}", _paddingCharSelection}, {"{{caseType}}", _caseType}, + {"{{randomNumberStart}}", _randomNumberStart}, + {"{{randomNumberEnd}}", _randomNumberEnd}, + {"{{generateInteger}}", _generateInteger}, }; PlaceWidgets( obs_module_text("AdvSceneSwitcher.action.variable.entry.other"), @@ -890,6 +951,14 @@ MacroActionVariableEdit::MacroActionVariableEdit( "AdvSceneSwitcher.action.variable.entry.userInput.placeholder"), _placeholderLayout, widgetPlaceholders); + auto randomLayout = new QHBoxLayout(); + PlaceWidgets( + obs_module_text( + "AdvSceneSwitcher.action.variable.entry.randomNumber"), + randomLayout, widgetPlaceholders); + _randomLayout->addLayout(randomLayout); + _randomLayout->addWidget(_generateInteger); + auto regexConfigLayout = new QHBoxLayout; regexConfigLayout->addWidget(_substringRegex); regexConfigLayout->addStretch(); @@ -908,6 +977,7 @@ MacroActionVariableEdit::MacroActionVariableEdit( layout->addWidget(_mathExpressionResult); layout->addLayout(_promptLayout); layout->addLayout(_placeholderLayout); + layout->addLayout(_randomLayout); setLayout(layout); _entryData = entryData; @@ -963,6 +1033,9 @@ void MacroActionVariableEdit::UpdateEntryData() QChar::fromLatin1(_entryData->_paddingChar)); _caseType->setCurrentIndex( _caseType->findData(static_cast(_entryData->_caseType))); + _randomNumberStart->SetValue(_entryData->_randomNumberStart); + _randomNumberEnd->SetValue(_entryData->_randomNumberEnd); + _generateInteger->setChecked(_entryData->_generateInteger); SetWidgetVisibility(); } @@ -1385,6 +1458,26 @@ void MacroActionVariableEdit::CaseTypeChanged(int index) _caseType->itemData(index).toInt()); } +void MacroActionVariableEdit::RandomNumberStartChanged( + const NumberVariable &value) +{ + GUARD_LOADING_AND_LOCK(); + _entryData->_randomNumberStart = value; +} + +void MacroActionVariableEdit::RandomNumberEndChanged( + const NumberVariable &value) +{ + GUARD_LOADING_AND_LOCK(); + _entryData->_randomNumberEnd = value; +} + +void MacroActionVariableEdit::GenerateIntegerChanged(int value) +{ + GUARD_LOADING_AND_LOCK(); + _entryData->_generateInteger = value; +} + void MacroActionVariableEdit::SetWidgetVisibility() { if (!_entryData) { @@ -1534,6 +1627,9 @@ void MacroActionVariableEdit::SetWidgetVisibility() MacroActionVariable::Type::PAD); _caseType->setVisible(_entryData->_type == MacroActionVariable::Type::CHANGE_CASE); + SetLayoutVisible(_randomLayout, + _entryData->_type == + MacroActionVariable::Type::RANDOM_NUMBER); adjustSize(); updateGeometry(); diff --git a/lib/macro/macro-action-variable.hpp b/lib/macro/macro-action-variable.hpp index 1aeb3bc2..9cdd2351 100644 --- a/lib/macro/macro-action-variable.hpp +++ b/lib/macro/macro-action-variable.hpp @@ -52,6 +52,7 @@ public: SWAP_VALUES, TRIM, CHANGE_CASE, + RANDOM_NUMBER, }; Type _type = Type::SET_FIXED_VALUE; @@ -99,6 +100,9 @@ public: }; CaseType _caseType = CaseType::LOWER_CASE; + DoubleVariable _randomNumberStart = 0; + DoubleVariable _randomNumberEnd = 100; + bool _generateInteger = true; private: void DecrementCurrentSegmentVariableRef(); @@ -108,6 +112,7 @@ private: void HandleMathExpression(Variable *); void HandleCaseChange(Variable *); void SetToSceneItemName(Variable *); + void GenerateRandomNumber(Variable *); std::weak_ptr _macroSegment; int _segmentIdxLoadValue = -1; @@ -161,6 +166,9 @@ private slots: void StringLengthChanged(const NumberVariable &); void CharSelectionChanged(const QString &); void CaseTypeChanged(int index); + void RandomNumberStartChanged(const NumberVariable &); + void RandomNumberEndChanged(const NumberVariable &); + void GenerateIntegerChanged(int); signals: void HeaderInfoChanged(const QString &); @@ -206,6 +214,10 @@ private: VariableSpinBox *_stringLength; SingleCharSelection *_paddingCharSelection; FilterComboBox *_caseType; + VariableDoubleSpinBox *_randomNumberStart; + VariableDoubleSpinBox *_randomNumberEnd; + QCheckBox *_generateInteger; + QVBoxLayout *_randomLayout; QHBoxLayout *_entryLayout; std::shared_ptr _entryData;