From a7ccfc328204acbc182e1045a92a8313f3aebafa Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 9 Jun 2023 21:23:02 +0200 Subject: [PATCH] Add action to toggle lock of scene items --- CMakeLists.txt | 2 + data/locale/en-US.ini | 5 + src/macro-core/macro-action-scene-lock.cpp | 175 +++++++++++++++++++++ src/macro-core/macro-action-scene-lock.hpp | 69 ++++++++ 4 files changed, 251 insertions(+) create mode 100644 src/macro-core/macro-action-scene-lock.cpp create mode 100644 src/macro-core/macro-action-scene-lock.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c5535e9..21f7139a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,8 @@ target_sources( src/macro-core/macro-action-run.hpp src/macro-core/macro-action-scene-collection.cpp src/macro-core/macro-action-scene-collection.hpp + src/macro-core/macro-action-scene-lock.cpp + src/macro-core/macro-action-scene-lock.hpp src/macro-core/macro-action-scene-order.cpp src/macro-core/macro-action-scene-order.hpp src/macro-core/macro-action-scene-switch.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index b77a7c66..7219a949 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -692,6 +692,11 @@ AdvSceneSwitcher.action.midi="MIDI" AdvSceneSwitcher.action.midi.entry="Send message to {{device}}:" AdvSceneSwitcher.action.midi.entry.listen="Set MIDI message selection to messages incoming on {{listenDevices}}: {{listenButton}}" AdvSceneSwitcher.action.osc="Open Sound Control" +AdvSceneSwitcher.action.sceneLock="Scene item lock" +AdvSceneSwitcher.action.sceneLock.type.lock="lock" +AdvSceneSwitcher.action.sceneLock.type.unlock="unlock" +AdvSceneSwitcher.action.sceneLock.type.toggle="toggle lock of" +AdvSceneSwitcher.action.sceneLock.entry="On{{scenes}}{{actions}}{{sources}}" ; Transition Tab AdvSceneSwitcher.transitionTab.title="Transition" diff --git a/src/macro-core/macro-action-scene-lock.cpp b/src/macro-core/macro-action-scene-lock.cpp new file mode 100644 index 00000000..bda2416e --- /dev/null +++ b/src/macro-core/macro-action-scene-lock.cpp @@ -0,0 +1,175 @@ +#include "macro-action-scene-lock.hpp" +#include "utility.hpp" + +namespace advss { + +const std::string MacroActionSceneLock::id = "scene_lock"; + +bool MacroActionSceneLock::_registered = MacroActionFactory::Register( + MacroActionSceneLock::id, + {MacroActionSceneLock::Create, MacroActionSceneLockEdit::Create, + "AdvSceneSwitcher.action.sceneLock"}); + +const static std::map actionTypes = { + {MacroActionSceneLock::Action::LOCK, + "AdvSceneSwitcher.action.sceneLock.type.lock"}, + {MacroActionSceneLock::Action::UNLOCK, + "AdvSceneSwitcher.action.sceneLock.type.unlock"}, + {MacroActionSceneLock::Action::TOGGLE, + "AdvSceneSwitcher.action.sceneLock.type.toggle"}, +}; + +static void setSceneItemLock(obs_sceneitem_t *item, + MacroActionSceneLock::Action action) +{ + switch (action) { + case MacroActionSceneLock::Action::LOCK: + obs_sceneitem_set_locked(item, true); + break; + case MacroActionSceneLock::Action::UNLOCK: + obs_sceneitem_set_locked(item, false); + break; + case MacroActionSceneLock::Action::TOGGLE: + obs_sceneitem_set_locked(item, !obs_sceneitem_locked(item)); + break; + } +} + +bool MacroActionSceneLock::PerformAction() +{ + + auto items = _source.GetSceneItems(_scene); + for (auto item : items) { + setSceneItemLock(item, _action); + obs_sceneitem_release(item); + } + + return true; +} + +void MacroActionSceneLock::LogAction() const +{ + auto it = actionTypes.find(_action); + if (it != actionTypes.end()) { + vblog(LOG_INFO, + "performed action \"%s\" for source \"%s\" on scene \"%s\"", + it->second.c_str(), _source.ToString(true).c_str(), + _scene.ToString(true).c_str()); + + } else { + blog(LOG_WARNING, "ignored unknown scene lock action %d", + static_cast(_action)); + } +} + +bool MacroActionSceneLock::Save(obs_data_t *obj) const +{ + MacroAction::Save(obj); + _scene.Save(obj); + _source.Save(obj); + obs_data_set_int(obj, "action", static_cast(_action)); + return true; +} + +bool MacroActionSceneLock::Load(obs_data_t *obj) +{ + MacroAction::Load(obj); + _scene.Load(obj); + _source.Load(obj); + _action = static_cast(obs_data_get_int(obj, "action")); + return true; +} + +std::string MacroActionSceneLock::GetShortDesc() const +{ + if (!_source.ToString().empty()) { + return _scene.ToString() + " - " + _source.ToString(); + } + return ""; +} + +static inline void populateActionSelection(QComboBox *list) +{ + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); + } +} + +MacroActionSceneLockEdit::MacroActionSceneLockEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent), + _scenes(new SceneSelectionWidget(window(), true, false, true, true)), + _sources(new SceneItemSelectionWidget(parent)), + _actions(new QComboBox()) +{ + 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(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), + _sources, SLOT(SceneChanged(const SceneSelection &))); + QWidget::connect(_sources, + SIGNAL(SceneItemChanged(const SceneItemSelection &)), + this, SLOT(SourceChanged(const SceneItemSelection &))); + + auto layout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{scenes}}", _scenes}, + {"{{sources}}", _sources}, + {"{{actions}}", _actions}, + }; + PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.sceneLock.entry"), + layout, widgetPlaceholders); + setLayout(layout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroActionSceneLockEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _actions->setCurrentIndex(static_cast(_entryData->_action)); + _scenes->SetScene(_entryData->_scene); + _sources->SetSceneItem((_entryData->_source)); +} + +void MacroActionSceneLockEdit::SceneChanged(const SceneSelection &s) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_scene = s; +} + +void MacroActionSceneLockEdit::SourceChanged(const SceneItemSelection &item) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_source = item; + emit HeaderInfoChanged( + QString::fromStdString(_entryData->GetShortDesc())); +} + +void MacroActionSceneLockEdit::ActionChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_action = static_cast(value); +} + +} // namespace advss diff --git a/src/macro-core/macro-action-scene-lock.hpp b/src/macro-core/macro-action-scene-lock.hpp new file mode 100644 index 00000000..5b4ea22f --- /dev/null +++ b/src/macro-core/macro-action-scene-lock.hpp @@ -0,0 +1,69 @@ +#pragma once +#include "macro-action-edit.hpp" +#include "scene-selection.hpp" +#include "scene-item-selection.hpp" + +namespace advss { + +class MacroActionSceneLock : public MacroAction { +public: + MacroActionSceneLock(Macro *m) : MacroAction(m) {} + bool PerformAction(); + void LogAction() const; + bool Save(obs_data_t *obj) const; + bool Load(obs_data_t *obj); + std::string GetShortDesc() const; + std::string GetId() const { return id; }; + static std::shared_ptr Create(Macro *m) + { + return std::make_shared(m); + } + + enum class Action { + LOCK, + UNLOCK, + TOGGLE, + }; + Action _action = Action::LOCK; + SceneSelection _scene; + SceneItemSelection _source; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroActionSceneLockEdit : public QWidget { + Q_OBJECT + +public: + MacroActionSceneLockEdit( + QWidget *parent, + std::shared_ptr entryData = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr action) + { + return new MacroActionSceneLockEdit( + parent, std::dynamic_pointer_cast( + action)); + } + +private slots: + void SceneChanged(const SceneSelection &); + void SourceChanged(const SceneItemSelection &); + void ActionChanged(int value); +signals: + void HeaderInfoChanged(const QString &); + +protected: + SceneSelectionWidget *_scenes; + SceneItemSelectionWidget *_sources; + QComboBox *_actions; + std::shared_ptr _entryData; + +private: + bool _loading = true; +}; + +} // namespace advss