diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index d763d014..9cb9e544 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -494,7 +494,13 @@ AdvSceneSwitcher.condition.midi.entry.listen="Set MIDI message selection to mess AdvSceneSwitcher.condition.display="Display" AdvSceneSwitcher.condition.display.type.displayName="Name of connected displays matches" AdvSceneSwitcher.condition.display.type.displayCount="Number of connected displays is" -AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}" +AdvSceneSwitcher.condition.display.type.displayWidth="Display width is" +AdvSceneSwitcher.condition.display.type.displayHeight="Display height is" +AdvSceneSwitcher.condition.display.compare.equals="Equals" +AdvSceneSwitcher.condition.display.compare.less="Less than" +AdvSceneSwitcher.condition.display.compare.more="More than" +AdvSceneSwitcher.condition.display.useDevicePixelRatio="Factor in ratio between physical pixels and device-independent pixels" +AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{compareModes}}{{displayHeight}}{{displayWidth}}{{regex}}{{displayCount}}" AdvSceneSwitcher.condition.slideshow="Slide Show" AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Slide changed" AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Current slide number is" @@ -1549,6 +1555,15 @@ AdvSceneSwitcher.tempVar.video.color.description="The average RGB color in a giv AdvSceneSwitcher.tempVar.websocket.message="Received websocket message" AdvSceneSwitcher.tempVar.websocket.message.description="The received websocket message, which matched the given pattern" +AdvSceneSwitcher.tempVar.display.name="Display name" +AdvSceneSwitcher.tempVar.display.name.description="Name of the display which matched the given pattern" +AdvSceneSwitcher.tempVar.display.count="Display count" +AdvSceneSwitcher.tempVar.display.count.description="The number of displays detected" +AdvSceneSwitcher.tempVar.display.width="Display width" +AdvSceneSwitcher.tempVar.display.width.description="The width of the display which matched the given pattern" +AdvSceneSwitcher.tempVar.display.height="Display height" +AdvSceneSwitcher.tempVar.display.height.description="The height of the display which matched the given pattern" + AdvSceneSwitcher.selectScene="--select scene--" AdvSceneSwitcher.selectPreviousScene="Previous Scene" AdvSceneSwitcher.selectCurrentScene="Current Scene" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index c04a5aa5..bcaac533 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -442,7 +442,6 @@ AdvSceneSwitcher.condition.midi.entry.listen="将MIDI信息选择设置为从选 AdvSceneSwitcher.condition.display="显示器" AdvSceneSwitcher.condition.display.type.displayName="连接的显示器的名称匹配" AdvSceneSwitcher.condition.display.type.displayCount="连接的显示器的数量为" -AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}" ; Macro Actions AdvSceneSwitcher.action.scene="切换场景" diff --git a/plugins/base/macro-condition-display.cpp b/plugins/base/macro-condition-display.cpp index 5d5a4aeb..e1ad3ba9 100644 --- a/plugins/base/macro-condition-display.cpp +++ b/plugins/base/macro-condition-display.cpp @@ -3,6 +3,7 @@ #include "monitor-helpers.hpp" #include +#include namespace advss { @@ -13,15 +14,82 @@ bool MacroConditionDisplay::_registered = MacroConditionFactory::Register( {MacroConditionDisplay::Create, MacroConditionDisplayEdit::Create, "AdvSceneSwitcher.condition.display"}); -const static std::map +static const std::map conditionTypes = { {MacroConditionDisplay::Condition::DISPLAY_NAME, "AdvSceneSwitcher.condition.display.type.displayName"}, {MacroConditionDisplay::Condition::DISPLAY_COUNT, "AdvSceneSwitcher.condition.display.type.displayCount"}, + {MacroConditionDisplay::Condition::DISPLAY_WIDTH, + "AdvSceneSwitcher.condition.display.type.displayWidth"}, + {MacroConditionDisplay::Condition::DISPLAY_HEIGHT, + "AdvSceneSwitcher.condition.display.type.displayHeight"}, }; -static bool matchDisplayNames(const std::string &name, const RegexConfig ®ex) +static const std::map + compareModes = { + {MacroConditionDisplay::CompareMode::EQUALS, + "AdvSceneSwitcher.condition.display.compare.equals"}, + {MacroConditionDisplay::CompareMode::LESS, + "AdvSceneSwitcher.condition.display.compare.less"}, + {MacroConditionDisplay::CompareMode::MORE, + "AdvSceneSwitcher.condition.display.compare.more"}, +}; + +static bool compare(MacroConditionDisplay::CompareMode compare, int value1, + int value2) +{ + switch (compare) { + case MacroConditionDisplay::CompareMode::EQUALS: + return value1 == value2; + case MacroConditionDisplay::CompareMode::LESS: + return value1 < value2; + case MacroConditionDisplay::CompareMode::MORE: + return value1 > value2; + default: + break; + } + return false; +} + +static std::optional getMonitorSize(const QString &monitorName, + const RegexConfig ®ex, bool height, + bool useDevicePixelRatio) +{ + auto monitorNames = GetMonitorNames(); + int index = -1; + if (regex.Enabled()) { + index = monitorNames.indexOf( + regex.GetRegularExpression(monitorName)); + } else { + index = monitorNames.indexOf(monitorName); + } + + if (index == -1) { + return {}; + } + + QList screens = QGuiApplication::screens(); + if (index >= screens.size()) { + return {}; + } + + auto screen = screens.at(index); + if (!screen) { + return {}; + } + + auto screenGeometry = screen->geometry(); + qreal ratio = useDevicePixelRatio ? screen->devicePixelRatio() : 1; + + return height ? screenGeometry.height() * ratio + : screenGeometry.width() * ratio; +} + +static bool +matchDisplayNames(const std::string &name, const RegexConfig ®ex, + std::function + setVariable) { auto monitors = GetMonitorNames(); if (regex.Enabled()) { @@ -33,12 +101,14 @@ static bool matchDisplayNames(const std::string &name, const RegexConfig ®ex) for (const auto &m : monitors) { auto match = expr.match(m); if (match.hasMatch()) { + setVariable("name", m.toStdString()); return true; } } } else { for (const auto &m : monitors) { if (m.toStdString() == name) { + setVariable("name", m.toStdString()); return true; } } @@ -49,10 +119,39 @@ static bool matchDisplayNames(const std::string &name, const RegexConfig ®ex) bool MacroConditionDisplay::CheckCondition() { switch (_condition) { - case advss::MacroConditionDisplay::Condition::DISPLAY_NAME: - return matchDisplayNames(_displayName, _regexConf); - case advss::MacroConditionDisplay::Condition::DISPLAY_COUNT: - return _displayCount == QGuiApplication::screens().count(); + case Condition::DISPLAY_NAME: + return matchDisplayNames(_displayName, _regexConf, + [this](const std::string &var, + const std::string &value) { + SetTempVarValue(var, value); + }); + case Condition::DISPLAY_COUNT: { + int count = QGuiApplication::screens().count(); + SetTempVarValue("count", std::to_string(count)); + return compare(_compare, count, _displayCount); + } + case Condition::DISPLAY_WIDTH: { + auto size = getMonitorSize(QString::fromStdString(_displayName), + _regexConf, false, + _useDevicePixelRatio); + if (size.has_value() && + compare(_compare, *size, _displayWidth)) { + SetTempVarValue("width", std::to_string(*size)); + return true; + } + return false; + } + case Condition::DISPLAY_HEIGHT: { + auto size = getMonitorSize(QString::fromStdString(_displayName), + _regexConf, true, + _useDevicePixelRatio); + if (size.has_value() && + compare(_compare, *size, _displayHeight)) { + SetTempVarValue("height", std::to_string(*size)); + return true; + } + return false; + } default: break; } @@ -63,9 +162,13 @@ bool MacroConditionDisplay::Save(obs_data_t *obj) const { MacroCondition::Save(obj); obs_data_set_int(obj, "condition", static_cast(_condition)); + obs_data_set_int(obj, "compareMode", static_cast(_compare)); _displayName.Save(obj, "displayName"); _regexConf.Save(obj); _displayCount.Save(obj, "displayCount"); + _displayWidth.Save(obj, "displayWidth"); + _displayHeight.Save(obj, "displayHeight"); + obs_data_set_bool(obj, "useDevicePixelRatio", _useDevicePixelRatio); return true; } @@ -73,16 +176,76 @@ bool MacroConditionDisplay::Load(obs_data_t *obj) { MacroCondition::Load(obj); _condition = static_cast(obs_data_get_int(obj, "condition")); + _compare = + static_cast(obs_data_get_int(obj, "compareMode")); _displayName.Load(obj, "displayName"); _regexConf.Load(obj); _displayCount.Load(obj, "displayCount"); + _displayWidth.Load(obj, "displayWidth"); + _displayHeight.Load(obj, "displayHeight"); + obs_data_set_default_bool(obj, "useDevicePixelRatio", true); + _useDevicePixelRatio = obs_data_get_bool(obj, "useDevicePixelRatio"); return true; } +void MacroConditionDisplay::SetCondition(Condition condition) +{ + _condition = condition; + SetupTempVars(); +} + +void MacroConditionDisplay::SetupTempVars() +{ + MacroCondition::SetupTempVars(); + switch (_condition) { + case Condition::DISPLAY_NAME: + AddTempvar( + "name", + obs_module_text( + "AdvSceneSwitcher.tempVar.display.name"), + obs_module_text( + "AdvSceneSwitcher.tempVar.display.name.description")); + break; + case Condition::DISPLAY_COUNT: + AddTempvar( + "count", + obs_module_text( + "AdvSceneSwitcher.tempVar.display.count"), + obs_module_text( + "AdvSceneSwitcher.tempVar.display.count.description")); + break; + case Condition::DISPLAY_WIDTH: + AddTempvar( + "width", + obs_module_text( + "AdvSceneSwitcher.tempVar.display.width"), + obs_module_text( + "AdvSceneSwitcher.tempVar.display.width.description")); + break; + case Condition::DISPLAY_HEIGHT: + AddTempvar( + "height", + obs_module_text( + "AdvSceneSwitcher.tempVar.display.height"), + obs_module_text( + "AdvSceneSwitcher.tempVar.display.height.description")); + break; + default: + break; + } +} + static inline void populateConditionSelection(QComboBox *list) { - for (const auto &entry : conditionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : conditionTypes) { + list->addItem(obs_module_text(name.c_str())); + } +} + +static inline void populateCompareModeselection(QComboBox *list) +{ + for (const auto &[_, name] : compareModes) { + list->addItem(obs_module_text(name.c_str())); } } @@ -90,16 +253,26 @@ MacroConditionDisplayEdit::MacroConditionDisplayEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), _conditions(new QComboBox()), + _compareModes(new QComboBox()), _displays(new QComboBox()), _regex(new RegexConfigWidget()), - _displayCount(new VariableSpinBox(this)) + _displayCount(new VariableSpinBox(this)), + _displayWidth(new VariableSpinBox(this)), + _displayHeight(new VariableSpinBox(this)), + _useDevicePixelRatio(new QCheckBox(obs_module_text( + "AdvSceneSwitcher.condition.display.useDevicePixelRatio"))) { populateConditionSelection(_conditions); + populateCompareModeselection(_compareModes); _displays->addItems(GetMonitorNames()); _displays->setEditable(true); + _displayWidth->setMaximum(99999); + _displayHeight->setMaximum(99999); QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this, SLOT(ConditionChanged(int))); + QWidget::connect(_compareModes, SIGNAL(currentIndexChanged(int)), this, + SLOT(CompareModeChanged(int))); QWidget::connect(_displays, SIGNAL(currentTextChanged(const QString &)), this, SLOT(DisplayNameChanged(const QString &))); QWidget::connect(_regex, @@ -109,18 +282,32 @@ MacroConditionDisplayEdit::MacroConditionDisplayEdit( _displayCount, SIGNAL(NumberVariableChanged(const NumberVariable &)), this, SLOT(DisplayCountChanged(const NumberVariable &))); + QWidget::connect( + _displayWidth, + SIGNAL(NumberVariableChanged(const NumberVariable &)), + this, SLOT(DisplayWidthChanged(const NumberVariable &))); + QWidget::connect( + _displayHeight, + SIGNAL(NumberVariableChanged(const NumberVariable &)), + this, SLOT(DisplayHeightChanged(const NumberVariable &))); + QWidget::connect(_useDevicePixelRatio, SIGNAL(stateChanged(int)), this, + SLOT(UseDevicePixelRatioChanged(int))); - auto mainLayout = new QHBoxLayout; - std::unordered_map widgetPlaceholders = { - {"{{conditions}}", _conditions}, - {"{{displays}}", _displays}, - {"{{regex}}", _regex}, - {"{{displayCount}}", _displayCount}, - }; + auto entryLayout = new QHBoxLayout; PlaceWidgets( obs_module_text("AdvSceneSwitcher.condition.display.entry"), - mainLayout, widgetPlaceholders); - setLayout(mainLayout); + entryLayout, + {{"{{conditions}}", _conditions}, + {"{{compareModes}}", _compareModes}, + {"{{displays}}", _displays}, + {"{{regex}}", _regex}, + {"{{displayCount}}", _displayCount}, + {"{{displayWidth}}", _displayWidth}, + {"{{displayHeight}}", _displayHeight}}); + auto layout = new QVBoxLayout; + layout->addLayout(entryLayout); + layout->addWidget(_useDevicePixelRatio); + setLayout(layout); _entryData = entryData; UpdateEntryData(); @@ -134,11 +321,22 @@ void MacroConditionDisplayEdit::ConditionChanged(int value) } auto lock = LockContext(); - _entryData->_condition = - static_cast(value); + _entryData->SetCondition( + static_cast(value)); SetWidgetVisibility(); } +void MacroConditionDisplayEdit::CompareModeChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_compare = + static_cast(value); +} + void MacroConditionDisplayEdit::DisplayNameChanged(const QString &display) { if (_loading || !_entryData) { @@ -173,29 +371,96 @@ void MacroConditionDisplayEdit::DisplayCountChanged( _entryData->_displayCount = value; } +void MacroConditionDisplayEdit::DisplayWidthChanged( + const NumberVariable &value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_displayWidth = value; +} + +void MacroConditionDisplayEdit::DisplayHeightChanged( + const NumberVariable &value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_displayHeight = value; +} + +void MacroConditionDisplayEdit::UseDevicePixelRatioChanged(int state) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_useDevicePixelRatio = state; +} + void MacroConditionDisplayEdit::UpdateEntryData() { if (!_entryData) { return; } - _conditions->setCurrentIndex(static_cast(_entryData->_condition)); + _conditions->setCurrentIndex( + static_cast(_entryData->GetCondition())); + _compareModes->setCurrentIndex(static_cast(_entryData->_compare)); _displays->setCurrentText(QString::fromStdString( _entryData->_displayName.UnresolvedValue())); _regex->SetRegexConfig(_entryData->_regexConf); _displayCount->SetValue(_entryData->_displayCount); + _displayWidth->SetValue(_entryData->_displayWidth); + _displayHeight->SetValue(_entryData->_displayHeight); + _useDevicePixelRatio->setChecked(_entryData->_useDevicePixelRatio); SetWidgetVisibility(); } void MacroConditionDisplayEdit::SetWidgetVisibility() { - _displays->setVisible(_entryData->_condition == - MacroConditionDisplay::Condition::DISPLAY_NAME); - _regex->setVisible(_entryData->_condition == - MacroConditionDisplay::Condition::DISPLAY_NAME); + _displays->setVisible( + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_NAME || + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_WIDTH || + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_HEIGHT); + _compareModes->setVisible( + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_WIDTH || + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_HEIGHT || + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_COUNT); + _regex->setVisible( + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_NAME || + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_WIDTH || + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_HEIGHT); _displayCount->setVisible( - _entryData->_condition == + _entryData->GetCondition() == MacroConditionDisplay::Condition::DISPLAY_COUNT); + _displayWidth->setVisible( + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_WIDTH); + _displayHeight->setVisible( + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_HEIGHT); + _useDevicePixelRatio->setVisible( + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_WIDTH || + _entryData->GetCondition() == + MacroConditionDisplay::Condition::DISPLAY_HEIGHT); + adjustSize(); + updateGeometry(); } } // namespace advss diff --git a/plugins/base/macro-condition-display.hpp b/plugins/base/macro-condition-display.hpp index 0cdbe157..b1c264da 100644 --- a/plugins/base/macro-condition-display.hpp +++ b/plugins/base/macro-condition-display.hpp @@ -24,13 +24,27 @@ public: enum class Condition { DISPLAY_NAME, DISPLAY_COUNT, + DISPLAY_WIDTH, + DISPLAY_HEIGHT, }; - Condition _condition = Condition::DISPLAY_NAME; + enum class CompareMode { EQUALS, LESS, MORE }; + CompareMode _compare = CompareMode::EQUALS; + + void SetCondition(Condition); + Condition GetCondition() const { return _condition; } + StringVariable _displayName; RegexConfig _regexConf; IntVariable _displayCount; + IntVariable _displayWidth; + IntVariable _displayHeight; + bool _useDevicePixelRatio = true; private: + void SetupTempVars(); + + Condition _condition = Condition::DISPLAY_NAME; + static bool _registered; static const std::string id; }; @@ -53,20 +67,27 @@ public: private slots: void ConditionChanged(int); + void CompareModeChanged(int); void DisplayNameChanged(const QString &); void RegexChanged(const RegexConfig &conf); void DisplayCountChanged(const NumberVariable &); - -protected: - QComboBox *_conditions; - QComboBox *_displays; - RegexConfigWidget *_regex; - VariableSpinBox *_displayCount; - std::shared_ptr _entryData; + void DisplayWidthChanged(const NumberVariable &); + void DisplayHeightChanged(const NumberVariable &); + void UseDevicePixelRatioChanged(int state); private: void SetWidgetVisibility(); + QComboBox *_conditions; + QComboBox *_compareModes; + QComboBox *_displays; + RegexConfigWidget *_regex; + VariableSpinBox *_displayCount; + VariableSpinBox *_displayWidth; + VariableSpinBox *_displayHeight; + QCheckBox *_useDevicePixelRatio; + + std::shared_ptr _entryData; bool _loading = true; };