diff --git a/CMakeLists.txt b/CMakeLists.txt index 887b53ae..e2a11283 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -291,6 +291,10 @@ target_sources( lib/utils/volume-control.hpp lib/utils/websocket-api.cpp lib/utils/websocket-api.hpp + lib/variables/variable-color-button.cpp + lib/variables/variable-color-button.hpp + lib/variables/variable-color.cpp + lib/variables/variable-color.hpp lib/variables/variable-line-edit.cpp lib/variables/variable-line-edit.hpp lib/variables/variable-number.hpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 0e6761f6..180f9194 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -444,6 +444,7 @@ AdvSceneSwitcher.condition.video.ocrConfigReload="Reload configuration file" AdvSceneSwitcher.condition.video.ocrConfigHint="Tesseract config files consist of lines with parameter-value pairs (space separated).\nFor example:\n\ntessedit_char_blacklist\t\t\t\t\"abc\"\nlanguage_model_penalty_non_dict_word\t0" AdvSceneSwitcher.condition.video.modelLoadFail="Model data could not be loaded!" AdvSceneSwitcher.condition.video.selectColor="Select Color" +AdvSceneSwitcher.condition.video.colorVariableTooltip="Expected format: #RRGGBB or #AARRGGBB\nInvalid values will default to black." AdvSceneSwitcher.condition.video.ocrMode.singleColumn="Single column of text of variable sizes" AdvSceneSwitcher.condition.video.ocrMode.singleBlockVertText="Single uniform block of vertically aligned text" AdvSceneSwitcher.condition.video.ocrMode.singleBlock="Single uniform block of text" diff --git a/lib/variables/variable-color-button.cpp b/lib/variables/variable-color-button.cpp new file mode 100644 index 00000000..7c882aad --- /dev/null +++ b/lib/variables/variable-color-button.cpp @@ -0,0 +1,106 @@ +#include "variable-color-button.hpp" +#include "obs-module-helper.hpp" +#include "ui-helpers.hpp" + +#include +#include + +namespace advss { + +VariableColorButton::VariableColorButton(QWidget *parent, + const QString &selectText) + : QWidget(parent), + _colorSwatch(new QLabel()), + _selectColor(new QPushButton(selectText)), + _variable(new VariableSelection(this)), + _toggleType(new QPushButton()) +{ + _toggleType->setCheckable(true); + _toggleType->setMaximumWidth(11); + SetButtonIcon(_toggleType, GetThemeTypeName() == "Light" + ? ":/res/images/dots-vert.svg" + : "theme:Dark/dots-vert.svg"); + + QWidget::connect(_selectColor, SIGNAL(clicked()), this, + SLOT(SelectColorClicked())); + QWidget::connect(_toggleType, SIGNAL(toggled(bool)), this, + SLOT(ToggleTypeClicked(bool))); + QWidget::connect(_variable, SIGNAL(SelectionChanged(const QString &)), + this, SLOT(VariableChanged(const QString &))); + + auto layout = new QHBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(_colorSwatch); + layout->addWidget(_selectColor); + layout->addWidget(_variable); + layout->addWidget(_toggleType); + setLayout(layout); + SetVisibility(); +} + +void VariableColorButton::SetValue(const ColorVariable &color) +{ + _color = color; + const QSignalBlocker b1(_toggleType); + const QSignalBlocker b2(_variable); + _toggleType->setChecked(!color.IsFixedType()); + SetupColorLabel(color.GetFixedValue()); + _variable->SetVariable(color.GetVariable()); + SetVisibility(); +} + +void VariableColorButton::SelectColorClicked() +{ + const QColor color = QColorDialog::getColor( + _color.GetFixedValue(), this, _selectColor->text(), + QColorDialog::ColorDialogOption()); + if (!color.isValid()) { + return; + } + SetupColorLabel(color); + _color._value = color; + emit ColorVariableChanged(_color); +} + +void VariableColorButton::VariableChanged(const QString &name) +{ + _color._variable = GetWeakVariableByQString(name); + emit ColorVariableChanged(_color); +} + +void VariableColorButton::ToggleTypeClicked(bool useVariable) +{ + _color._type = useVariable ? ColorVariable::Type::VARIABLE + : ColorVariable::Type::FIXED_VALUE; + SetVisibility(); + emit ColorVariableChanged(_color); +} + +void VariableColorButton::SetupColorLabel(const QColor &color) +{ + _colorSwatch->setText(color.name()); + _colorSwatch->setStyleSheet( + QString("background-color: %1;").arg(color.name())); +} + +void VariableColorButton::SetVisibility() +{ + if (_color.IsFixedType()) { + SetupColorLabel(_color.GetFixedValue()); + _colorSwatch->show(); + _selectColor->show(); + _variable->hide(); + _toggleType->setVisible(!GetVariables().empty()); + } else { + _colorSwatch->hide(); + _selectColor->hide(); + _variable->show(); + _variable->setToolTip(obs_module_text( + "AdvSceneSwitcher.condition.video.colorVariableTooltip")); + _toggleType->show(); + } + adjustSize(); + updateGeometry(); +} + +} // namespace advss diff --git a/lib/variables/variable-color-button.hpp b/lib/variables/variable-color-button.hpp new file mode 100644 index 00000000..3e576e38 --- /dev/null +++ b/lib/variables/variable-color-button.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "export-symbol-helper.hpp" +#include "variable-color.hpp" + +#include +#include +#include + +namespace advss { + +class ADVSS_EXPORT VariableColorButton : public QWidget { + Q_OBJECT +public: + VariableColorButton(QWidget *parent, const QString &selectText); + void SetValue(const ColorVariable &); + ColorVariable Value() const { return _color; } + +public slots: + void SelectColorClicked(); + void VariableChanged(const QString &); + void ToggleTypeClicked(bool useVariable); + +signals: + void ColorVariableChanged(const ColorVariable &); + +private: + void SetupColorLabel(const QColor &); + void SetVisibility(); + + ColorVariable _color; + QLabel *_colorSwatch; + QPushButton *_selectColor; + VariableSelection *_variable; + QPushButton *_toggleType; +}; + +} // namespace advss diff --git a/lib/variables/variable-color.cpp b/lib/variables/variable-color.cpp new file mode 100644 index 00000000..8b5e478a --- /dev/null +++ b/lib/variables/variable-color.cpp @@ -0,0 +1,53 @@ +#include "variable-color.hpp" + +#include + +namespace advss { + +ColorVariable::ColorVariable(const QColor &value) : _value(value) {} + +void ColorVariable::Save(obs_data_t *obj, const char *name) const +{ + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_int(data, "version", 1); + obs_data_set_int(data, "type", static_cast(_type)); + auto var = _variable.lock(); + if (var) { + obs_data_set_string(data, "variable", var->Name().c_str()); + } + obs_data_set_int(data, "red", _value.red()); + obs_data_set_int(data, "green", _value.green()); + obs_data_set_int(data, "blue", _value.blue()); + obs_data_set_obj(obj, name, data); +} + +void ColorVariable::Load(obs_data_t *obj, const char *name) +{ + OBSDataAutoRelease data = obs_data_get_obj(obj, name); + _value.setRed(obs_data_get_int(data, "red")); + _value.setGreen(obs_data_get_int(data, "green")); + _value.setBlue(obs_data_get_int(data, "blue")); + if (!obs_data_has_user_value(data, "version")) { + // Old format: no variable support, just R/G/B + _type = Type::FIXED_VALUE; + return; + } + auto variableName = obs_data_get_string(data, "variable"); + _variable = GetWeakVariableByName(variableName); + _type = static_cast(obs_data_get_int(data, "type")); +} + +QColor ColorVariable::GetValue() const +{ + if (_type == Type::FIXED_VALUE) { + return _value; + } + auto var = _variable.lock(); + if (!var) { + return Qt::black; + } + const QColor color(QString::fromStdString(var->Value())); + return color.isValid() ? color : Qt::black; +} + +} // namespace advss diff --git a/lib/variables/variable-color.hpp b/lib/variables/variable-color.hpp new file mode 100644 index 00000000..fe4ff003 --- /dev/null +++ b/lib/variables/variable-color.hpp @@ -0,0 +1,35 @@ +#pragma once +#include "variable.hpp" + +#include +#include + +namespace advss { + +class VariableColorButton; + +class ADVSS_EXPORT ColorVariable { +public: + enum class Type { FIXED_VALUE, VARIABLE }; + + ColorVariable() = default; + ColorVariable(const QColor &value); + + void Save(obs_data_t *obj, const char *name) const; + void Load(obs_data_t *obj, const char *name); + + QColor GetValue() const; + QColor GetFixedValue() const { return _value; } + bool IsFixedType() const { return _type == Type::FIXED_VALUE; } + Type GetType() const { return _type; } + std::weak_ptr GetVariable() const { return _variable; } + +private: + Type _type = Type::FIXED_VALUE; + QColor _value = Qt::black; + std::weak_ptr _variable; + + friend class VariableColorButton; +}; + +} // namespace advss