From fd7e48eff9e66648627f47ae48876ec80b045f1f Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 12 Nov 2021 19:47:43 +0100 Subject: [PATCH] Add scene-visibility macro condition --- CMakeLists.txt | 2 + data/locale/en-US.ini | 4 + .../macro-condition-scene-visibility.hpp | 66 +++++++ src/macro-condition-scene-visibility.cpp | 182 ++++++++++++++++++ 4 files changed, 254 insertions(+) create mode 100644 src/headers/macro-condition-scene-visibility.hpp create mode 100644 src/macro-condition-scene-visibility.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c4514fe..8573a9c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,6 +245,7 @@ set(advanced-scene-switcher_HEADERS src/headers/macro-condition-replay-buffer.hpp src/headers/macro-condition-scene-order.hpp src/headers/macro-condition-scene-transform.hpp + src/headers/macro-condition-scene-visibility.hpp src/headers/macro-condition-scene.hpp src/headers/macro-condition-source.hpp src/headers/macro-condition-streaming.hpp @@ -336,6 +337,7 @@ set(advanced-scene-switcher_SOURCES src/macro-condition-replay-buffer.cpp src/macro-condition-scene-order.cpp src/macro-condition-scene-transform.cpp + src/macro-condition-scene-visibility.cpp src/macro-condition-scene.cpp src/macro-condition-source.cpp src/macro-condition-streaming.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 97b7eeaf..0c606ffe 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -233,6 +233,10 @@ AdvSceneSwitcher.condition.transition.type.started="Transition active" AdvSceneSwitcher.condition.transition.type.ended="Transition ended" AdvSceneSwitcher.condition.transition.durationSuffix="seconds" AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{duration}}{{durationSuffix}}" +AdvSceneSwitcher.condition.sceneVisibility="Scene item visibility" +AdvSceneSwitcher.condition.sceneVisibility.type.shown="Shown" +AdvSceneSwitcher.condition.sceneVisibility.type.hidden="Hidden" +AdvSceneSwitcher.condition.sceneVisibility.entry="On {{scenes}} {{sources}} is {{conditions}} " ; Macro Actions AdvSceneSwitcher.action.switchScene="Switch scene" diff --git a/src/headers/macro-condition-scene-visibility.hpp b/src/headers/macro-condition-scene-visibility.hpp new file mode 100644 index 00000000..7360fc24 --- /dev/null +++ b/src/headers/macro-condition-scene-visibility.hpp @@ -0,0 +1,66 @@ +#pragma once +#include "macro.hpp" +#include "scene-selection.hpp" + +#include + +enum class SceneVisibilityCondition { + SHOWN, + HIDDEN, +}; + +class MacroConditionSceneVisibility : public MacroCondition { +public: + bool CheckCondition(); + bool Save(obs_data_t *obj); + bool Load(obs_data_t *obj); + std::string GetShortDesc(); + std::string GetId() { return id; }; + static std::shared_ptr Create() + { + return std::make_shared(); + } + + SceneSelection _scene; + OBSWeakSource _source; + SceneVisibilityCondition _condition = SceneVisibilityCondition::SHOWN; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroConditionSceneVisibilityEdit : public QWidget { + Q_OBJECT + +public: + MacroConditionSceneVisibilityEdit( + QWidget *parent, + std::shared_ptr cond = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr cond) + { + return new MacroConditionSceneVisibilityEdit( + parent, + std::dynamic_pointer_cast( + cond)); + } + +private slots: + void SceneChanged(const SceneSelection &); + void SourceChanged(const QString &text); + void ConditionChanged(int cond); +signals: + void HeaderInfoChanged(const QString &); + +protected: + SceneSelectionWidget *_scenes; + QComboBox *_sources; + QComboBox *_conditions; + + std::shared_ptr _entryData; + +private: + bool _loading = true; +}; diff --git a/src/macro-condition-scene-visibility.cpp b/src/macro-condition-scene-visibility.cpp new file mode 100644 index 00000000..78f5394e --- /dev/null +++ b/src/macro-condition-scene-visibility.cpp @@ -0,0 +1,182 @@ +#include "headers/macro-condition-edit.hpp" +#include "headers/macro-condition-scene-visibility.hpp" +#include "headers/utility.hpp" +#include "headers/advanced-scene-switcher.hpp" + +#include + +const std::string MacroConditionSceneVisibility::id = "scene_visibility"; + +bool MacroConditionSceneVisibility::_registered = + MacroConditionFactory::Register( + MacroConditionSceneVisibility::id, + {MacroConditionSceneVisibility::Create, + MacroConditionSceneVisibilityEdit::Create, + "AdvSceneSwitcher.condition.sceneVisibility"}); + +static std::map + SceneVisibilityConditionTypes = { + {SceneVisibilityCondition::SHOWN, + "AdvSceneSwitcher.condition.sceneVisibility.type.shown"}, + {SceneVisibilityCondition::HIDDEN, + "AdvSceneSwitcher.condition.sceneVisibility.type.hidden"}, +}; + +struct VisibilityData { + std::string name; + bool visible; + bool result; +}; + +static bool visibilityEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr) +{ + VisibilityData *vInfo = reinterpret_cast(ptr); + auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item)); + if (vInfo->name == sourceName && + obs_sceneitem_visible(item) == vInfo->visible) { + vInfo->result = true; + return false; + } + + if (obs_sceneitem_is_group(item)) { + obs_scene_t *scene = obs_sceneitem_group_get_scene(item); + obs_scene_enum_items(scene, visibilityEnum, ptr); + } + + return true; +} + +bool MacroConditionSceneVisibility::CheckCondition() +{ + if (!_source) { + return false; + } + + auto s = obs_weak_source_get_source(_scene.GetScene()); + auto scene = obs_scene_from_source(s); + auto sourceName = GetWeakSourceName(_source); + VisibilityData data = {sourceName, + _condition == SceneVisibilityCondition::SHOWN, + false}; + obs_scene_enum_items(scene, visibilityEnum, &data); + obs_source_release(s); + return data.result; +} + +bool MacroConditionSceneVisibility::Save(obs_data_t *obj) +{ + MacroCondition::Save(obj); + _scene.Save(obj); + obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str()); + + obs_data_set_int(obj, "condition", static_cast(_condition)); + + return true; +} + +bool MacroConditionSceneVisibility::Load(obs_data_t *obj) +{ + MacroCondition::Load(obj); + _scene.Load(obj); + const char *sourceName = obs_data_get_string(obj, "source"); + _source = GetWeakSourceByName(sourceName); + _condition = static_cast( + obs_data_get_int(obj, "condition")); + return true; +} + +std::string MacroConditionSceneVisibility::GetShortDesc() +{ + if (_source) { + return _scene.ToString() + " - " + GetWeakSourceName(_source); + } + return ""; +} + +static inline void populateConditionSelection(QComboBox *list) +{ + for (auto entry : SceneVisibilityConditionTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + +MacroConditionSceneVisibilityEdit::MacroConditionSceneVisibilityEdit( + QWidget *parent, + std::shared_ptr entryData) + : QWidget(parent) +{ + _scenes = new SceneSelectionWidget(window(), false, true, true); + _sources = new QComboBox(); + _conditions = new QComboBox(); + + populateConditionSelection(_conditions); + + QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), + this, SLOT(SceneChanged(const SceneSelection &))); + QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)), + this, SLOT(SourceChanged(const QString &))); + QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this, + SLOT(ConditionChanged(int))); + + std::unordered_map widgetPlaceholders = { + {"{{sources}}", _sources}, + {"{{scenes}}", _scenes}, + {"{{conditions}}", _conditions}, + }; + QHBoxLayout *mainLayout = new QHBoxLayout; + placeWidgets( + obs_module_text( + "AdvSceneSwitcher.condition.sceneVisibility.entry"), + mainLayout, widgetPlaceholders); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroConditionSceneVisibilityEdit::SourceChanged(const QString &text) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_source = GetWeakSourceByQString(text); +} + +void MacroConditionSceneVisibilityEdit::SceneChanged(const SceneSelection &s) +{ + if (_loading || !_entryData) { + return; + } + { + std::lock_guard lock(switcher->m); + _entryData->_scene = s; + } + _sources->clear(); + populateSceneItemSelection(_sources, _entryData->_scene); +} + +void MacroConditionSceneVisibilityEdit::ConditionChanged(int index) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_condition = static_cast(index); +} + +void MacroConditionSceneVisibilityEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _conditions->setCurrentIndex(static_cast(_entryData->_condition)); + _scenes->SetScene(_entryData->_scene); + populateSceneItemSelection(_sources, _entryData->_scene); + _sources->setCurrentText( + GetWeakSourceName(_entryData->_source).c_str()); +}