From e452d8cc8c4107159e359086200e8ebbedd5da7b Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 7 Nov 2021 12:21:07 +0100 Subject: [PATCH] Allow selecting source type for scene visibility action This should allow to simplify some setups which required showing / hiding all sources of a particular type. --- data/locale/en-US.ini | 4 +- src/headers/macro-action-scene-visibility.hpp | 9 ++ src/headers/utility.hpp | 1 + src/macro-action-scene-visibility.cpp | 136 +++++++++++++++--- src/utility.cpp | 30 ++++ 5 files changed, 161 insertions(+), 19 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 2b14059c..97b7eeaf 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -272,7 +272,9 @@ AdvSceneSwitcher.action.run.entry="Run {{filePath}}" AdvSceneSwitcher.action.sceneVisibility="Scene item visibility" AdvSceneSwitcher.action.sceneVisibility.type.show="Show" AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide" -AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sources}}" +AdvSceneSwitcher.action.sceneVisibility.type.source="Source" +AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any" +AdvSceneSwitcher.action.sceneVisibility.entry="On {{scenes}} {{actions}} {{sourceTypes}} {{sources}}" AdvSceneSwitcher.action.filter="Filter" AdvSceneSwitcher.action.filter.type.enable="Enable" AdvSceneSwitcher.action.filter.type.disable="Disable" diff --git a/src/headers/macro-action-scene-visibility.hpp b/src/headers/macro-action-scene-visibility.hpp index 68c0fb8d..0c31cd21 100644 --- a/src/headers/macro-action-scene-visibility.hpp +++ b/src/headers/macro-action-scene-visibility.hpp @@ -8,6 +8,11 @@ enum class SceneVisibilityAction { HIDE, }; +enum class SceneItemSourceType { + SOURCE, + SOURCE_GROUP, +}; + class MacroActionSceneVisibility : public MacroAction { public: bool PerformAction(); @@ -22,7 +27,9 @@ public: } SceneSelection _scene; + SceneItemSourceType _sourceType = SceneItemSourceType::SOURCE; OBSWeakSource _source; + std::string _sourceGroup = ""; SceneVisibilityAction _action = SceneVisibilityAction::SHOW; private: @@ -49,6 +56,7 @@ public: private slots: void SceneChanged(const SceneSelection &); + void SourceTypeChanged(int value); void SourceChanged(const QString &text); void ActionChanged(int value); signals: @@ -56,6 +64,7 @@ signals: protected: SceneSelectionWidget *_scenes; + QComboBox *_sourceTypes; QComboBox *_sources; QComboBox *_actions; std::shared_ptr _entryData; diff --git a/src/headers/utility.hpp b/src/headers/utility.hpp index 15165eca..4d5d7537 100644 --- a/src/headers/utility.hpp +++ b/src/headers/utility.hpp @@ -78,3 +78,4 @@ void populateFilterSelection(QComboBox *list, void populateSceneItemSelection(QComboBox *list, OBSWeakSource sceneWeakSource = nullptr); void populateSceneItemSelection(QComboBox *list, SceneSelection &s); +void populateSourceTypeSelection(QComboBox *list); diff --git a/src/macro-action-scene-visibility.cpp b/src/macro-action-scene-visibility.cpp index 580f5e27..15540330 100644 --- a/src/macro-action-scene-visibility.cpp +++ b/src/macro-action-scene-visibility.cpp @@ -17,12 +17,20 @@ const static std::map actionTypes = { "AdvSceneSwitcher.action.sceneVisibility.type.hide"}, }; +const static std::map sourceItemSourceTypes = { + {SceneItemSourceType::SOURCE, + "AdvSceneSwitcher.action.sceneVisibility.type.source"}, + {SceneItemSourceType::SOURCE_GROUP, + "AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup"}, +}; + struct VisInfo { std::string name; bool visible; }; -static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr) +static bool visibilitySourceEnum(obs_scene_t *, obs_sceneitem_t *item, + void *ptr) { VisInfo *vInfo = reinterpret_cast(ptr); auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item)); @@ -32,7 +40,26 @@ static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr) if (obs_sceneitem_is_group(item)) { obs_scene_t *scene = obs_sceneitem_group_get_scene(item); - obs_scene_enum_items(scene, visibilityEnum, ptr); + obs_scene_enum_items(scene, visibilitySourceEnum, ptr); + } + + return true; +} + +static bool visibilitySourceTypeEnum(obs_scene_t *, obs_sceneitem_t *item, + void *ptr) +{ + VisInfo *vInfo = reinterpret_cast(ptr); + + auto sourceTypeName = obs_source_get_display_name( + obs_source_get_id(obs_sceneitem_get_source(item))); + if (vInfo->name == sourceTypeName) { + obs_sceneitem_set_visible(item, vInfo->visible); + } + + if (obs_sceneitem_is_group(item)) { + obs_scene_t *scene = obs_sceneitem_group_get_scene(item); + obs_scene_enum_items(scene, visibilitySourceTypeEnum, ptr); } return true; @@ -43,18 +70,21 @@ bool MacroActionSceneVisibility::PerformAction() auto s = obs_weak_source_get_source(_scene.GetScene()); auto scene = obs_scene_from_source(s); auto sourceName = GetWeakSourceName(_source); - VisInfo vInfo = {sourceName, _action == SceneVisibilityAction::SHOW}; + VisInfo vInfo = {"", _action == SceneVisibilityAction::SHOW}; - switch (_action) { - case SceneVisibilityAction::SHOW: - obs_scene_enum_items(scene, visibilityEnum, &vInfo); + switch (_sourceType) { + case SceneItemSourceType::SOURCE: + vInfo.name = sourceName; + obs_scene_enum_items(scene, visibilitySourceEnum, &vInfo); break; - case SceneVisibilityAction::HIDE: - obs_scene_enum_items(scene, visibilityEnum, &vInfo); + case SceneItemSourceType::SOURCE_GROUP: + vInfo.name = _sourceGroup; + obs_scene_enum_items(scene, visibilitySourceTypeEnum, &vInfo); break; default: break; } + obs_source_release(s); return true; } @@ -63,10 +93,18 @@ void MacroActionSceneVisibility::LogAction() { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { - vblog(LOG_INFO, - "performed visibility action \"%s\" for source \"%s\" on scene \"%s\"", - it->second.c_str(), GetWeakSourceName(_source).c_str(), - _scene.ToString().c_str()); + if (_sourceType == SceneItemSourceType::SOURCE) { + vblog(LOG_INFO, + "performed visibility action \"%s\" for source \"%s\" on scene \"%s\"", + it->second.c_str(), + GetWeakSourceName(_source).c_str(), + _scene.ToString().c_str()); + } else { + vblog(LOG_INFO, + "performed visibility action \"%s\" for any source type \"%s\" on scene \"%s\"", + it->second.c_str(), _sourceGroup.c_str(), + _scene.ToString().c_str()); + } } else { blog(LOG_WARNING, "ignored unknown SceneVisibility action %d", static_cast(_action)); @@ -77,8 +115,14 @@ bool MacroActionSceneVisibility::Save(obs_data_t *obj) { MacroAction::Save(obj); _scene.Save(obj); - obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str()); + if (_sourceType == SceneItemSourceType::SOURCE) { + obs_data_set_string(obj, "source", + GetWeakSourceName(_source).c_str()); + } else { + obs_data_set_string(obj, "source", _sourceGroup.c_str()); + } obs_data_set_int(obj, "action", static_cast(_action)); + obs_data_set_int(obj, "sourceType", static_cast(_sourceType)); return true; } @@ -86,8 +130,11 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj) { MacroAction::Load(obj); _scene.Load(obj); + _sourceType = static_cast( + obs_data_get_int(obj, "sourceType")); const char *sourceName = obs_data_get_string(obj, "source"); _source = GetWeakSourceByName(sourceName); + _sourceGroup = sourceName; _action = static_cast( obs_data_get_int(obj, "action")); return true; @@ -95,9 +142,16 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj) std::string MacroActionSceneVisibility::GetShortDesc() { - if (_source) { + if (_sourceType == SceneItemSourceType::SOURCE && _source) { return _scene.ToString() + " - " + GetWeakSourceName(_source); } + if (_sourceType == SceneItemSourceType::SOURCE_GROUP && + !_sourceGroup.empty()) { + return _scene.ToString() + " - " + + obs_module_text( + "AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup") + + " " + _sourceGroup; + } return ""; } @@ -108,26 +162,38 @@ static inline void populateActionSelection(QComboBox *list) } } +static inline void populateSourceItemTypeSelection(QComboBox *list) +{ + for (auto entry : sourceItemSourceTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent) { _scenes = new SceneSelectionWidget(window(), false, false, true); + _sourceTypes = new QComboBox(); _sources = new QComboBox(); _actions = new QComboBox(); + populateSourceItemTypeSelection(_sourceTypes); populateActionSelection(_actions); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), this, SLOT(SceneChanged(const SceneSelection &))); + QWidget::connect(_sourceTypes, SIGNAL(currentIndexChanged(int)), this, + SLOT(SourceTypeChanged(int))); QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)), this, SLOT(SourceChanged(const QString &))); QHBoxLayout *mainLayout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { {"{{scenes}}", _scenes}, + {"{{sourceTypes}}", _sourceTypes}, {"{{sources}}", _sources}, {"{{actions}}", _actions}, }; @@ -148,10 +214,17 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData() } _actions->setCurrentIndex(static_cast(_entryData->_action)); + _sourceTypes->setCurrentIndex( + static_cast(_entryData->_sourceType)); _scenes->SetScene(_entryData->_scene); - populateSceneItemSelection(_sources, _entryData->_scene); - _sources->setCurrentText( - GetWeakSourceName(_entryData->_source).c_str()); + if (_entryData->_sourceType == SceneItemSourceType::SOURCE) { + populateSceneItemSelection(_sources, _entryData->_scene); + _sources->setCurrentText( + GetWeakSourceName(_entryData->_source).c_str()); + } else { + populateSourceTypeSelection(_sources); + _sources->setCurrentText(_entryData->_sourceGroup.c_str()); + } } void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s) @@ -167,6 +240,25 @@ void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s) populateSceneItemSelection(_sources, _entryData->_scene); } +void MacroActionSceneVisibilityEdit::SourceTypeChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + { + std::lock_guard lock(switcher->m); + _entryData->_sourceType = + static_cast(value); + } + + _sources->clear(); + if (_entryData->_sourceType == SceneItemSourceType::SOURCE) { + populateSceneItemSelection(_sources, _entryData->_scene); + } else { + populateSourceTypeSelection(_sources); + } +} + void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text) { if (_loading || !_entryData) { @@ -174,7 +266,15 @@ void MacroActionSceneVisibilityEdit::SourceChanged(const QString &text) } std::lock_guard lock(switcher->m); - _entryData->_source = GetWeakSourceByQString(text); + if (_entryData->_sourceType == SceneItemSourceType::SOURCE) { + _entryData->_source = GetWeakSourceByQString(text); + } else { + if (text == obs_module_text("AdvSceneSwitcher.selectItem")) { + _entryData->_sourceGroup = ""; + } else { + _entryData->_sourceGroup = text.toStdString(); + } + } emit HeaderInfoChanged( QString::fromStdString(_entryData->GetShortDesc())); } diff --git a/src/utility.cpp b/src/utility.cpp index 62031c98..5c0b0b90 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -828,6 +828,36 @@ void populateSceneItemSelection(QComboBox *list, SceneSelection &s) list->setCurrentIndex(0); } +void populateSourceTypeSelection(QComboBox *list) +{ + std::set sourceTypeNames; + auto enumSourcesTypes = [](void *param, obs_source_t *source) { + if (!source) { + return true; + } + std::set *names = + reinterpret_cast *>(param); + if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT) { + return true; + } + names->insert( + obs_source_get_display_name(obs_source_get_id(source))); + return true; + }; + + obs_enum_sources(enumSourcesTypes, &sourceTypeNames); + + for (auto &name : sourceTypeNames) { + if (!name.isEmpty()) { + list->addItem(name); + } + } + + list->model()->sort(0); + addSelectionEntry(list, obs_module_text("AdvSceneSwitcher.selectItem")); + list->setCurrentIndex(0); +} + QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor, QColor endColor, QString specifier, bool once)