mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-10-25 10:02:41 -05:00
Refactor "Variable" action
This commit is contained in:
@@ -113,6 +113,22 @@ target_sources(
|
||||
lib/macro/macro-action-macro.hpp
|
||||
lib/macro/macro-action-queue.cpp
|
||||
lib/macro/macro-action-queue.hpp
|
||||
lib/macro/macro-action-variable-basic.cpp
|
||||
lib/macro/macro-action-variable-basic.hpp
|
||||
lib/macro/macro-action-variable-group.cpp
|
||||
lib/macro/macro-action-variable-group.hpp
|
||||
lib/macro/macro-action-variable-input.cpp
|
||||
lib/macro/macro-action-variable-input.hpp
|
||||
lib/macro/macro-action-variable-json.cpp
|
||||
lib/macro/macro-action-variable-json.hpp
|
||||
lib/macro/macro-action-variable-macro.cpp
|
||||
lib/macro/macro-action-variable-macro.hpp
|
||||
lib/macro/macro-action-variable-math.cpp
|
||||
lib/macro/macro-action-variable-math.hpp
|
||||
lib/macro/macro-action-variable-scene.cpp
|
||||
lib/macro/macro-action-variable-scene.hpp
|
||||
lib/macro/macro-action-variable-string.cpp
|
||||
lib/macro/macro-action-variable-string.hpp
|
||||
lib/macro/macro-action-variable.cpp
|
||||
lib/macro/macro-action-variable.hpp
|
||||
lib/macro/macro-action.cpp
|
||||
|
||||
@@ -1426,7 +1426,19 @@ 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.layout.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}{{caseType}}{{jsonQuery}}{{jsonQueryHelp}}{{jsonIndex}}"
|
||||
AdvSceneSwitcher.action.variable.layout.default="{{actions}}{{variables}}"
|
||||
AdvSceneSwitcher.action.variable.layout.strValue="{{actions}}{{variables}}{{strValue}}"
|
||||
AdvSceneSwitcher.action.variable.layout.variable2="{{actions}}{{variables}}{{variables2}}"
|
||||
AdvSceneSwitcher.action.variable.layout.changeCase="{{actions}}{{variables}}{{caseType}}"
|
||||
AdvSceneSwitcher.action.variable.layout.queryJson="{{actions}}{{variables}}{{jsonQuery}}{{jsonQueryHelp}}"
|
||||
AdvSceneSwitcher.action.variable.layout.accessJsonArray="{{actions}}{{variables}}{{jsonIndex}}"
|
||||
AdvSceneSwitcher.action.variable.layout.setToTempvar="{{actions}}{{variables}}{{tempVars}}{{tempVarsHelp}}"
|
||||
AdvSceneSwitcher.action.variable.layout.segmentValue="{{actions}}{{variables}}{{segmentIndex}}"
|
||||
AdvSceneSwitcher.action.variable.layout.mathExpression="{{actions}}{{variables}}{{mathExpression}}"
|
||||
AdvSceneSwitcher.action.variable.layout.numValue="{{actions}}{{variables}}{{numValue}}"
|
||||
AdvSceneSwitcher.action.variable.layout.environmentVariable="{{actions}}{{variables}}{{envVariableName}}"
|
||||
AdvSceneSwitcher.action.variable.layout.sceneItemName="{{actions}}{{variables}}{{scenes}}{{sceneItemIndex}}"
|
||||
AdvSceneSwitcher.action.variable.layout.sceneItemCount="{{actions}}{{variables}}{{scenes}}"
|
||||
AdvSceneSwitcher.action.variable.layout.copy="{{actions}}{{variables2}}to{{variables}}"
|
||||
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}"
|
||||
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}"
|
||||
|
||||
@@ -1374,7 +1374,6 @@ AdvSceneSwitcher.action.variable.invalidSelection="无效的选择!"
|
||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="不支持从 %1 操作获取变量值!"
|
||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="不支持从 %1 条件获取变量值!"
|
||||
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
|
||||
AdvSceneSwitcher.action.variable.layout.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}{{caseType}}{{jsonQuery}}{{jsonQueryHelp}}{{jsonIndex}}"
|
||||
AdvSceneSwitcher.action.variable.layout.copy="{{actions}}{{variables2}}到{{variables}}"
|
||||
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}{{variables}}到长度{{stringLength}}通过向{{direction}}添加{{paddingCharSelection}}"
|
||||
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}{{variables}}到长度{{stringLength}}通过从{{direction}}删除字符"
|
||||
|
||||
99
lib/macro/macro-action-variable-basic.cpp
Normal file
99
lib/macro/macro-action-variable-basic.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "macro-action-variable-basic.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
using Action = MacroActionVariable::Action;
|
||||
|
||||
static bool registered = RegisterVariableActionGroup(
|
||||
{0,
|
||||
{
|
||||
{Action::SET_VALUE, "AdvSceneSwitcher.action.variable.type.set",
|
||||
"AdvSceneSwitcher.action.variable.layout.strValue", true},
|
||||
{Action::COPY_VAR, "AdvSceneSwitcher.action.variable.type.copy",
|
||||
"AdvSceneSwitcher.action.variable.layout.copy"},
|
||||
{Action::APPEND, "AdvSceneSwitcher.action.variable.type.append",
|
||||
"AdvSceneSwitcher.action.variable.layout.strValue", true},
|
||||
{Action::APPEND_VAR,
|
||||
"AdvSceneSwitcher.action.variable.type.appendVar",
|
||||
"AdvSceneSwitcher.action.variable.layout.variable2"},
|
||||
{Action::SWAP_VALUES,
|
||||
"AdvSceneSwitcher.action.variable.type.swapValues",
|
||||
"AdvSceneSwitcher.action.variable.layout.variable2"},
|
||||
},
|
||||
[]() { return std::make_unique<VariableActionBasic>(); },
|
||||
VariableActionBasicEdit::Create});
|
||||
|
||||
static void apppend(Variable &var, const std::string &value)
|
||||
{
|
||||
auto currentValue = var.Value();
|
||||
var.SetValue(currentValue + value);
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableActionGroup> VariableActionBasic::Copy() const
|
||||
{
|
||||
return std::make_unique<VariableActionBasic>(*this);
|
||||
}
|
||||
|
||||
bool VariableActionBasic::Perform(MacroActionVariable &action,
|
||||
MacroActionVariable::Action type,
|
||||
Variable &var)
|
||||
{
|
||||
switch (type) {
|
||||
case Action::SET_VALUE:
|
||||
var.SetValue(action._strValue);
|
||||
break;
|
||||
case Action::APPEND:
|
||||
apppend(var, action._strValue);
|
||||
break;
|
||||
case Action::COPY_VAR: {
|
||||
auto var2 = action._variable2.lock();
|
||||
if (!var2) {
|
||||
return true;
|
||||
}
|
||||
var.SetValue(var2->Value());
|
||||
break;
|
||||
}
|
||||
case Action::APPEND_VAR: {
|
||||
auto var2 = action._variable2.lock();
|
||||
if (!var2) {
|
||||
return true;
|
||||
}
|
||||
apppend(var, var2->Value());
|
||||
break;
|
||||
}
|
||||
case Action::SWAP_VALUES: {
|
||||
auto var2 = action._variable2.lock();
|
||||
if (!var2) {
|
||||
return true;
|
||||
}
|
||||
auto tempValue = var.Value();
|
||||
var.SetValue(var2->Value());
|
||||
var2->SetValue(tempValue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VariableActionBasicEdit::VariableActionBasicEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: VariableActionGroupEdit(parent, entryData)
|
||||
{
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
VariableActionGroupEdit *
|
||||
VariableActionBasicEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData)
|
||||
{
|
||||
return new VariableActionBasicEdit(parent, entryData);
|
||||
}
|
||||
|
||||
void VariableActionBasicEdit::SetWidgetVisibility(MacroActionVariable::Action)
|
||||
{
|
||||
hide();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
25
lib/macro/macro-action-variable-basic.hpp
Normal file
25
lib/macro/macro-action-variable-basic.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable-group.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionBasic : public VariableActionGroup {
|
||||
public:
|
||||
std::unique_ptr<VariableActionGroup> Copy() const override;
|
||||
bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) override;
|
||||
};
|
||||
|
||||
class VariableActionBasicEdit : public VariableActionGroupEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionBasicEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
static VariableActionGroupEdit *
|
||||
Create(QWidget *parent, std::shared_ptr<MacroActionVariable> entryData);
|
||||
void UpdateEntryData() override {}
|
||||
void SetWidgetVisibility(MacroActionVariable::Action) override;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
83
lib/macro/macro-action-variable-group.cpp
Normal file
83
lib/macro/macro-action-variable-group.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "macro-action-variable-group.hpp"
|
||||
#include "log-helper.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace advss {
|
||||
|
||||
static std::vector<VariableActionGroupInfo> &getGroups()
|
||||
{
|
||||
static std::vector<VariableActionGroupInfo> groups;
|
||||
return groups;
|
||||
}
|
||||
|
||||
bool RegisterVariableActionGroup(const VariableActionGroupInfo &info)
|
||||
{
|
||||
for (const auto &option : info.options) {
|
||||
if (GetVariableActionGroupIndex(option.action) != -1) {
|
||||
blog(LOG_WARNING,
|
||||
"variable action option %d already registered",
|
||||
static_cast<int>(option.action));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto &groups = getGroups();
|
||||
auto it = std::upper_bound(groups.begin(), groups.end(), info,
|
||||
[](const VariableActionGroupInfo &a,
|
||||
const VariableActionGroupInfo &b) {
|
||||
return a.order < b.order;
|
||||
});
|
||||
groups.insert(it, info);
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<VariableActionGroupInfo> &GetVariableActionGroups()
|
||||
{
|
||||
return getGroups();
|
||||
}
|
||||
|
||||
int GetVariableActionGroupIndex(MacroActionVariable::Action action)
|
||||
{
|
||||
const auto &groups = getGroups();
|
||||
for (size_t idx = 0; idx < groups.size(); idx++) {
|
||||
for (const auto &option : groups[idx].options) {
|
||||
if (option.action == action) {
|
||||
return static_cast<int>(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const VariableActionOption *
|
||||
GetVariableActionOption(MacroActionVariable::Action action)
|
||||
{
|
||||
for (const auto &group : getGroups()) {
|
||||
for (const auto &option : group.options) {
|
||||
if (option.action == action) {
|
||||
return &option;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VariableActionGroupEdit::VariableActionGroupEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: QWidget(parent),
|
||||
_entryData(entryData)
|
||||
{
|
||||
}
|
||||
|
||||
void VariableActionGroupEdit::UpdateSize()
|
||||
{
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
if (auto parent = parentWidget()) {
|
||||
parent->adjustSize();
|
||||
parent->updateGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
73
lib/macro/macro-action-variable-group.hpp
Normal file
73
lib/macro/macro-action-variable-group.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace advss {
|
||||
|
||||
struct VariableActionOption {
|
||||
MacroActionVariable::Action action;
|
||||
const char *label;
|
||||
const char *layout = "AdvSceneSwitcher.action.variable.layout.default";
|
||||
bool expandInlineRow = false;
|
||||
};
|
||||
|
||||
class VariableActionGroup {
|
||||
public:
|
||||
virtual ~VariableActionGroup() = default;
|
||||
virtual std::unique_ptr<VariableActionGroup> Copy() const = 0;
|
||||
virtual void Save(obs_data_t *, const MacroActionVariable &) const {}
|
||||
virtual void Load(obs_data_t *, MacroActionVariable &) {}
|
||||
virtual void PostLoad(MacroActionVariable &) {}
|
||||
virtual void ResolveVariables() {}
|
||||
virtual std::vector<TempVariableRef> GetTempVarRefs() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
// Returning false aborts the macro
|
||||
virtual bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) = 0;
|
||||
};
|
||||
|
||||
class VariableActionGroupEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionGroupEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
virtual std::unordered_map<std::string, QWidget *> GetInlineWidgets()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
virtual void UpdateEntryData() = 0;
|
||||
virtual void SetWidgetVisibility(MacroActionVariable::Action) = 0;
|
||||
|
||||
protected:
|
||||
void UpdateSize();
|
||||
|
||||
std::shared_ptr<MacroActionVariable> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
struct VariableActionGroupInfo {
|
||||
int order;
|
||||
std::vector<VariableActionOption> options;
|
||||
std::function<std::unique_ptr<VariableActionGroup>()> createData;
|
||||
std::function<VariableActionGroupEdit *(
|
||||
QWidget *, std::shared_ptr<MacroActionVariable>)>
|
||||
createEdit;
|
||||
};
|
||||
|
||||
bool RegisterVariableActionGroup(const VariableActionGroupInfo &);
|
||||
const std::vector<VariableActionGroupInfo> &GetVariableActionGroups();
|
||||
int GetVariableActionGroupIndex(MacroActionVariable::Action);
|
||||
const VariableActionOption *
|
||||
GetVariableActionOption(MacroActionVariable::Action);
|
||||
|
||||
} // namespace advss
|
||||
324
lib/macro/macro-action-variable-input.cpp
Normal file
324
lib/macro/macro-action-variable-input.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
#include "macro-action-variable-input.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "non-modal-dialog.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace advss {
|
||||
|
||||
using Action = MacroActionVariable::Action;
|
||||
|
||||
static bool registered = RegisterVariableActionGroup(
|
||||
{50,
|
||||
{
|
||||
{Action::USER_INPUT,
|
||||
"AdvSceneSwitcher.action.variable.type.askForValue"},
|
||||
{Action::ENV_VARIABLE,
|
||||
"AdvSceneSwitcher.action.variable.type.environmentVariable",
|
||||
"AdvSceneSwitcher.action.variable.layout.environmentVariable",
|
||||
true},
|
||||
},
|
||||
[]() { return std::make_unique<VariableActionInput>(); },
|
||||
VariableActionInputEdit::Create});
|
||||
|
||||
struct AskForInputParams {
|
||||
AskForInputParams(const QString &prompt_, const QString &placeholder_,
|
||||
ValueInputType type_, const QStringList &options_)
|
||||
: prompt(prompt_),
|
||||
placeholder(placeholder_),
|
||||
type(type_),
|
||||
options(options_){};
|
||||
QString prompt;
|
||||
QString placeholder;
|
||||
ValueInputType type;
|
||||
QStringList options;
|
||||
std::optional<std::string> result;
|
||||
std::atomic_bool resultReady = {false};
|
||||
};
|
||||
|
||||
static void askForInput(void *param)
|
||||
{
|
||||
auto parameters =
|
||||
*static_cast<std::shared_ptr<AskForInputParams> *>(param);
|
||||
NonModalMessageDialog *dialog = nullptr;
|
||||
if (parameters->type == ValueInputType::String) {
|
||||
dialog = new NonModalMessageDialog(
|
||||
parameters->prompt, NonModalMessageDialog::Type::INPUT,
|
||||
false);
|
||||
dialog->SetInput(parameters->placeholder);
|
||||
} else {
|
||||
dialog = new NonModalMessageDialog(
|
||||
parameters->prompt, parameters->type,
|
||||
parameters->placeholder.toStdString(),
|
||||
parameters->options);
|
||||
}
|
||||
parameters->result = dialog->GetInput();
|
||||
parameters->resultReady = true;
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableActionGroup> VariableActionInput::Copy() const
|
||||
{
|
||||
return std::make_unique<VariableActionInput>(*this);
|
||||
}
|
||||
|
||||
void VariableActionInput::Save(obs_data_t *obj,
|
||||
const MacroActionVariable &) const
|
||||
{
|
||||
obs_data_set_bool(obj, "useCustomPrompt", _useCustomPrompt);
|
||||
_inputPrompt.Save(obj, "inputPrompt");
|
||||
obs_data_set_bool(obj, "useInputPlaceholder", _useInputPlaceholder);
|
||||
_inputPlaceholder.Save(obj, "inputPlaceholder");
|
||||
obs_data_set_int(obj, "inputType", static_cast<int>(_inputType));
|
||||
_inputOptions.Save(obj, "inputOptions", "value");
|
||||
_envVariableName.Save(obj, "environmentVariableName");
|
||||
}
|
||||
|
||||
void VariableActionInput::Load(obs_data_t *obj, MacroActionVariable &)
|
||||
{
|
||||
_useCustomPrompt = obs_data_get_bool(obj, "useCustomPrompt");
|
||||
_inputPrompt.Load(obj, "inputPrompt");
|
||||
_useInputPlaceholder = obs_data_get_bool(obj, "useInputPlaceholder");
|
||||
_inputPlaceholder.Load(obj, "inputPlaceholder");
|
||||
obs_data_set_default_int(obj, "inputType",
|
||||
static_cast<int>(ValueInputType::String));
|
||||
_inputType =
|
||||
static_cast<ValueInputType>(obs_data_get_int(obj, "inputType"));
|
||||
_inputOptions.Load(obj, "inputOptions", "value");
|
||||
_envVariableName.Load(obj, "environmentVariableName");
|
||||
}
|
||||
|
||||
void VariableActionInput::ResolveVariables()
|
||||
{
|
||||
_inputPrompt.ResolveVariables();
|
||||
_inputPlaceholder.ResolveVariables();
|
||||
_inputOptions.ResolveVariables();
|
||||
_envVariableName.ResolveVariables();
|
||||
}
|
||||
|
||||
bool VariableActionInput::AskForUserInput(MacroActionVariable &action,
|
||||
Variable &var)
|
||||
{
|
||||
QStringList options;
|
||||
for (const auto &option : _inputOptions) {
|
||||
options << QString::fromStdString(option);
|
||||
}
|
||||
auto params = std::make_shared<AskForInputParams>(
|
||||
_useCustomPrompt
|
||||
? QString::fromStdString(_inputPrompt)
|
||||
: QString(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.askForValuePromptDefault"))
|
||||
.arg(QString::fromStdString(var.Name())),
|
||||
_useCustomPrompt && _useInputPlaceholder
|
||||
? QString::fromStdString(_inputPlaceholder)
|
||||
: "",
|
||||
_inputType, options);
|
||||
obs_queue_task(OBS_TASK_UI, askForInput, ¶ms, false);
|
||||
while (!params->resultReady) {
|
||||
if (action.GetMacro()->GetStop()) {
|
||||
return false;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
if (!params->result.has_value()) {
|
||||
return true;
|
||||
}
|
||||
var.SetValue(*params->result);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VariableActionInput::Perform(MacroActionVariable &action,
|
||||
MacroActionVariable::Action type,
|
||||
Variable &var)
|
||||
{
|
||||
switch (type) {
|
||||
case Action::USER_INPUT:
|
||||
return AskForUserInput(action, var);
|
||||
case Action::ENV_VARIABLE: {
|
||||
auto value = std::getenv(_envVariableName.c_str());
|
||||
if (value) {
|
||||
var.SetValue(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
VariableActionInputEdit::VariableActionInputEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: VariableActionGroupEdit(parent, entryData),
|
||||
_data(entryData ? entryData->GetGroup<VariableActionInput>()
|
||||
: nullptr),
|
||||
_promptLayout(new QHBoxLayout()),
|
||||
_useCustomPrompt(new QCheckBox(this)),
|
||||
_inputPrompt(new VariableLineEdit(this)),
|
||||
_placeholderLayout(new QHBoxLayout()),
|
||||
_useInputPlaceholder(new QCheckBox(this)),
|
||||
_inputPlaceholder(new VariableLineEdit(this)),
|
||||
_inputTypeLayout(new QHBoxLayout()),
|
||||
_inputType(new QComboBox(this)),
|
||||
_inputOptions(new StringListEdit(this)),
|
||||
_envVariable(new VariableLineEdit(this))
|
||||
{
|
||||
_inputPrompt->setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::Preferred);
|
||||
_inputOptions->SetMaxStringSize(99999999);
|
||||
PopulateValueInputTypeSelection(_inputType);
|
||||
|
||||
QWidget::connect(_useCustomPrompt, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(UseCustomPromptChanged(int)));
|
||||
QWidget::connect(_inputPrompt, SIGNAL(editingFinished()), this,
|
||||
SLOT(InputPromptChanged()));
|
||||
QWidget::connect(_useInputPlaceholder, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(UseInputPlaceholderChanged(int)));
|
||||
QWidget::connect(_inputPlaceholder, SIGNAL(editingFinished()), this,
|
||||
SLOT(InputPlaceholderChanged()));
|
||||
QWidget::connect(_inputType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(InputTypeChanged(int)));
|
||||
QWidget::connect(_inputOptions,
|
||||
SIGNAL(StringListChanged(const StringList &)), this,
|
||||
SLOT(InputOptionsChanged(const StringList &)));
|
||||
QWidget::connect(_envVariable, SIGNAL(editingFinished()), this,
|
||||
SLOT(EnvVariableChanged()));
|
||||
|
||||
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{useCustomPrompt}}", _useCustomPrompt},
|
||||
{"{{inputPrompt}}", _inputPrompt},
|
||||
{"{{useInputPlaceholder}}", _useInputPlaceholder},
|
||||
{"{{inputPlaceholder}}", _inputPlaceholder},
|
||||
{"{{inputType}}", _inputType},
|
||||
};
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.layout.userInput.type"),
|
||||
_inputTypeLayout, widgetPlaceholders);
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.layout.userInput.customPrompt"),
|
||||
_promptLayout, widgetPlaceholders);
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.layout.userInput.placeholder"),
|
||||
_placeholderLayout, widgetPlaceholders);
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addLayout(_inputTypeLayout);
|
||||
layout->addWidget(_inputOptions);
|
||||
layout->addLayout(_promptLayout);
|
||||
layout->addLayout(_placeholderLayout);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
VariableActionGroupEdit *
|
||||
VariableActionInputEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData)
|
||||
{
|
||||
return new VariableActionInputEdit(parent, entryData);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, QWidget *>
|
||||
VariableActionInputEdit::GetInlineWidgets()
|
||||
{
|
||||
return {{"{{envVariableName}}", _envVariable}};
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
_useCustomPrompt->setChecked(_data->_useCustomPrompt);
|
||||
_inputPrompt->setText(_data->_inputPrompt);
|
||||
_useInputPlaceholder->setChecked(_data->_useInputPlaceholder);
|
||||
_inputPlaceholder->setText(_data->_inputPlaceholder);
|
||||
_inputType->setCurrentIndex(
|
||||
_inputType->findData(static_cast<int>(_data->_inputType)));
|
||||
_inputOptions->SetStringList(_data->_inputOptions);
|
||||
_envVariable->setText(_data->_envVariableName);
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::SetWidgetVisibility(
|
||||
MacroActionVariable::Action action)
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isUserInput = action == Action::USER_INPUT;
|
||||
SetLayoutVisible(_inputTypeLayout, isUserInput);
|
||||
_inputOptions->setVisible(
|
||||
isUserInput && _data->_inputType == ValueInputType::Selection);
|
||||
SetLayoutVisible(_promptLayout, isUserInput);
|
||||
_inputPrompt->setVisible(isUserInput && _data->_useCustomPrompt);
|
||||
if (_data->_useCustomPrompt) {
|
||||
RemoveStretchIfPresent(_promptLayout);
|
||||
} else {
|
||||
AddStretchIfNecessary(_promptLayout);
|
||||
}
|
||||
SetLayoutVisible(_placeholderLayout,
|
||||
isUserInput && _data->_useCustomPrompt);
|
||||
_useInputPlaceholder->setVisible(isUserInput &&
|
||||
_data->_useCustomPrompt);
|
||||
_inputPlaceholder->setVisible(isUserInput && _data->_useCustomPrompt &&
|
||||
_data->_useInputPlaceholder);
|
||||
if (_data->_useInputPlaceholder) {
|
||||
RemoveStretchIfPresent(_placeholderLayout);
|
||||
} else {
|
||||
AddStretchIfNecessary(_placeholderLayout);
|
||||
}
|
||||
setVisible(isUserInput);
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::UseCustomPromptChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_useCustomPrompt = value;
|
||||
SetWidgetVisibility(_entryData->_action);
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::InputPromptChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_inputPrompt = _inputPrompt->text().toStdString();
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::UseInputPlaceholderChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_useInputPlaceholder = value;
|
||||
SetWidgetVisibility(_entryData->_action);
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::InputPlaceholderChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_inputPlaceholder = _inputPlaceholder->text().toStdString();
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::InputTypeChanged(int)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_inputType =
|
||||
static_cast<ValueInputType>(_inputType->currentData().toInt());
|
||||
SetWidgetVisibility(_entryData->_action);
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::InputOptionsChanged(const StringList &options)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_inputOptions = options;
|
||||
}
|
||||
|
||||
void VariableActionInputEdit::EnvVariableChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_envVariableName = _envVariable->text().toStdString();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
72
lib/macro/macro-action-variable-input.hpp
Normal file
72
lib/macro/macro-action-variable-input.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable-group.hpp"
|
||||
#include "string-list.hpp"
|
||||
#include "value-input.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionInput : public VariableActionGroup {
|
||||
public:
|
||||
std::unique_ptr<VariableActionGroup> Copy() const override;
|
||||
void Save(obs_data_t *, const MacroActionVariable &) const override;
|
||||
void Load(obs_data_t *, MacroActionVariable &) override;
|
||||
void ResolveVariables() override;
|
||||
bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) override;
|
||||
|
||||
bool _useCustomPrompt = false;
|
||||
StringVariable _inputPrompt = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.askForValuePrompt");
|
||||
bool _useInputPlaceholder = false;
|
||||
StringVariable _inputPlaceholder =
|
||||
obs_module_text("AdvSceneSwitcher.enterText");
|
||||
ValueInputType _inputType = ValueInputType::String;
|
||||
StringList _inputOptions = {"value1", "value2", "value3"};
|
||||
#ifdef _WIN32
|
||||
StringVariable _envVariableName = "USERPROFILE";
|
||||
#else
|
||||
StringVariable _envVariableName = "HOME";
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool AskForUserInput(MacroActionVariable &, Variable &);
|
||||
};
|
||||
|
||||
class VariableActionInputEdit : public VariableActionGroupEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionInputEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
static VariableActionGroupEdit *
|
||||
Create(QWidget *parent, std::shared_ptr<MacroActionVariable> entryData);
|
||||
std::unordered_map<std::string, QWidget *> GetInlineWidgets() override;
|
||||
void UpdateEntryData() override;
|
||||
void SetWidgetVisibility(MacroActionVariable::Action) override;
|
||||
|
||||
private slots:
|
||||
void UseCustomPromptChanged(int);
|
||||
void InputPromptChanged();
|
||||
void UseInputPlaceholderChanged(int);
|
||||
void InputPlaceholderChanged();
|
||||
void InputTypeChanged(int);
|
||||
void InputOptionsChanged(const StringList &);
|
||||
void EnvVariableChanged();
|
||||
|
||||
private:
|
||||
VariableActionInput *_data;
|
||||
|
||||
QHBoxLayout *_promptLayout;
|
||||
QCheckBox *_useCustomPrompt;
|
||||
VariableLineEdit *_inputPrompt;
|
||||
QHBoxLayout *_placeholderLayout;
|
||||
QCheckBox *_useInputPlaceholder;
|
||||
VariableLineEdit *_inputPlaceholder;
|
||||
QHBoxLayout *_inputTypeLayout;
|
||||
QComboBox *_inputType;
|
||||
StringListEdit *_inputOptions;
|
||||
VariableLineEdit *_envVariable;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
189
lib/macro/macro-action-variable-json.cpp
Normal file
189
lib/macro/macro-action-variable-json.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "macro-action-variable-json.hpp"
|
||||
#include "json-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
using Action = MacroActionVariable::Action;
|
||||
|
||||
static bool registered = RegisterVariableActionGroup(
|
||||
{20,
|
||||
{
|
||||
{Action::EXTRACT_JSON,
|
||||
"AdvSceneSwitcher.action.variable.type.extractJsonField",
|
||||
"AdvSceneSwitcher.action.variable.layout.strValue", true},
|
||||
{Action::QUERY_JSON,
|
||||
"AdvSceneSwitcher.action.variable.type.queryJson",
|
||||
"AdvSceneSwitcher.action.variable.layout.queryJson", true},
|
||||
{Action::ARRAY_JSON,
|
||||
"AdvSceneSwitcher.action.variable.type.accessJsonArray",
|
||||
"AdvSceneSwitcher.action.variable.layout.accessJsonArray"},
|
||||
},
|
||||
[]() { return std::make_unique<VariableActionJson>(); },
|
||||
VariableActionJsonEdit::Create});
|
||||
|
||||
std::unique_ptr<VariableActionGroup> VariableActionJson::Copy() const
|
||||
{
|
||||
return std::make_unique<VariableActionJson>(*this);
|
||||
}
|
||||
|
||||
void VariableActionJson::Save(obs_data_t *obj,
|
||||
const MacroActionVariable &) const
|
||||
{
|
||||
_jsonQuery.Save(obj, "jsonQuery");
|
||||
_jsonIndex.Save(obj, "jsonIndex");
|
||||
obs_data_set_bool(obj, "jsonQueryExtractSingle",
|
||||
_jsonQueryExtractSingle);
|
||||
}
|
||||
|
||||
void VariableActionJson::Load(obs_data_t *obj, MacroActionVariable &)
|
||||
{
|
||||
_jsonQuery.Load(obj, "jsonQuery");
|
||||
_jsonIndex.Load(obj, "jsonIndex");
|
||||
_jsonQueryExtractSingle =
|
||||
obs_data_get_bool(obj, "jsonQueryExtractSingle");
|
||||
}
|
||||
|
||||
void VariableActionJson::ResolveVariables()
|
||||
{
|
||||
_jsonQuery.ResolveVariables();
|
||||
_jsonIndex.ResolveVariables();
|
||||
}
|
||||
|
||||
bool VariableActionJson::Perform(MacroActionVariable &action,
|
||||
MacroActionVariable::Action type,
|
||||
Variable &var)
|
||||
{
|
||||
switch (type) {
|
||||
case Action::EXTRACT_JSON: {
|
||||
auto value = GetJsonField(var.Value(), action._strValue);
|
||||
if (!value.has_value()) {
|
||||
return true;
|
||||
}
|
||||
var.SetValue(*value);
|
||||
return true;
|
||||
}
|
||||
case Action::QUERY_JSON: {
|
||||
auto value = QueryJson(var.Value(), _jsonQuery);
|
||||
if (!value.has_value()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_jsonQueryExtractSingle) {
|
||||
var.SetValue(*value);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto extracted = ExtractSingleJsonArrayElement(*value);
|
||||
if (extracted.has_value()) {
|
||||
var.SetValue(*extracted);
|
||||
} else {
|
||||
var.SetValue(*value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Action::ARRAY_JSON: {
|
||||
auto value = AccessJsonArrayIndex(var.Value(), _jsonIndex);
|
||||
if (!value.has_value()) {
|
||||
return true;
|
||||
}
|
||||
var.SetValue(*value);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
VariableActionJsonEdit::VariableActionJsonEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: VariableActionGroupEdit(parent, entryData),
|
||||
_data(entryData ? entryData->GetGroup<VariableActionJson>()
|
||||
: nullptr),
|
||||
_jsonQuery(new VariableLineEdit(this)),
|
||||
_jsonQueryHelp(new HelpIcon(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.type.queryJson.info"),
|
||||
this)),
|
||||
_jsonIndex(new VariableSpinBox(this)),
|
||||
_jsonExtractSingle(new QCheckBox(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.type.queryJson.extractSingle"),
|
||||
this)),
|
||||
_jsonExtractSingleHelp(new HelpIcon(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.type.queryJson.extractSingle.info"),
|
||||
this))
|
||||
{
|
||||
_jsonIndex->setMaximum(999);
|
||||
|
||||
QWidget::connect(_jsonQuery, SIGNAL(editingFinished()), this,
|
||||
SLOT(JsonQueryChanged()));
|
||||
QWidget::connect(
|
||||
_jsonIndex,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(JsonIndexChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_jsonExtractSingle, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(JsonQueryExtractSingleChanged(int)));
|
||||
|
||||
auto layout = new QHBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(_jsonExtractSingle);
|
||||
layout->addWidget(_jsonExtractSingleHelp);
|
||||
layout->addStretch();
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
VariableActionGroupEdit *
|
||||
VariableActionJsonEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData)
|
||||
{
|
||||
return new VariableActionJsonEdit(parent, entryData);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, QWidget *>
|
||||
VariableActionJsonEdit::GetInlineWidgets()
|
||||
{
|
||||
return {
|
||||
{"{{jsonQuery}}", _jsonQuery},
|
||||
{"{{jsonQueryHelp}}", _jsonQueryHelp},
|
||||
{"{{jsonIndex}}", _jsonIndex},
|
||||
};
|
||||
}
|
||||
|
||||
void VariableActionJsonEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
_jsonQuery->setText(_data->_jsonQuery);
|
||||
_jsonIndex->SetValue(_data->_jsonIndex);
|
||||
_jsonExtractSingle->setChecked(_data->_jsonQueryExtractSingle);
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void VariableActionJsonEdit::SetWidgetVisibility(
|
||||
MacroActionVariable::Action action)
|
||||
{
|
||||
setVisible(action == Action::QUERY_JSON);
|
||||
}
|
||||
|
||||
void VariableActionJsonEdit::JsonQueryChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_jsonQuery = _jsonQuery->text().toStdString();
|
||||
}
|
||||
|
||||
void VariableActionJsonEdit::JsonIndexChanged(const NumberVariable<int> &value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_jsonIndex = value;
|
||||
}
|
||||
|
||||
void VariableActionJsonEdit::JsonQueryExtractSingleChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_jsonQueryExtractSingle = value;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
50
lib/macro/macro-action-variable-json.hpp
Normal file
50
lib/macro/macro-action-variable-json.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable-group.hpp"
|
||||
#include "help-icon.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionJson : public VariableActionGroup {
|
||||
public:
|
||||
std::unique_ptr<VariableActionGroup> Copy() const override;
|
||||
void Save(obs_data_t *, const MacroActionVariable &) const override;
|
||||
void Load(obs_data_t *, MacroActionVariable &) override;
|
||||
void ResolveVariables() override;
|
||||
bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) override;
|
||||
|
||||
StringVariable _jsonQuery = "$.some.nested.value";
|
||||
IntVariable _jsonIndex = 0;
|
||||
bool _jsonQueryExtractSingle = true;
|
||||
};
|
||||
|
||||
class VariableActionJsonEdit : public VariableActionGroupEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionJsonEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
static VariableActionGroupEdit *
|
||||
Create(QWidget *parent, std::shared_ptr<MacroActionVariable> entryData);
|
||||
std::unordered_map<std::string, QWidget *> GetInlineWidgets() override;
|
||||
void UpdateEntryData() override;
|
||||
void SetWidgetVisibility(MacroActionVariable::Action) override;
|
||||
|
||||
private slots:
|
||||
void JsonQueryChanged();
|
||||
void JsonIndexChanged(const NumberVariable<int> &);
|
||||
void JsonQueryExtractSingleChanged(int);
|
||||
|
||||
private:
|
||||
VariableActionJson *_data;
|
||||
|
||||
VariableLineEdit *_jsonQuery;
|
||||
HelpIcon *_jsonQueryHelp;
|
||||
VariableSpinBox *_jsonIndex;
|
||||
QCheckBox *_jsonExtractSingle;
|
||||
HelpIcon *_jsonExtractSingleHelp;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
374
lib/macro/macro-action-variable-macro.cpp
Normal file
374
lib/macro/macro-action-variable-macro.cpp
Normal file
@@ -0,0 +1,374 @@
|
||||
#include "macro-action-variable-macro.hpp"
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "macro-signals.hpp"
|
||||
#include "macro.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
using Action = MacroActionVariable::Action;
|
||||
|
||||
static bool registered = RegisterVariableActionGroup(
|
||||
{30,
|
||||
{
|
||||
{Action::SET_TO_TEMPVAR,
|
||||
"AdvSceneSwitcher.action.variable.type.setToTempvar",
|
||||
"AdvSceneSwitcher.action.variable.layout.setToTempvar"},
|
||||
{Action::SET_CONDITION_VALUE,
|
||||
"AdvSceneSwitcher.action.variable.type.setConditionValue",
|
||||
"AdvSceneSwitcher.action.variable.layout.segmentValue"},
|
||||
{Action::SET_ACTION_VALUE,
|
||||
"AdvSceneSwitcher.action.variable.type.setActionValue",
|
||||
"AdvSceneSwitcher.action.variable.layout.segmentValue"},
|
||||
},
|
||||
[]() { return std::make_unique<VariableActionMacro>(); },
|
||||
VariableActionMacroEdit::Create});
|
||||
|
||||
static bool isSegmentValueAction(MacroActionVariable::Action action)
|
||||
{
|
||||
return action == Action::SET_CONDITION_VALUE ||
|
||||
action == Action::SET_ACTION_VALUE;
|
||||
}
|
||||
|
||||
VariableActionMacro::~VariableActionMacro()
|
||||
{
|
||||
DecrementCurrentSegmentVariableRef();
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableActionGroup> VariableActionMacro::Copy() const
|
||||
{
|
||||
return std::make_unique<VariableActionMacro>(*this);
|
||||
}
|
||||
|
||||
void VariableActionMacro::Save(obs_data_t *obj,
|
||||
const MacroActionVariable &action) const
|
||||
{
|
||||
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue(action));
|
||||
_tempVar.Save(obj, action.GetMacro());
|
||||
}
|
||||
|
||||
void VariableActionMacro::Load(obs_data_t *obj, MacroActionVariable &action)
|
||||
{
|
||||
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
||||
_tempVar.Load(obj, action.GetMacro());
|
||||
}
|
||||
|
||||
void VariableActionMacro::PostLoad(MacroActionVariable &action)
|
||||
{
|
||||
SetSegmentIndexValue(action, _segmentIdxLoadValue);
|
||||
}
|
||||
|
||||
std::vector<TempVariableRef> VariableActionMacro::GetTempVarRefs() const
|
||||
{
|
||||
if (_tempVar.HasValidID()) {
|
||||
return {_tempVar};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool VariableActionMacro::Perform(MacroActionVariable &action,
|
||||
MacroActionVariable::Action type,
|
||||
Variable &var)
|
||||
{
|
||||
switch (type) {
|
||||
case Action::SET_CONDITION_VALUE:
|
||||
case Action::SET_ACTION_VALUE: {
|
||||
auto m = action.GetMacro();
|
||||
if (!m) {
|
||||
return true;
|
||||
}
|
||||
if (GetSegmentIndexValue(action) == -1) {
|
||||
return true;
|
||||
}
|
||||
auto segment = _macroSegment.lock();
|
||||
if (!segment) {
|
||||
return true;
|
||||
}
|
||||
var.SetValue(segment->GetVariableValue());
|
||||
return true;
|
||||
}
|
||||
case Action::SET_TO_TEMPVAR: {
|
||||
auto tempVar = _tempVar.GetTempVariable(action.GetMacro());
|
||||
if (!tempVar) {
|
||||
return true;
|
||||
}
|
||||
auto value = tempVar->Value();
|
||||
if (!value) {
|
||||
return true;
|
||||
}
|
||||
var.SetValue(*value);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void VariableActionMacro::SetSegmentIndexValue(
|
||||
const MacroActionVariable &action, int value)
|
||||
{
|
||||
DecrementCurrentSegmentVariableRef();
|
||||
|
||||
auto m = action.GetMacro();
|
||||
if (!m) {
|
||||
_macroSegment.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
_macroSegment.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroSegment> segment;
|
||||
if (action._action == Action::SET_CONDITION_VALUE) {
|
||||
if (value < (int)m->Conditions().size()) {
|
||||
segment = m->Conditions().at(value);
|
||||
}
|
||||
} else if (action._action == Action::SET_ACTION_VALUE) {
|
||||
if (value < (int)m->Actions().size()) {
|
||||
segment = m->Actions().at(value);
|
||||
}
|
||||
}
|
||||
|
||||
_macroSegment = segment;
|
||||
if (segment) {
|
||||
IncrementVariableRef(segment.get());
|
||||
}
|
||||
}
|
||||
|
||||
int VariableActionMacro::GetSegmentIndexValue(
|
||||
const MacroActionVariable &action) const
|
||||
{
|
||||
auto m = action.GetMacro();
|
||||
if (!m) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto segment = _macroSegment.lock();
|
||||
if (!segment) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (action._action == Action::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 (action._action == Action::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 VariableActionMacro::DecrementCurrentSegmentVariableRef()
|
||||
{
|
||||
auto segment = _macroSegment.lock();
|
||||
if (!segment) {
|
||||
return;
|
||||
}
|
||||
|
||||
DecrementVariableRef(segment.get());
|
||||
}
|
||||
|
||||
VariableActionMacroEdit::VariableActionMacroEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: VariableActionGroupEdit(parent, entryData),
|
||||
_data(entryData ? entryData->GetGroup<VariableActionMacro>()
|
||||
: nullptr),
|
||||
_segmentIdx(new MacroSegmentSelection(
|
||||
this, MacroSegmentSelection::Type::CONDITION, false)),
|
||||
_segmentValueStatus(new QLabel(this)),
|
||||
_segmentValue(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_tempVars(new TempVariableSelection(this)),
|
||||
_tempVarsHelp(new HelpIcon(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.type.setToTempvar.help"),
|
||||
this))
|
||||
{
|
||||
_segmentValue->setReadOnly(true);
|
||||
|
||||
QWidget::connect(_segmentIdx,
|
||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||
SLOT(SegmentIndexChanged(const IntVariable &)));
|
||||
QWidget::connect(MacroSignalManager::Instance(),
|
||||
SIGNAL(SegmentOrderChanged()), this,
|
||||
SLOT(MacroSegmentOrderChanged()));
|
||||
QWidget::connect(_tempVars,
|
||||
SIGNAL(SelectionChanged(const TempVariableRef &)),
|
||||
this, SLOT(SelectionChanged(const TempVariableRef &)));
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(_segmentValueStatus);
|
||||
layout->addWidget(_segmentValue);
|
||||
setLayout(layout);
|
||||
|
||||
connect(&_timer, SIGNAL(timeout()), this,
|
||||
SLOT(UpdateSegmentVariableValue()));
|
||||
_timer.start(1500);
|
||||
}
|
||||
|
||||
VariableActionGroupEdit *
|
||||
VariableActionMacroEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData)
|
||||
{
|
||||
return new VariableActionMacroEdit(parent, entryData);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, QWidget *>
|
||||
VariableActionMacroEdit::GetInlineWidgets()
|
||||
{
|
||||
return {
|
||||
{"{{segmentIndex}}", _segmentIdx},
|
||||
{"{{tempVars}}", _tempVars},
|
||||
{"{{tempVarsHelp}}", _tempVarsHelp},
|
||||
};
|
||||
}
|
||||
|
||||
void VariableActionMacroEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
_segmentIdx->SetValue(_data->GetSegmentIndexValue(*_entryData) + 1);
|
||||
_segmentIdx->SetMacro(_entryData->GetMacro());
|
||||
_tempVars->SetVariable(_data->_tempVar);
|
||||
_loading = false;
|
||||
UpdateSegmentVariableValue();
|
||||
}
|
||||
|
||||
void VariableActionMacroEdit::SetWidgetVisibility(
|
||||
MacroActionVariable::Action action)
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == Action::SET_ACTION_VALUE) {
|
||||
_segmentIdx->SetType(MacroSegmentSelection::Type::ACTION);
|
||||
} else if (action == Action::SET_CONDITION_VALUE) {
|
||||
_segmentIdx->SetType(MacroSegmentSelection::Type::CONDITION);
|
||||
}
|
||||
|
||||
_tempVarsHelp->setVisible(action == Action::SET_TO_TEMPVAR &&
|
||||
!_data->_tempVar.HasValidID());
|
||||
setVisible(isSegmentValueAction(action));
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionMacroEdit::SegmentIndexChanged(const IntVariable &val)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->SetSegmentIndexValue(*_entryData, val - 1);
|
||||
}
|
||||
|
||||
void VariableActionMacroEdit::SetSegmentValueError(const QString &text)
|
||||
{
|
||||
_segmentValueStatus->setText(text);
|
||||
_segmentValue->setPlainText("");
|
||||
_segmentValue->hide();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionMacroEdit::UpdateSegmentVariableValue()
|
||||
{
|
||||
if (!_data || !isSegmentValueAction(_entryData->_action)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto m = _entryData->GetMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = _data->GetSegmentIndexValue(*_entryData);
|
||||
if (index < 0) {
|
||||
SetSegmentValueError(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.invalidSelection"));
|
||||
const QSignalBlocker b(_segmentIdx);
|
||||
_segmentIdx->SetValue(0);
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroSegment> segment;
|
||||
if (_entryData->_action == Action::SET_ACTION_VALUE) {
|
||||
const auto &actions = m->Actions();
|
||||
if (index < (int)actions.size()) {
|
||||
segment = actions.at(index);
|
||||
}
|
||||
} else if (_entryData->_action == Action::SET_CONDITION_VALUE) {
|
||||
const auto &conditions = m->Conditions();
|
||||
if (index < (int)conditions.size()) {
|
||||
segment = conditions.at(index);
|
||||
}
|
||||
}
|
||||
|
||||
if (!segment) {
|
||||
SetSegmentValueError(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.invalidSelection"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SupportsVariableValue(segment.get())) {
|
||||
std::string type;
|
||||
QString fmt;
|
||||
|
||||
if (_entryData->_action == Action::SET_ACTION_VALUE) {
|
||||
type = MacroActionFactory::GetActionName(
|
||||
segment->GetId());
|
||||
fmt = QString(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.actionNoVariableSupport"));
|
||||
} else if (_entryData->_action == Action::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();
|
||||
|
||||
// Only update the text if the value changed to prevent possible text
|
||||
// selections being lost
|
||||
auto previousText = _segmentValue->toPlainText();
|
||||
auto newText = QString::fromStdString(segment->GetVariableValue());
|
||||
if (newText != previousText) {
|
||||
_segmentValue->setPlainText(newText);
|
||||
}
|
||||
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionMacroEdit::MacroSegmentOrderChanged()
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QSignalBlocker b(_segmentIdx);
|
||||
_segmentIdx->SetValue(_data->GetSegmentIndexValue(*_entryData) + 1);
|
||||
}
|
||||
|
||||
void VariableActionMacroEdit::SelectionChanged(const TempVariableRef &var)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_tempVar = var;
|
||||
IncrementTempVarInUseGeneration();
|
||||
SetWidgetVisibility(_entryData->_action);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
67
lib/macro/macro-action-variable-macro.hpp
Normal file
67
lib/macro/macro-action-variable-macro.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable-group.hpp"
|
||||
#include "help-icon.hpp"
|
||||
#include "macro-segment-selection.hpp"
|
||||
#include "resizing-text-edit.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionMacro : public VariableActionGroup {
|
||||
public:
|
||||
VariableActionMacro() = default;
|
||||
VariableActionMacro(const VariableActionMacro &) = default;
|
||||
~VariableActionMacro();
|
||||
std::unique_ptr<VariableActionGroup> Copy() const override;
|
||||
void Save(obs_data_t *, const MacroActionVariable &) const override;
|
||||
void Load(obs_data_t *, MacroActionVariable &) override;
|
||||
void PostLoad(MacroActionVariable &) override;
|
||||
std::vector<TempVariableRef> GetTempVarRefs() const override;
|
||||
bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) override;
|
||||
|
||||
void SetSegmentIndexValue(const MacroActionVariable &, int);
|
||||
int GetSegmentIndexValue(const MacroActionVariable &) const;
|
||||
|
||||
TempVariableRef _tempVar;
|
||||
|
||||
private:
|
||||
void DecrementCurrentSegmentVariableRef();
|
||||
|
||||
std::weak_ptr<MacroSegment> _macroSegment;
|
||||
int _segmentIdxLoadValue = -1;
|
||||
};
|
||||
|
||||
class VariableActionMacroEdit : public VariableActionGroupEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionMacroEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
static VariableActionGroupEdit *
|
||||
Create(QWidget *parent, std::shared_ptr<MacroActionVariable> entryData);
|
||||
std::unordered_map<std::string, QWidget *> GetInlineWidgets() override;
|
||||
void UpdateEntryData() override;
|
||||
void SetWidgetVisibility(MacroActionVariable::Action) override;
|
||||
|
||||
private slots:
|
||||
void SegmentIndexChanged(const IntVariable &);
|
||||
void UpdateSegmentVariableValue();
|
||||
void MacroSegmentOrderChanged();
|
||||
void SelectionChanged(const TempVariableRef &var);
|
||||
|
||||
private:
|
||||
void SetSegmentValueError(const QString &);
|
||||
|
||||
VariableActionMacro *_data;
|
||||
|
||||
MacroSegmentSelection *_segmentIdx;
|
||||
QLabel *_segmentValueStatus;
|
||||
ResizingPlainTextEdit *_segmentValue;
|
||||
TempVariableSelection *_tempVars;
|
||||
HelpIcon *_tempVarsHelp;
|
||||
QTimer _timer;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
366
lib/macro/macro-action-variable-math.cpp
Normal file
366
lib/macro/macro-action-variable-math.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
#include "macro-action-variable-math.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "math-helpers.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace advss {
|
||||
|
||||
using Action = MacroActionVariable::Action;
|
||||
|
||||
static bool registered = RegisterVariableActionGroup(
|
||||
{40,
|
||||
{
|
||||
{Action::MATH_EXPRESSION,
|
||||
"AdvSceneSwitcher.action.variable.type.mathExpression",
|
||||
"AdvSceneSwitcher.action.variable.layout.mathExpression",
|
||||
true},
|
||||
{Action::INCREMENT,
|
||||
"AdvSceneSwitcher.action.variable.type.increment",
|
||||
"AdvSceneSwitcher.action.variable.layout.numValue"},
|
||||
{Action::DECREMENT,
|
||||
"AdvSceneSwitcher.action.variable.type.decrement",
|
||||
"AdvSceneSwitcher.action.variable.layout.numValue"},
|
||||
{Action::ROUND_TO_INT,
|
||||
"AdvSceneSwitcher.action.variable.type.roundToInt"},
|
||||
{Action::RANDOM_NUMBER,
|
||||
"AdvSceneSwitcher.action.variable.type.randomNumber"},
|
||||
{Action::RANDOM_LIST_VALUE,
|
||||
"AdvSceneSwitcher.action.variable.type.randomListValue"},
|
||||
},
|
||||
[]() { return std::make_unique<VariableActionMath>(); },
|
||||
VariableActionMathEdit::Create});
|
||||
|
||||
static void modifyNumValue(Variable &var, double val, const bool increment)
|
||||
{
|
||||
auto current = var.DoubleValue();
|
||||
if (!current.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (increment) {
|
||||
var.SetValue(*current + val);
|
||||
} else {
|
||||
var.SetValue(*current - val);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableActionGroup> VariableActionMath::Copy() const
|
||||
{
|
||||
return std::make_unique<VariableActionMath>(*this);
|
||||
}
|
||||
|
||||
void VariableActionMath::Save(obs_data_t *obj,
|
||||
const MacroActionVariable &) const
|
||||
{
|
||||
_numValue.Save(obj, "numValue");
|
||||
_mathExpression.Save(obj, "mathExpression");
|
||||
_randomNumberStart.Save(obj, "randomNumberStart");
|
||||
_randomNumberEnd.Save(obj, "randomNumberEnd");
|
||||
obs_data_set_bool(obj, "generateInteger", _generateInteger);
|
||||
_randomValues.Save(obj, "randomValues", "value");
|
||||
obs_data_set_bool(obj, "allowRepeatValues", _allowRepeatValues);
|
||||
}
|
||||
|
||||
void VariableActionMath::Load(obs_data_t *obj, MacroActionVariable &)
|
||||
{
|
||||
_mathExpression.Load(obj, "mathExpression");
|
||||
|
||||
// Convert old data format
|
||||
// TODO: Remove in future version
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
_numValue = obs_data_get_double(obj, "numValue");
|
||||
} else {
|
||||
_numValue.Load(obj, "numValue");
|
||||
}
|
||||
|
||||
_randomNumberStart.Load(obj, "randomNumberStart");
|
||||
_randomNumberEnd.Load(obj, "randomNumberEnd");
|
||||
_generateInteger = obs_data_get_bool(obj, "generateInteger");
|
||||
_randomValues.Load(obj, "randomValues", "value");
|
||||
_allowRepeatValues = obs_data_get_bool(obj, "allowRepeatValues");
|
||||
}
|
||||
|
||||
void VariableActionMath::ResolveVariables()
|
||||
{
|
||||
_mathExpression.ResolveVariables();
|
||||
}
|
||||
|
||||
void VariableActionMath::HandleMathExpression(Variable &var)
|
||||
{
|
||||
auto result = EvalMathExpression(_mathExpression);
|
||||
if (std::holds_alternative<std::string>(result)) {
|
||||
blog(LOG_WARNING, "%s", std::get<std::string>(result).c_str());
|
||||
return;
|
||||
}
|
||||
var.SetValue(std::get<double>(result));
|
||||
}
|
||||
|
||||
void VariableActionMath::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<int> dis(start, end);
|
||||
var.SetValue(dis(gen));
|
||||
} else {
|
||||
std::uniform_real_distribution<double> dis(start, end);
|
||||
var.SetValue(dis(gen));
|
||||
}
|
||||
}
|
||||
|
||||
void VariableActionMath::PickRandomValue(Variable &var)
|
||||
{
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static const uint8_t maxIter = 255;
|
||||
|
||||
if (_randomValues.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_randomValues.size() == 1) {
|
||||
const auto &value = _randomValues.at(0);
|
||||
var.SetValue(value);
|
||||
_lastRandomValue = value;
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<int> dis(0, _randomValues.size() - 1);
|
||||
StringVariable value = _randomValues.at(dis(gen));
|
||||
|
||||
uint8_t iter = 0;
|
||||
for (; !_allowRepeatValues && iter < maxIter &&
|
||||
_lastRandomValue.has_value() &&
|
||||
std::string(value) == _lastRandomValue.value();
|
||||
iter++) {
|
||||
value = _randomValues.at(dis(gen));
|
||||
}
|
||||
|
||||
if (iter == maxIter) {
|
||||
blog(LOG_INFO,
|
||||
"giving up picking non-repeat random value after %d tries",
|
||||
maxIter);
|
||||
}
|
||||
|
||||
var.SetValue(value);
|
||||
_lastRandomValue = value;
|
||||
}
|
||||
|
||||
bool VariableActionMath::Perform(MacroActionVariable &,
|
||||
MacroActionVariable::Action type,
|
||||
Variable &var)
|
||||
{
|
||||
switch (type) {
|
||||
case Action::MATH_EXPRESSION:
|
||||
HandleMathExpression(var);
|
||||
break;
|
||||
case Action::INCREMENT:
|
||||
modifyNumValue(var, _numValue.GetValue(), true);
|
||||
break;
|
||||
case Action::DECREMENT:
|
||||
modifyNumValue(var, _numValue.GetValue(), false);
|
||||
break;
|
||||
case Action::ROUND_TO_INT: {
|
||||
auto curValue = var.DoubleValue();
|
||||
if (!curValue.has_value()) {
|
||||
break;
|
||||
}
|
||||
var.SetValue(std::to_string(int(std::round(*curValue))));
|
||||
break;
|
||||
}
|
||||
case Action::RANDOM_NUMBER:
|
||||
GenerateRandomNumber(var);
|
||||
break;
|
||||
case Action::RANDOM_LIST_VALUE:
|
||||
PickRandomValue(var);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VariableActionMathEdit::VariableActionMathEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: VariableActionGroupEdit(parent, entryData),
|
||||
_data(entryData ? entryData->GetGroup<VariableActionMath>()
|
||||
: nullptr),
|
||||
_numValue(new VariableDoubleSpinBox(this)),
|
||||
_mathExpression(new VariableLineEdit(this)),
|
||||
_mathExpressionResult(new QLabel(this)),
|
||||
_randomNumberStart(new VariableDoubleSpinBox(this)),
|
||||
_randomNumberEnd(new VariableDoubleSpinBox(this)),
|
||||
_generateInteger(new QCheckBox(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.generateInteger"),
|
||||
this)),
|
||||
_randomNumberLayout(new QVBoxLayout()),
|
||||
_randomValues(new StringListEdit(this)),
|
||||
_allowRepeatValues(new QCheckBox(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.type.allowRepeat"),
|
||||
this)),
|
||||
_randomValueLayout(new QVBoxLayout())
|
||||
{
|
||||
_numValue->setMinimum(-9999999999);
|
||||
_numValue->setMaximum(9999999999);
|
||||
_randomNumberStart->setMinimum(-9999999999);
|
||||
_randomNumberStart->setMaximum(9999999999);
|
||||
_randomNumberEnd->setMinimum(-9999999999);
|
||||
_randomNumberEnd->setMaximum(9999999999);
|
||||
_randomValues->SetMaxStringSize(99999999);
|
||||
|
||||
QWidget::connect(
|
||||
_numValue,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||
this, SLOT(NumValueChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(_mathExpression, SIGNAL(editingFinished()), this,
|
||||
SLOT(MathExpressionChanged()));
|
||||
QWidget::connect(
|
||||
_randomNumberStart,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||
this,
|
||||
SLOT(RandomNumberStartChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(
|
||||
_randomNumberEnd,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||
this,
|
||||
SLOT(RandomNumberEndChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(_generateInteger, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(GenerateIntegerChanged(int)));
|
||||
QWidget::connect(_randomValues,
|
||||
SIGNAL(StringListChanged(const StringList &)), this,
|
||||
SLOT(RandomValueListChanged(const StringList &)));
|
||||
QWidget::connect(_allowRepeatValues, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(AllowRepeatValuesChanged(int)));
|
||||
|
||||
auto randomLayout = new QHBoxLayout();
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.layout.randomNumber"),
|
||||
randomLayout,
|
||||
{{"{{randomNumberStart}}", _randomNumberStart},
|
||||
{"{{randomNumberEnd}}", _randomNumberEnd}});
|
||||
_randomNumberLayout->addLayout(randomLayout);
|
||||
_randomNumberLayout->addWidget(_generateInteger);
|
||||
|
||||
_randomValueLayout->addWidget(_randomValues);
|
||||
_randomValueLayout->addWidget(_allowRepeatValues);
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(_mathExpressionResult);
|
||||
layout->addLayout(_randomNumberLayout);
|
||||
layout->addLayout(_randomValueLayout);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
VariableActionGroupEdit *
|
||||
VariableActionMathEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData)
|
||||
{
|
||||
return new VariableActionMathEdit(parent, entryData);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, QWidget *>
|
||||
VariableActionMathEdit::GetInlineWidgets()
|
||||
{
|
||||
return {
|
||||
{"{{numValue}}", _numValue},
|
||||
{"{{mathExpression}}", _mathExpression},
|
||||
};
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
_numValue->SetValue(_data->_numValue);
|
||||
_mathExpression->setText(_data->_mathExpression);
|
||||
_randomNumberStart->SetValue(_data->_randomNumberStart);
|
||||
_randomNumberEnd->SetValue(_data->_randomNumberEnd);
|
||||
_generateInteger->setChecked(_data->_generateInteger);
|
||||
_allowRepeatValues->setChecked(_data->_allowRepeatValues);
|
||||
_randomValues->SetStringList(_data->_randomValues);
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::SetWidgetVisibility(
|
||||
MacroActionVariable::Action action)
|
||||
{
|
||||
const bool isRandomNumber = action == Action::RANDOM_NUMBER;
|
||||
const bool isRandomListValue = action == Action::RANDOM_LIST_VALUE;
|
||||
_mathExpressionResult->hide();
|
||||
SetLayoutVisible(_randomNumberLayout, isRandomNumber);
|
||||
SetLayoutVisible(_randomValueLayout, isRandomListValue);
|
||||
setVisible(isRandomNumber || isRandomListValue);
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::NumValueChanged(const NumberVariable<double> &value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_numValue = value;
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::MathExpressionChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_mathExpression = _mathExpression->text().toStdString();
|
||||
|
||||
// In case of invalid expression display an error
|
||||
auto result = EvalMathExpression(_data->_mathExpression);
|
||||
auto hasError = std::holds_alternative<std::string>(result);
|
||||
if (hasError) {
|
||||
_mathExpressionResult->setText(
|
||||
QString::fromStdString(std::get<std::string>(result)));
|
||||
}
|
||||
_mathExpressionResult->setVisible(hasError);
|
||||
setVisible(hasError);
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::RandomNumberStartChanged(
|
||||
const NumberVariable<double> &value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_randomNumberStart = value;
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::RandomNumberEndChanged(
|
||||
const NumberVariable<double> &value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_randomNumberEnd = value;
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::GenerateIntegerChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_generateInteger = value;
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::RandomValueListChanged(const StringList &values)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_randomValues = values;
|
||||
}
|
||||
|
||||
void VariableActionMathEdit::AllowRepeatValuesChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_allowRepeatValues = value;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
73
lib/macro/macro-action-variable-math.hpp
Normal file
73
lib/macro/macro-action-variable-math.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable-group.hpp"
|
||||
#include "string-list.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionMath : public VariableActionGroup {
|
||||
public:
|
||||
std::unique_ptr<VariableActionGroup> Copy() const override;
|
||||
void Save(obs_data_t *, const MacroActionVariable &) const override;
|
||||
void Load(obs_data_t *, MacroActionVariable &) override;
|
||||
void ResolveVariables() override;
|
||||
bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) override;
|
||||
|
||||
DoubleVariable _numValue = 0;
|
||||
StringVariable _mathExpression = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.mathExpression.example");
|
||||
DoubleVariable _randomNumberStart = 0;
|
||||
DoubleVariable _randomNumberEnd = 100;
|
||||
bool _generateInteger = true;
|
||||
StringList _randomValues = {"value1", "value2", "value3"};
|
||||
bool _allowRepeatValues = true;
|
||||
|
||||
private:
|
||||
void HandleMathExpression(Variable &);
|
||||
void GenerateRandomNumber(Variable &);
|
||||
void PickRandomValue(Variable &);
|
||||
|
||||
std::optional<std::string> _lastRandomValue;
|
||||
};
|
||||
|
||||
class VariableActionMathEdit : public VariableActionGroupEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionMathEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
static VariableActionGroupEdit *
|
||||
Create(QWidget *parent, std::shared_ptr<MacroActionVariable> entryData);
|
||||
std::unordered_map<std::string, QWidget *> GetInlineWidgets() override;
|
||||
void UpdateEntryData() override;
|
||||
void SetWidgetVisibility(MacroActionVariable::Action) override;
|
||||
|
||||
private slots:
|
||||
void NumValueChanged(const NumberVariable<double> &value);
|
||||
void MathExpressionChanged();
|
||||
void RandomNumberStartChanged(const NumberVariable<double> &);
|
||||
void RandomNumberEndChanged(const NumberVariable<double> &);
|
||||
void GenerateIntegerChanged(int);
|
||||
void RandomValueListChanged(const StringList &);
|
||||
void AllowRepeatValuesChanged(int);
|
||||
|
||||
private:
|
||||
VariableActionMath *_data;
|
||||
|
||||
VariableDoubleSpinBox *_numValue;
|
||||
VariableLineEdit *_mathExpression;
|
||||
QLabel *_mathExpressionResult;
|
||||
VariableDoubleSpinBox *_randomNumberStart;
|
||||
VariableDoubleSpinBox *_randomNumberEnd;
|
||||
QCheckBox *_generateInteger;
|
||||
QVBoxLayout *_randomNumberLayout;
|
||||
StringListEdit *_randomValues;
|
||||
QCheckBox *_allowRepeatValues;
|
||||
QVBoxLayout *_randomValueLayout;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
169
lib/macro/macro-action-variable-scene.cpp
Normal file
169
lib/macro/macro-action-variable-scene.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#include "macro-action-variable-scene.hpp"
|
||||
#include "source-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
using Action = MacroActionVariable::Action;
|
||||
|
||||
static bool registered = RegisterVariableActionGroup(
|
||||
{60,
|
||||
{
|
||||
{Action::SCENE_ITEM_NAME,
|
||||
"AdvSceneSwitcher.action.variable.type.sceneItemName",
|
||||
"AdvSceneSwitcher.action.variable.layout.sceneItemName"},
|
||||
{Action::SCENE_ITEM_COUNT,
|
||||
"AdvSceneSwitcher.action.variable.type.sceneItemCount",
|
||||
"AdvSceneSwitcher.action.variable.layout.sceneItemCount"},
|
||||
},
|
||||
[]() { return std::make_unique<VariableActionScene>(); },
|
||||
VariableActionSceneEdit::Create});
|
||||
|
||||
struct GetSceneItemNameHelper {
|
||||
int curIdx = 0;
|
||||
int targetIdx = 0;
|
||||
std::string name = "";
|
||||
};
|
||||
|
||||
static bool getSceneItemAtIdx(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||
{
|
||||
auto data = reinterpret_cast<GetSceneItemNameHelper *>(ptr);
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, getSceneItemAtIdx, ptr);
|
||||
}
|
||||
if (data->curIdx == data->targetIdx) {
|
||||
data->name =
|
||||
obs_source_get_name(obs_sceneitem_get_source(item));
|
||||
data->curIdx--;
|
||||
return false;
|
||||
}
|
||||
data->curIdx--;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableActionGroup> VariableActionScene::Copy() const
|
||||
{
|
||||
return std::make_unique<VariableActionScene>(*this);
|
||||
}
|
||||
|
||||
void VariableActionScene::Save(obs_data_t *obj,
|
||||
const MacroActionVariable &) const
|
||||
{
|
||||
_scene.Save(obj);
|
||||
_sceneItemIndex.Save(obj, "sceneItemIndex");
|
||||
}
|
||||
|
||||
void VariableActionScene::Load(obs_data_t *obj, MacroActionVariable &)
|
||||
{
|
||||
_scene.Load(obj);
|
||||
_sceneItemIndex.Load(obj, "sceneItemIndex");
|
||||
}
|
||||
|
||||
void VariableActionScene::ResolveVariables()
|
||||
{
|
||||
_scene.ResolveVariables();
|
||||
_sceneItemIndex.ResolveVariables();
|
||||
}
|
||||
|
||||
void VariableActionScene::SetToSceneItemName(Variable &var)
|
||||
{
|
||||
auto weakSource = _scene.GetScene();
|
||||
if (!weakSource) {
|
||||
var.SetValue("");
|
||||
return;
|
||||
}
|
||||
auto index = _sceneItemIndex.GetValue();
|
||||
if (index < 1) {
|
||||
var.SetValue("");
|
||||
return;
|
||||
}
|
||||
auto sceneItemCount = GetSceneItemCount(weakSource);
|
||||
OBSSourceAutoRelease source = obs_weak_source_get_source(weakSource);
|
||||
auto scene = obs_scene_from_source(source);
|
||||
GetSceneItemNameHelper data{sceneItemCount, index};
|
||||
obs_scene_enum_items(scene, getSceneItemAtIdx, &data);
|
||||
var.SetValue(data.name);
|
||||
}
|
||||
|
||||
bool VariableActionScene::Perform(MacroActionVariable &,
|
||||
MacroActionVariable::Action type,
|
||||
Variable &var)
|
||||
{
|
||||
switch (type) {
|
||||
case Action::SCENE_ITEM_NAME:
|
||||
SetToSceneItemName(var);
|
||||
break;
|
||||
case Action::SCENE_ITEM_COUNT:
|
||||
var.SetValue(GetSceneItemCount(_scene.GetScene(false)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VariableActionSceneEdit::VariableActionSceneEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: VariableActionGroupEdit(parent, entryData),
|
||||
_data(entryData ? entryData->GetGroup<VariableActionScene>()
|
||||
: nullptr),
|
||||
_scenes(new SceneSelectionWidget(this, true, false, true, true,
|
||||
true)),
|
||||
_sceneItemIndex(new VariableSpinBox(this))
|
||||
{
|
||||
_sceneItemIndex->setMinimum(1);
|
||||
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(
|
||||
_sceneItemIndex,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(SceneItemIndexChanged(const NumberVariable<int> &)));
|
||||
}
|
||||
|
||||
VariableActionGroupEdit *
|
||||
VariableActionSceneEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData)
|
||||
{
|
||||
return new VariableActionSceneEdit(parent, entryData);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, QWidget *>
|
||||
VariableActionSceneEdit::GetInlineWidgets()
|
||||
{
|
||||
return {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sceneItemIndex}}", _sceneItemIndex},
|
||||
};
|
||||
}
|
||||
|
||||
void VariableActionSceneEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scenes->SetScene(_data->_scene);
|
||||
_sceneItemIndex->SetValue(_data->_sceneItemIndex);
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void VariableActionSceneEdit::SetWidgetVisibility(MacroActionVariable::Action)
|
||||
{
|
||||
hide();
|
||||
}
|
||||
|
||||
void VariableActionSceneEdit::SceneChanged(const SceneSelection &scene)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_scene = scene;
|
||||
}
|
||||
|
||||
void VariableActionSceneEdit::SceneItemIndexChanged(
|
||||
const NumberVariable<int> &value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_sceneItemIndex = value;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
47
lib/macro/macro-action-variable-scene.hpp
Normal file
47
lib/macro/macro-action-variable-scene.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable-group.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionScene : public VariableActionGroup {
|
||||
public:
|
||||
std::unique_ptr<VariableActionGroup> Copy() const override;
|
||||
void Save(obs_data_t *, const MacroActionVariable &) const override;
|
||||
void Load(obs_data_t *, MacroActionVariable &) override;
|
||||
void ResolveVariables() override;
|
||||
bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) override;
|
||||
|
||||
SceneSelection _scene;
|
||||
IntVariable _sceneItemIndex = 1;
|
||||
|
||||
private:
|
||||
void SetToSceneItemName(Variable &);
|
||||
};
|
||||
|
||||
class VariableActionSceneEdit : public VariableActionGroupEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionSceneEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
static VariableActionGroupEdit *
|
||||
Create(QWidget *parent, std::shared_ptr<MacroActionVariable> entryData);
|
||||
std::unordered_map<std::string, QWidget *> GetInlineWidgets() override;
|
||||
void UpdateEntryData() override;
|
||||
void SetWidgetVisibility(MacroActionVariable::Action) override;
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SceneItemIndexChanged(const NumberVariable<int> &);
|
||||
|
||||
private:
|
||||
VariableActionScene *_data;
|
||||
|
||||
SceneSelectionWidget *_scenes;
|
||||
VariableSpinBox *_sceneItemIndex;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
556
lib/macro/macro-action-variable-string.cpp
Normal file
556
lib/macro/macro-action-variable-string.cpp
Normal file
@@ -0,0 +1,556 @@
|
||||
#include "macro-action-variable-string.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace advss {
|
||||
|
||||
using Action = MacroActionVariable::Action;
|
||||
|
||||
static bool registered = RegisterVariableActionGroup(
|
||||
{10,
|
||||
{
|
||||
{Action::PAD, "AdvSceneSwitcher.action.variable.type.padValue",
|
||||
"AdvSceneSwitcher.action.variable.layout.pad"},
|
||||
{Action::TRUNCATE,
|
||||
"AdvSceneSwitcher.action.variable.type.truncateValue",
|
||||
"AdvSceneSwitcher.action.variable.layout.truncate"},
|
||||
{Action::SUBSTRING,
|
||||
"AdvSceneSwitcher.action.variable.type.subString"},
|
||||
{Action::FIND_AND_REPLACE,
|
||||
"AdvSceneSwitcher.action.variable.type.findAndReplace"},
|
||||
{Action::STRING_LENGTH,
|
||||
"AdvSceneSwitcher.action.variable.type.stringLength",
|
||||
"AdvSceneSwitcher.action.variable.layout.strValue", true},
|
||||
{Action::TRIM, "AdvSceneSwitcher.action.variable.type.trim"},
|
||||
{Action::CHANGE_CASE,
|
||||
"AdvSceneSwitcher.action.variable.type.changeCase",
|
||||
"AdvSceneSwitcher.action.variable.layout.changeCase"},
|
||||
},
|
||||
[]() { return std::make_unique<VariableActionString>(); },
|
||||
VariableActionStringEdit::Create});
|
||||
|
||||
static std::string truncate(const std::string &input,
|
||||
VariableActionString::Direction direction,
|
||||
size_t length)
|
||||
{
|
||||
if (input.length() <= length) {
|
||||
return input;
|
||||
}
|
||||
|
||||
if (direction == VariableActionString::Direction::RIGHT) {
|
||||
return input.substr(0, length);
|
||||
} else {
|
||||
return input.substr(input.length() - length);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string pad(const std::string &input,
|
||||
VariableActionString::Direction direction, size_t length,
|
||||
char paddingChar)
|
||||
{
|
||||
if (input.length() >= length) {
|
||||
return input;
|
||||
}
|
||||
|
||||
if (direction == VariableActionString::Direction::RIGHT) {
|
||||
return input +
|
||||
std::string(length - input.length(), paddingChar);
|
||||
} else {
|
||||
return std::string(length - input.length(), paddingChar) +
|
||||
input;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableActionGroup> VariableActionString::Copy() const
|
||||
{
|
||||
return std::make_unique<VariableActionString>(*this);
|
||||
}
|
||||
|
||||
void VariableActionString::Save(obs_data_t *obj,
|
||||
const MacroActionVariable &) const
|
||||
{
|
||||
_subStringStart.Save(obj, "subStringStart");
|
||||
_subStringSize.Save(obj, "subStringSize");
|
||||
obs_data_set_string(obj, "regexPattern", _regexPattern.c_str());
|
||||
_regexMatchIdx.Save(obj, "regexMatchIdx");
|
||||
_findRegex.Save(obj, "findRegex");
|
||||
_findStr.Save(obj, "findStr");
|
||||
_replaceStr.Save(obj, "replaceStr");
|
||||
_subStringRegex.Save(obj);
|
||||
obs_data_set_int(obj, "direction", static_cast<int>(_direction));
|
||||
_stringLength.Save(obj, "stringLength");
|
||||
obs_data_set_int(obj, "paddingChar", _paddingChar);
|
||||
obs_data_set_int(obj, "caseType", static_cast<int>(_caseType));
|
||||
}
|
||||
|
||||
void VariableActionString::Load(obs_data_t *obj, MacroActionVariable &)
|
||||
{
|
||||
_subStringRegex.Load(obj);
|
||||
_regexPattern = obs_data_get_string(obj, "regexPattern");
|
||||
_findRegex.Load(obj, "findRegex");
|
||||
_findStr.Load(obj, "findStr");
|
||||
_replaceStr.Load(obj, "replaceStr");
|
||||
_direction = static_cast<Direction>(obs_data_get_int(obj, "direction"));
|
||||
_stringLength.Load(obj, "stringLength");
|
||||
if (obs_data_has_user_value(obj, "paddingChar")) {
|
||||
_paddingChar = obs_data_get_int(obj, "paddingChar");
|
||||
} else {
|
||||
_paddingChar = ' ';
|
||||
}
|
||||
_caseType = static_cast<CaseType>(obs_data_get_int(obj, "caseType"));
|
||||
|
||||
// Convert old data format
|
||||
// TODO: Remove in future version
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
_subStringStart = obs_data_get_int(obj, "subStringStart") + 1;
|
||||
_subStringSize = obs_data_get_int(obj, "subStringSize");
|
||||
_regexMatchIdx = obs_data_get_int(obj, "regexMatchIdx") + 1;
|
||||
} else {
|
||||
_subStringStart.Load(obj, "subStringStart");
|
||||
_subStringSize.Load(obj, "subStringSize");
|
||||
_regexMatchIdx.Load(obj, "regexMatchIdx");
|
||||
}
|
||||
}
|
||||
|
||||
void VariableActionString::ResolveVariables()
|
||||
{
|
||||
_findStr.ResolveVariables();
|
||||
_replaceStr.ResolveVariables();
|
||||
}
|
||||
|
||||
void VariableActionString::HandleIndexSubString(Variable &var)
|
||||
{
|
||||
const auto curValue = var.Value();
|
||||
const auto subStringSize = _subStringSize.GetValue();
|
||||
const auto subStringStart = _subStringStart.GetValue() - 1;
|
||||
|
||||
try {
|
||||
if (subStringSize == 0) {
|
||||
var.SetValue(curValue.substr(subStringStart));
|
||||
return;
|
||||
}
|
||||
|
||||
var.SetValue(curValue.substr(subStringStart, subStringSize));
|
||||
} catch (const std::out_of_range &) {
|
||||
vblog(LOG_WARNING,
|
||||
"invalid start index \"%d\" selected for substring of \"%s\" of variable \"%s\"",
|
||||
subStringStart, curValue.c_str(), var.Name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void VariableActionString::HandleRegexSubString(Variable &var)
|
||||
{
|
||||
const auto curValue = var.Value();
|
||||
auto regex = _subStringRegex.GetRegularExpression(_regexPattern);
|
||||
if (!regex.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = regex.globalMatch(QString::fromStdString(curValue));
|
||||
const auto regexMatchIndex = _regexMatchIdx.GetValue() - 1;
|
||||
for (int idx = 0; idx < regexMatchIndex; idx++) {
|
||||
if (!it.hasNext()) {
|
||||
return;
|
||||
}
|
||||
it.next();
|
||||
}
|
||||
|
||||
if (!it.hasNext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto match = it.next();
|
||||
var.SetValue(match.captured(0).toStdString());
|
||||
}
|
||||
|
||||
void VariableActionString::HandleFindAndReplace(Variable &var)
|
||||
{
|
||||
auto value = var.Value();
|
||||
if (!_findRegex.Enabled()) {
|
||||
ReplaceAll(value, _findStr, _replaceStr);
|
||||
var.SetValue(value);
|
||||
return;
|
||||
}
|
||||
|
||||
QString replacement = QString::fromStdString(_replaceStr);
|
||||
auto regex = _findRegex.GetRegularExpression(_findStr);
|
||||
auto result = QString::fromStdString(value);
|
||||
result = result.replace(regex, replacement);
|
||||
var.SetValue(result.toStdString());
|
||||
}
|
||||
|
||||
void VariableActionString::HandleCaseChange(Variable &var)
|
||||
{
|
||||
auto value = QString::fromStdString(var.Value());
|
||||
|
||||
switch (_caseType) {
|
||||
case CaseType::LOWER_CASE:
|
||||
var.SetValue(value.toLower().toStdString());
|
||||
break;
|
||||
case CaseType::UPPER_CASE:
|
||||
var.SetValue(value.toUpper().toStdString());
|
||||
break;
|
||||
case CaseType::CAPITALIZED: {
|
||||
if (value.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
value[0] = value[0].toUpper();
|
||||
var.SetValue(value.toStdString());
|
||||
break;
|
||||
}
|
||||
case CaseType::START_CASE: {
|
||||
auto partList = value.split(QRegularExpression("\\b"));
|
||||
|
||||
for (auto &part : partList) {
|
||||
if (part.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
part[0] = part[0].toUpper();
|
||||
}
|
||||
|
||||
var.SetValue(partList.join("").toStdString());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VariableActionString::Perform(MacroActionVariable &action,
|
||||
MacroActionVariable::Action type,
|
||||
Variable &var)
|
||||
{
|
||||
switch (type) {
|
||||
case Action::PAD:
|
||||
var.SetValue(pad(var.Value(), _direction, _stringLength,
|
||||
_paddingChar));
|
||||
break;
|
||||
case Action::TRUNCATE:
|
||||
var.SetValue(truncate(var.Value(), _direction, _stringLength));
|
||||
break;
|
||||
case Action::SUBSTRING:
|
||||
if (_subStringRegex.Enabled()) {
|
||||
HandleRegexSubString(var);
|
||||
break;
|
||||
}
|
||||
HandleIndexSubString(var);
|
||||
break;
|
||||
case Action::FIND_AND_REPLACE:
|
||||
HandleFindAndReplace(var);
|
||||
break;
|
||||
case Action::STRING_LENGTH:
|
||||
var.SetValue(std::string(action._strValue).length());
|
||||
break;
|
||||
case Action::TRIM:
|
||||
var.SetValue(QString::fromStdString(var.Value())
|
||||
.trimmed()
|
||||
.toStdString());
|
||||
break;
|
||||
case Action::CHANGE_CASE:
|
||||
HandleCaseChange(var);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void populateCaseTypeSelection(QComboBox *list)
|
||||
{
|
||||
const static std::map<VariableActionString::CaseType, std::string>
|
||||
caseTypes = {
|
||||
{VariableActionString::CaseType::LOWER_CASE,
|
||||
"AdvSceneSwitcher.action.variable.case.type.lowerCase"},
|
||||
{VariableActionString::CaseType::UPPER_CASE,
|
||||
"AdvSceneSwitcher.action.variable.case.type.upperCase"},
|
||||
{VariableActionString::CaseType::CAPITALIZED,
|
||||
"AdvSceneSwitcher.action.variable.case.type.capitalized"},
|
||||
{VariableActionString::CaseType::START_CASE,
|
||||
"AdvSceneSwitcher.action.variable.case.type.startCase"},
|
||||
};
|
||||
|
||||
for (const auto &[type, name] : caseTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(type));
|
||||
}
|
||||
}
|
||||
|
||||
static void populateDirectionSelection(QComboBox *list)
|
||||
{
|
||||
list->addItems(
|
||||
QStringList()
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.truncateOrPadDirection.left")
|
||||
<< obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.truncateOrPadDirection.right"));
|
||||
}
|
||||
|
||||
VariableActionStringEdit::VariableActionStringEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionVariable> entryData)
|
||||
: VariableActionGroupEdit(parent, entryData),
|
||||
_data(entryData ? entryData->GetGroup<VariableActionString>()
|
||||
: nullptr),
|
||||
_substringLayout(new QVBoxLayout()),
|
||||
_subStringControlsLayout(new QHBoxLayout()),
|
||||
_subStringStart(new VariableSpinBox(this)),
|
||||
_subStringSize(new VariableSpinBox(this)),
|
||||
_subStringRegex(new RegexConfigWidget(this)),
|
||||
_regexPattern(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_regexMatchIdx(new VariableSpinBox(this)),
|
||||
_findReplaceLayout(new QHBoxLayout()),
|
||||
_findRegex(new RegexConfigWidget(this)),
|
||||
_findStr(new VariableTextEdit(this, 10, 1, 1)),
|
||||
_replaceStr(new VariableTextEdit(this, 10, 1, 1)),
|
||||
_direction(new QComboBox(this)),
|
||||
_stringLength(new VariableSpinBox(this)),
|
||||
_paddingCharSelection(new SingleCharSelection(this)),
|
||||
_caseType(new FilterComboBox(this))
|
||||
{
|
||||
_subStringStart->setMinimum(1);
|
||||
_subStringStart->setMaximum(99999);
|
||||
_subStringStart->setSpecialValueText(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.subString.begin"));
|
||||
_subStringSize->setMinimum(0);
|
||||
_subStringSize->setMaximum(99999);
|
||||
_subStringSize->setSpecialValueText(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.subString.all"));
|
||||
_regexMatchIdx->setMinimum(1);
|
||||
_regexMatchIdx->setMaximum(999);
|
||||
_regexMatchIdx->setSuffix(".");
|
||||
_replaceStr->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.findAndReplace.replace.tooltip"));
|
||||
_stringLength->setMaximum(999);
|
||||
populateDirectionSelection(_direction);
|
||||
populateCaseTypeSelection(_caseType);
|
||||
|
||||
QWidget::connect(
|
||||
_subStringStart,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(SubStringStartChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(
|
||||
_subStringSize,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(SubStringSizeChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_subStringRegex,
|
||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||
SLOT(SubStringRegexChanged(const RegexConfig &)));
|
||||
QWidget::connect(_regexPattern, SIGNAL(textChanged()), this,
|
||||
SLOT(RegexPatternChanged()));
|
||||
QWidget::connect(
|
||||
_regexMatchIdx,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(RegexMatchIdxChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_findRegex,
|
||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||
SLOT(FindRegexChanged(const RegexConfig &)));
|
||||
QWidget::connect(_findStr, SIGNAL(textChanged()), this,
|
||||
SLOT(FindStrValueChanged()));
|
||||
QWidget::connect(_replaceStr, SIGNAL(textChanged()), this,
|
||||
SLOT(ReplaceStrValueChanged()));
|
||||
QWidget::connect(_direction, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(DirectionChanged(int)));
|
||||
QWidget::connect(
|
||||
_stringLength,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(StringLengthChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_paddingCharSelection,
|
||||
SIGNAL(CharChanged(const QString &)), this,
|
||||
SLOT(CharSelectionChanged(const QString &)));
|
||||
QWidget::connect(_caseType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(CaseTypeChanged(int)));
|
||||
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.layout.findAndReplace"),
|
||||
_findReplaceLayout,
|
||||
{{"{{findStr}}", _findStr},
|
||||
{"{{findRegex}}", _findRegex},
|
||||
{"{{replaceStr}}", _replaceStr}},
|
||||
false);
|
||||
|
||||
auto regexConfigLayout = new QHBoxLayout;
|
||||
regexConfigLayout->addWidget(_subStringRegex);
|
||||
regexConfigLayout->addStretch();
|
||||
|
||||
_substringLayout->addLayout(_subStringControlsLayout);
|
||||
_substringLayout->addWidget(_regexPattern);
|
||||
_substringLayout->addLayout(regexConfigLayout);
|
||||
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addLayout(_substringLayout);
|
||||
layout->addLayout(_findReplaceLayout);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
VariableActionGroupEdit *
|
||||
VariableActionStringEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData)
|
||||
{
|
||||
return new VariableActionStringEdit(parent, entryData);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, QWidget *>
|
||||
VariableActionStringEdit::GetInlineWidgets()
|
||||
{
|
||||
return {
|
||||
{"{{direction}}", _direction},
|
||||
{"{{stringLength}}", _stringLength},
|
||||
{"{{paddingCharSelection}}", _paddingCharSelection},
|
||||
{"{{caseType}}", _caseType},
|
||||
};
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
_subStringStart->SetValue(_data->_subStringStart);
|
||||
_subStringSize->SetValue(_data->_subStringSize);
|
||||
_subStringRegex->SetRegexConfig(_data->_subStringRegex);
|
||||
_findRegex->SetRegexConfig(_data->_findRegex);
|
||||
_regexPattern->setPlainText(
|
||||
QString::fromStdString(_data->_regexPattern));
|
||||
_regexMatchIdx->SetValue(_data->_regexMatchIdx);
|
||||
_findStr->setPlainText(_data->_findStr);
|
||||
_replaceStr->setPlainText(_data->_replaceStr);
|
||||
_direction->setCurrentIndex(static_cast<int>(_data->_direction));
|
||||
_stringLength->SetValue(_data->_stringLength);
|
||||
_paddingCharSelection->setText(QChar::fromLatin1(_data->_paddingChar));
|
||||
_caseType->setCurrentIndex(
|
||||
_caseType->findData(static_cast<int>(_data->_caseType)));
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::SetWidgetVisibility(
|
||||
MacroActionVariable::Action action)
|
||||
{
|
||||
if (!_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, QWidget *> substringWidgets = {
|
||||
{"{{subStringRegex}}", _subStringRegex},
|
||||
{"{{subStringStart}}", _subStringStart},
|
||||
{"{{subStringSize}}", _subStringSize},
|
||||
{"{{regexMatchIdx}}", _regexMatchIdx},
|
||||
};
|
||||
for (const auto &[_, widget] : substringWidgets) {
|
||||
_subStringControlsLayout->removeWidget(widget);
|
||||
}
|
||||
ClearLayout(_subStringControlsLayout);
|
||||
|
||||
const bool showRegex = _data->_subStringRegex.Enabled();
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
showRegex
|
||||
? "AdvSceneSwitcher.action.variable.layout.substringRegex"
|
||||
: "AdvSceneSwitcher.action.variable.layout.substringIndex"),
|
||||
_subStringControlsLayout, substringWidgets);
|
||||
_subStringStart->setVisible(!showRegex);
|
||||
_subStringSize->setVisible(!showRegex);
|
||||
_regexMatchIdx->setVisible(showRegex);
|
||||
|
||||
const bool isSubstring = action == Action::SUBSTRING;
|
||||
const bool isFindAndReplace = action == Action::FIND_AND_REPLACE;
|
||||
SetLayoutVisible(_substringLayout, isSubstring);
|
||||
_regexPattern->setVisible(showRegex && isSubstring);
|
||||
SetLayoutVisible(_findReplaceLayout, isFindAndReplace);
|
||||
setVisible(isSubstring || isFindAndReplace);
|
||||
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::SubStringStartChanged(
|
||||
const NumberVariable<int> &start)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_subStringStart = start;
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::SubStringSizeChanged(
|
||||
const NumberVariable<int> &size)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_subStringSize = size;
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::SubStringRegexChanged(const RegexConfig &conf)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_subStringRegex = conf;
|
||||
SetWidgetVisibility(_entryData->_action);
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::RegexPatternChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_regexPattern = _regexPattern->toPlainText().toStdString();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::RegexMatchIdxChanged(
|
||||
const NumberVariable<int> &index)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_regexMatchIdx = index;
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::FindStrValueChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_findStr = _findStr->toPlainText().toStdString();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::FindRegexChanged(const RegexConfig &conf)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_findRegex = conf;
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::ReplaceStrValueChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_replaceStr = _replaceStr->toPlainText().toStdString();
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::DirectionChanged(int value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_direction = static_cast<VariableActionString::Direction>(value);
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::StringLengthChanged(
|
||||
const NumberVariable<int> &value)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_stringLength = value;
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::CharSelectionChanged(const QString &character)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
if (character.isEmpty()) {
|
||||
_data->_paddingChar = ' ';
|
||||
} else {
|
||||
_data->_paddingChar = character.toStdString().at(0);
|
||||
}
|
||||
}
|
||||
|
||||
void VariableActionStringEdit::CaseTypeChanged(int index)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_data->_caseType = static_cast<VariableActionString::CaseType>(
|
||||
_caseType->itemData(index).toInt());
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
95
lib/macro/macro-action-variable-string.hpp
Normal file
95
lib/macro/macro-action-variable-string.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
#include "macro-action-variable-group.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "resizing-text-edit.hpp"
|
||||
#include "single-char-selection.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionString : public VariableActionGroup {
|
||||
public:
|
||||
std::unique_ptr<VariableActionGroup> Copy() const override;
|
||||
void Save(obs_data_t *, const MacroActionVariable &) const override;
|
||||
void Load(obs_data_t *, MacroActionVariable &) override;
|
||||
void ResolveVariables() override;
|
||||
bool Perform(MacroActionVariable &, MacroActionVariable::Action,
|
||||
Variable &) override;
|
||||
|
||||
enum class Direction { LEFT, RIGHT };
|
||||
enum class CaseType {
|
||||
LOWER_CASE,
|
||||
UPPER_CASE,
|
||||
CAPITALIZED,
|
||||
START_CASE,
|
||||
};
|
||||
|
||||
IntVariable _subStringStart = 0;
|
||||
IntVariable _subStringSize = 0;
|
||||
RegexConfig _subStringRegex = RegexConfig::PartialMatchRegexConfig();
|
||||
std::string _regexPattern = ".*";
|
||||
IntVariable _regexMatchIdx = 0;
|
||||
RegexConfig _findRegex;
|
||||
StringVariable _findStr = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.findAndReplace.find");
|
||||
StringVariable _replaceStr = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.findAndReplace.replace");
|
||||
Direction _direction = Direction::LEFT;
|
||||
IntVariable _stringLength = 1;
|
||||
char _paddingChar = '0';
|
||||
CaseType _caseType = CaseType::LOWER_CASE;
|
||||
|
||||
private:
|
||||
void HandleIndexSubString(Variable &);
|
||||
void HandleRegexSubString(Variable &);
|
||||
void HandleFindAndReplace(Variable &);
|
||||
void HandleCaseChange(Variable &);
|
||||
};
|
||||
|
||||
class VariableActionStringEdit : public VariableActionGroupEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VariableActionStringEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroActionVariable> entryData);
|
||||
static VariableActionGroupEdit *
|
||||
Create(QWidget *parent, std::shared_ptr<MacroActionVariable> entryData);
|
||||
std::unordered_map<std::string, QWidget *> GetInlineWidgets() override;
|
||||
void UpdateEntryData() override;
|
||||
void SetWidgetVisibility(MacroActionVariable::Action) override;
|
||||
|
||||
private slots:
|
||||
void SubStringStartChanged(const NumberVariable<int> &start);
|
||||
void SubStringSizeChanged(const NumberVariable<int> &size);
|
||||
void SubStringRegexChanged(const RegexConfig &conf);
|
||||
void RegexPatternChanged();
|
||||
void RegexMatchIdxChanged(const NumberVariable<int> &index);
|
||||
void FindStrValueChanged();
|
||||
void FindRegexChanged(const RegexConfig &conf);
|
||||
void ReplaceStrValueChanged();
|
||||
void DirectionChanged(int);
|
||||
void StringLengthChanged(const NumberVariable<int> &);
|
||||
void CharSelectionChanged(const QString &);
|
||||
void CaseTypeChanged(int index);
|
||||
|
||||
private:
|
||||
VariableActionString *_data;
|
||||
|
||||
QVBoxLayout *_substringLayout;
|
||||
QHBoxLayout *_subStringControlsLayout;
|
||||
VariableSpinBox *_subStringStart;
|
||||
VariableSpinBox *_subStringSize;
|
||||
RegexConfigWidget *_subStringRegex;
|
||||
ResizingPlainTextEdit *_regexPattern;
|
||||
VariableSpinBox *_regexMatchIdx;
|
||||
QHBoxLayout *_findReplaceLayout;
|
||||
RegexConfigWidget *_findRegex;
|
||||
VariableTextEdit *_findStr;
|
||||
VariableTextEdit *_replaceStr;
|
||||
QComboBox *_direction;
|
||||
VariableSpinBox *_stringLength;
|
||||
SingleCharSelection *_paddingCharSelection;
|
||||
FilterComboBox *_caseType;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,21 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "help-icon.hpp"
|
||||
#include "macro-segment-selection.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "resizing-text-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "single-char-selection.hpp"
|
||||
#include "string-list.hpp"
|
||||
#include "value-input.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "variable-ref.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class VariableActionGroup;
|
||||
class VariableActionGroupEdit;
|
||||
|
||||
class MacroActionVariable : public MacroAction {
|
||||
public:
|
||||
MacroActionVariable(Macro *m) : MacroAction(m) {}
|
||||
MacroActionVariable(Macro *m);
|
||||
MacroActionVariable(const MacroActionVariable &);
|
||||
~MacroActionVariable();
|
||||
bool PerformAction();
|
||||
bool Save(obs_data_t *obj) const;
|
||||
@@ -28,10 +26,19 @@ public:
|
||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
||||
static std::shared_ptr<MacroAction> Create(Macro *m);
|
||||
std::shared_ptr<MacroAction> Copy() const;
|
||||
void SetSegmentIndexValue(int);
|
||||
int GetSegmentIndexValue() const;
|
||||
void ResolveVariablesToFixedValues();
|
||||
|
||||
template<class T> T *GetGroup() const
|
||||
{
|
||||
for (const auto &group : _groups) {
|
||||
if (auto result = dynamic_cast<T *>(group.get())) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Values are persisted, do not change existing ones
|
||||
enum class Action {
|
||||
SET_VALUE,
|
||||
APPEND,
|
||||
@@ -67,74 +74,10 @@ public:
|
||||
VariableRef _variable;
|
||||
VariableRef _variable2;
|
||||
StringVariable _strValue = "";
|
||||
DoubleVariable _numValue = 0;
|
||||
IntVariable _subStringStart = 0;
|
||||
IntVariable _subStringSize = 0;
|
||||
RegexConfig _subStringRegex = RegexConfig::PartialMatchRegexConfig();
|
||||
std::string _regexPattern = ".*";
|
||||
IntVariable _regexMatchIdx = 0;
|
||||
RegexConfig _findRegex;
|
||||
StringVariable _findStr = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.findAndReplace.find");
|
||||
StringVariable _replaceStr = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.findAndReplace.replace");
|
||||
StringVariable _mathExpression = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.mathExpression.example");
|
||||
bool _useCustomPrompt = false;
|
||||
StringVariable _inputPrompt = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.askForValuePrompt");
|
||||
bool _useInputPlaceholder = false;
|
||||
StringVariable _inputPlaceholder =
|
||||
obs_module_text("AdvSceneSwitcher.enterText");
|
||||
ValueInputType _inputType = ValueInputType::String;
|
||||
StringList _inputOptions = {"value1", "value2", "value3"};
|
||||
#ifdef _WIN32
|
||||
StringVariable _envVariableName = "USERPROFILE";
|
||||
#else
|
||||
StringVariable _envVariableName = "HOME";
|
||||
#endif
|
||||
SceneSelection _scene;
|
||||
TempVariableRef _tempVar;
|
||||
IntVariable _sceneItemIndex = 1;
|
||||
|
||||
enum class Direction { LEFT, RIGHT };
|
||||
Direction _direction = Direction::LEFT;
|
||||
IntVariable _stringLength = 1;
|
||||
char _paddingChar = '0';
|
||||
|
||||
enum class CaseType {
|
||||
LOWER_CASE,
|
||||
UPPER_CASE,
|
||||
CAPITALIZED,
|
||||
START_CASE,
|
||||
};
|
||||
|
||||
CaseType _caseType = CaseType::LOWER_CASE;
|
||||
DoubleVariable _randomNumberStart = 0;
|
||||
DoubleVariable _randomNumberEnd = 100;
|
||||
bool _generateInteger = true;
|
||||
|
||||
StringList _randomValues = {"value1", "value2", "value3"};
|
||||
bool _allowRepeatValues = true;
|
||||
std::optional<std::string> _lastRandomValue;
|
||||
|
||||
StringVariable _jsonQuery = "$.some.nested.value";
|
||||
IntVariable _jsonIndex = 0;
|
||||
bool _jsonQueryExtractSingle = true;
|
||||
|
||||
private:
|
||||
void DecrementCurrentSegmentVariableRef();
|
||||
void HandleIndexSubString(Variable *);
|
||||
void HandleRegexSubString(Variable *);
|
||||
void HandleFindAndReplace(Variable *);
|
||||
void HandleMathExpression(Variable *);
|
||||
void HandleCaseChange(Variable *);
|
||||
void SetToSceneItemName(Variable *);
|
||||
void GenerateRandomNumber(Variable *);
|
||||
void PickRandomValue(Variable *);
|
||||
std::vector<std::unique_ptr<VariableActionGroup>> _groups;
|
||||
|
||||
std::weak_ptr<MacroSegment> _macroSegment;
|
||||
int _segmentIdxLoadValue = -1;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
@@ -160,105 +103,22 @@ private slots:
|
||||
void Variable2Changed(const QString &);
|
||||
void ActionChanged(int);
|
||||
void StrValueChanged();
|
||||
void NumValueChanged(const NumberVariable<double> &value);
|
||||
void SegmentIndexChanged(const IntVariable &);
|
||||
void UpdateSegmentVariableValue();
|
||||
void MacroSegmentOrderChanged();
|
||||
void SubStringStartChanged(const NumberVariable<int> &start);
|
||||
void SubStringSizeChanged(const NumberVariable<int> &size);
|
||||
void SubStringRegexChanged(const RegexConfig &conf);
|
||||
void RegexPatternChanged();
|
||||
void RegexMatchIdxChanged(const NumberVariable<int> &index);
|
||||
void FindStrValueChanged();
|
||||
void FindRegexChanged(const RegexConfig &conf);
|
||||
void ReplaceStrValueChanged();
|
||||
void MathExpressionChanged();
|
||||
void UseCustomPromptChanged(int);
|
||||
void InputPromptChanged();
|
||||
void UseInputPlaceholderChanged(int);
|
||||
void InputPlaceholderChanged();
|
||||
void InputTypeChanged(int);
|
||||
void InputOptionsChanged(const StringList &);
|
||||
void EnvVariableChanged();
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SelectionChanged(const TempVariableRef &var);
|
||||
void SceneItemIndexChanged(const NumberVariable<int> &);
|
||||
void DirectionChanged(int);
|
||||
void StringLengthChanged(const NumberVariable<int> &);
|
||||
void CharSelectionChanged(const QString &);
|
||||
void CaseTypeChanged(int index);
|
||||
void RandomNumberStartChanged(const NumberVariable<double> &);
|
||||
void RandomNumberEndChanged(const NumberVariable<double> &);
|
||||
void GenerateIntegerChanged(int);
|
||||
void RandomValueListChanged(const StringList &);
|
||||
void AllowRepeatValuesChanged(int);
|
||||
void JsonQueryChanged();
|
||||
void JsonIndexChanged(const NumberVariable<int> &);
|
||||
void JsonQueryExtractSingleChanged(int);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
void SetSegmentValueError(const QString &);
|
||||
std::unordered_map<std::string, QWidget *> GetInlineWidgets() const;
|
||||
|
||||
VariableSelection *_variables;
|
||||
VariableSelection *_variables2;
|
||||
FilterComboBox *_actions;
|
||||
VariableTextEdit *_strValue;
|
||||
VariableDoubleSpinBox *_numValue;
|
||||
MacroSegmentSelection *_segmentIdx;
|
||||
QLabel *_segmentValueStatus;
|
||||
ResizingPlainTextEdit *_segmentValue;
|
||||
QVBoxLayout *_substringLayout;
|
||||
QHBoxLayout *_subStringControlsLayout;
|
||||
VariableSpinBox *_subStringStart;
|
||||
VariableSpinBox *_subStringSize;
|
||||
RegexConfigWidget *_subStringRegex;
|
||||
ResizingPlainTextEdit *_regexPattern;
|
||||
VariableSpinBox *_regexMatchIdx;
|
||||
QHBoxLayout *_findReplaceLayout;
|
||||
RegexConfigWidget *_findRegex;
|
||||
VariableTextEdit *_findStr;
|
||||
VariableTextEdit *_replaceStr;
|
||||
VariableLineEdit *_mathExpression;
|
||||
QLabel *_mathExpressionResult;
|
||||
QHBoxLayout *_promptLayout;
|
||||
QCheckBox *_useCustomPrompt;
|
||||
VariableLineEdit *_inputPrompt;
|
||||
QHBoxLayout *_placeholderLayout;
|
||||
QCheckBox *_useInputPlaceholder;
|
||||
VariableLineEdit *_inputPlaceholder;
|
||||
QHBoxLayout *_inputTypeLayout;
|
||||
QComboBox *_inputType;
|
||||
StringListEdit *_inputOptions;
|
||||
VariableLineEdit *_envVariable;
|
||||
SceneSelectionWidget *_scenes;
|
||||
TempVariableSelection *_tempVars;
|
||||
HelpIcon *_tempVarsHelp;
|
||||
VariableSpinBox *_sceneItemIndex;
|
||||
QComboBox *_direction;
|
||||
VariableSpinBox *_stringLength;
|
||||
SingleCharSelection *_paddingCharSelection;
|
||||
FilterComboBox *_caseType;
|
||||
VariableDoubleSpinBox *_randomNumberStart;
|
||||
VariableDoubleSpinBox *_randomNumberEnd;
|
||||
QCheckBox *_generateInteger;
|
||||
QVBoxLayout *_randomNumberLayout;
|
||||
StringListEdit *_randomValues;
|
||||
QCheckBox *_allowRepeatValues;
|
||||
QVBoxLayout *_randomValueLayout;
|
||||
VariableLineEdit *_jsonQuery;
|
||||
HelpIcon *_jsonQueryHelp;
|
||||
VariableSpinBox *_jsonIndex;
|
||||
QCheckBox *_jsonExtractSingle;
|
||||
HelpIcon *_jsonExtractSingleHelp;
|
||||
QVBoxLayout *_jsonQueryLayout;
|
||||
QHBoxLayout *_entryLayout;
|
||||
std::vector<VariableActionGroupEdit *> _groupEdits;
|
||||
|
||||
std::shared_ptr<MacroActionVariable> _entryData;
|
||||
QTimer _timer;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user