SceneSwitcher/lib/macro/macro-condition-tempvar.cpp
WarmUpTill 7d0332dd0e Restructure library and plugins
The "core" macro conditions and actions have been extracted out to the
"base" plugin.

The library now mostly contains functionality which is required across
all plugins and (e.g. definitions for macro segments).

The goal is to reduce the complexity and cross-dependencies and group
the source files in a better way.

This should relsove the "library limit of 65535 objects exceeded" build
issue occuring in some Windows build environments.
2024-01-27 14:10:34 +01:00

365 lines
9.6 KiB
C++

#include "macro-condition-tempvar.hpp"
#include "math-helpers.hpp"
#include "utility.hpp"
namespace advss {
const std::string MacroConditionTempVar::id = "temp_var";
bool MacroConditionTempVar::_registered = MacroConditionFactory::Register(
MacroConditionTempVar::id,
{MacroConditionTempVar::Create, MacroConditionTempVarEdit::Create,
"AdvSceneSwitcher.condition.temporaryVariable"});
const static std::map<MacroConditionTempVar::Condition, std::string>
conditionTypes = {
{MacroConditionTempVar::Condition::EQUALS,
"AdvSceneSwitcher.condition.variable.type.compare"},
{MacroConditionTempVar::Condition::IS_EMPTY,
"AdvSceneSwitcher.condition.variable.type.empty"},
{MacroConditionTempVar::Condition::IS_NUMBER,
"AdvSceneSwitcher.condition.variable.type.number"},
{MacroConditionTempVar::Condition::LESS_THAN,
"AdvSceneSwitcher.condition.variable.type.lessThan"},
{MacroConditionTempVar::Condition::GREATER_THAN,
"AdvSceneSwitcher.condition.variable.type.greaterThan"},
{MacroConditionTempVar::Condition::VALUE_CHANGED,
"AdvSceneSwitcher.condition.variable.type.valueChanged"},
{MacroConditionTempVar::Condition::EQUALS_VARIABLE,
"AdvSceneSwitcher.condition.variable.type.equalsVariable"},
{MacroConditionTempVar::Condition::LESS_THAN_VARIABLE,
"AdvSceneSwitcher.condition.variable.type.lessThanVariable"},
{MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE,
"AdvSceneSwitcher.condition.variable.type.greaterThanVariable"},
};
static bool isNumber(const TempVariable &var)
{
auto value = var.Value();
if (!value) {
return false;
}
return GetDouble(*value).has_value();
}
static bool compareNumber(const TempVariable &var, double value, bool less)
{
auto tempVarValue = var.Value();
if (!tempVarValue) {
return false;
}
auto doubleValue = GetDouble(*tempVarValue);
if (!doubleValue.has_value()) {
return false;
}
if (less) {
return doubleValue < value;
}
return doubleValue > value;
}
bool MacroConditionTempVar::Compare(const TempVariable &var) const
{
auto value = var.Value();
if (!value) {
return false;
}
if (_regex.Enabled()) {
return _regex.Matches(*value, _strValue);
}
return std::string(_strValue) == *value;
}
bool MacroConditionTempVar::ValueChanged(const TempVariable &var)
{
auto value = var.Value();
if (!value) {
return false;
}
bool changed = *value != _lastValue;
if (changed) {
_lastValue = *value;
}
return changed;
}
bool MacroConditionTempVar::CompareVariables()
{
auto var1 = _tempVar.GetTempVariable(GetMacro());
auto var2 = _variable2.lock();
if (!var1 || !var2) {
return false;
}
auto tempVarValue = var1->Value();
if (!tempVarValue) {
return false;
}
auto val1 = GetDouble(*tempVarValue);
auto val2 = var2->DoubleValue();
bool validNumbers = val1.has_value() && val2.has_value();
switch (_type) {
case MacroConditionTempVar::Condition::EQUALS_VARIABLE:
return *tempVarValue == var2->Value() ||
(validNumbers && val1 == val2);
case MacroConditionTempVar::Condition::LESS_THAN_VARIABLE:
return validNumbers && val1 < val2;
case MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE:
return validNumbers && val1 > val2;
default:
blog(LOG_WARNING,
"Unexpected call of %s with condition type %d", __func__,
static_cast<int>(_type));
}
return false;
}
bool MacroConditionTempVar::CheckCondition()
{
auto var = _tempVar.GetTempVariable(GetMacro());
if (!var) {
return false;
}
switch (_type) {
case MacroConditionTempVar::Condition::EQUALS:
return Compare(*var);
case MacroConditionTempVar::Condition::IS_EMPTY:
return var->Value().has_value() && var->Value()->empty();
case MacroConditionTempVar::Condition::IS_NUMBER:
return isNumber(*var);
case MacroConditionTempVar::Condition::LESS_THAN:
return compareNumber(*var, _numValue, true);
case MacroConditionTempVar::Condition::GREATER_THAN:
return compareNumber(*var, _numValue, false);
case MacroConditionTempVar::Condition::VALUE_CHANGED:
return ValueChanged(*var);
case MacroConditionTempVar::Condition::EQUALS_VARIABLE:
return CompareVariables();
case MacroConditionTempVar::Condition::LESS_THAN_VARIABLE:
return CompareVariables();
case MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE:
return CompareVariables();
}
return false;
}
bool MacroConditionTempVar::Save(obs_data_t *obj) const
{
MacroCondition::Save(obj);
_tempVar.Save(obj);
obs_data_set_string(obj, "variableName",
GetWeakVariableName(_variable2).c_str());
_strValue.Save(obj, "strValue");
obs_data_set_double(obj, "numValue", _numValue);
obs_data_set_int(obj, "condition", static_cast<int>(_type));
_regex.Save(obj);
return true;
}
bool MacroConditionTempVar::Load(obs_data_t *obj)
{
MacroCondition::Load(obj);
_tempVar.Load(obj, GetMacro());
_variable2 =
GetWeakVariableByName(obs_data_get_string(obj, "variableName"));
_strValue.Load(obj, "strValue");
_numValue = obs_data_get_double(obj, "numValue");
_type = static_cast<Condition>(obs_data_get_int(obj, "condition"));
_regex.Load(obj);
// TODO: remove in future version
if (obs_data_has_user_value(obj, "regex")) {
_regex.CreateBackwardsCompatibleRegex(
obs_data_get_bool(obj, "regex"));
}
return true;
}
std::string MacroConditionTempVar::GetShortDesc() const
{
auto var = _tempVar.GetTempVariable(GetMacro());
if (!var) {
return "";
}
return var->Name();
}
static inline void populateConditionSelection(QComboBox *list)
{
for (auto entry : conditionTypes) {
list->addItem(obs_module_text(entry.second.c_str()));
}
}
MacroConditionTempVarEdit::MacroConditionTempVarEdit(
QWidget *parent, std::shared_ptr<MacroConditionTempVar> entryData)
: QWidget(parent),
_tempVars(new TempVariableSelection(this)),
_variables2(new VariableSelection(this)),
_conditions(new QComboBox()),
_strValue(new VariableTextEdit(this, 5, 1, 1)),
_numValue(new QDoubleSpinBox()),
_regex(new RegexConfigWidget(parent))
{
_numValue->setMinimum(-9999999999);
_numValue->setMaximum(9999999999);
populateConditionSelection(_conditions);
QWidget::connect(_tempVars,
SIGNAL(SelectionChanged(const TempVariableRef &)),
this, SLOT(VariableChanged(const TempVariableRef &)));
QWidget::connect(_variables2, SIGNAL(SelectionChanged(const QString &)),
this, SLOT(Variable2Changed(const QString &)));
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ConditionChanged(int)));
QWidget::connect(_strValue, SIGNAL(textChanged()), this,
SLOT(StrValueChanged()));
QWidget::connect(_numValue, SIGNAL(valueChanged(double)), this,
SLOT(NumValueChanged(double)));
QWidget::connect(_regex,
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
SLOT(RegexChanged(const RegexConfig &)));
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{variables}}", _tempVars},
{"{{variables2}}", _variables2},
{"{{conditions}}", _conditions},
{"{{strValue}}", _strValue},
{"{{numValue}}", _numValue},
{"{{regex}}", _regex},
};
auto layout = new QHBoxLayout;
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.condition.variable.entry"),
layout, widgetPlaceholders);
setLayout(layout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroConditionTempVarEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_tempVars->SetVariable(_entryData->_tempVar);
_variables2->SetVariable(_entryData->_variable2);
_conditions->setCurrentIndex(static_cast<int>(_entryData->_type));
_strValue->setPlainText(_entryData->_strValue);
_numValue->setValue(_entryData->_numValue);
_regex->SetRegexConfig(_entryData->_regex);
SetWidgetVisibility();
}
void MacroConditionTempVarEdit::VariableChanged(const TempVariableRef &var)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_tempVar = var;
}
void MacroConditionTempVarEdit::Variable2Changed(const QString &text)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_variable2 = GetWeakVariableByQString(text);
}
void MacroConditionTempVarEdit::ConditionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_type =
static_cast<MacroConditionTempVar::Condition>(value);
SetWidgetVisibility();
}
void MacroConditionTempVarEdit::StrValueChanged()
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_strValue = _strValue->toPlainText().toStdString();
adjustSize();
updateGeometry();
}
void MacroConditionTempVarEdit::NumValueChanged(double val)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_numValue = val;
}
void MacroConditionTempVarEdit::RegexChanged(const RegexConfig &conf)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_regex = conf;
adjustSize();
updateGeometry();
}
void MacroConditionTempVarEdit::SetWidgetVisibility()
{
if (!_entryData) {
return;
}
_regex->setVisible(_entryData->_type ==
MacroConditionTempVar::Condition::EQUALS);
_strValue->setVisible(_entryData->_type ==
MacroConditionTempVar::Condition::EQUALS);
_numValue->setVisible(
_entryData->_type ==
MacroConditionTempVar::Condition::LESS_THAN ||
_entryData->_type ==
MacroConditionTempVar::Condition::GREATER_THAN);
_numValue->setVisible(
_entryData->_type ==
MacroConditionTempVar::Condition::LESS_THAN ||
_entryData->_type ==
MacroConditionTempVar::Condition::GREATER_THAN);
_variables2->setVisible(
_entryData->_type ==
MacroConditionTempVar::Condition::EQUALS_VARIABLE ||
_entryData->_type ==
MacroConditionTempVar::Condition::LESS_THAN_VARIABLE ||
_entryData->_type ==
MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE);
adjustSize();
updateGeometry();
}
} // namespace advss