diff --git a/CMakeLists.txt b/CMakeLists.txt index 1503cd96..2f993c9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,7 @@ set(advanced-scene-switcher_HEADERS src/headers/macro-action-recording.hpp src/headers/macro-action-replay-buffer.hpp src/headers/macro-action-run.hpp + src/headers/macro-action-scene-collection.hpp src/headers/macro-action-scene-order.hpp src/headers/macro-action-scene-swap.hpp src/headers/macro-action-scene-switch.hpp @@ -299,6 +300,7 @@ set(advanced-scene-switcher_SOURCES src/macro-action-recording.cpp src/macro-action-replay-buffer.cpp src/macro-action-run.cpp + src/macro-action-scene-collection.cpp src/macro-action-scene-order.cpp src/macro-action-scene-swap.cpp src/macro-action-scene-switch.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index a9fe3f66..708e3c5b 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -382,6 +382,9 @@ AdvSceneSwitcher.action.screenshot.mainOutput="OBS's main output" AdvSceneSwitcher.action.screenshot.entry="Screenshot {{sources}}" AdvSceneSwitcher.action.profile="Profile" AdvSceneSwitcher.action.profile.entry="Switch active profile to {{profiles}}" +AdvSceneSwitcher.action.sceneCollection="Scene collection" +AdvSceneSwitcher.action.sceneCollection.entry="Switch active scene collection to {{sceneCollections}}" +AdvSceneSwitcher.action.sceneCollection.warning="Note: Any actions following after this will not be executed as the changing scene collection will also reload the scene switcher settings.\nThe scene collection action will be ignored while the settings window is opened." ; Transition Tab AdvSceneSwitcher.transitionTab.title="Transition" @@ -652,6 +655,7 @@ AdvSceneSwitcher.selectFilter="--select filter--" AdvSceneSwitcher.selectMacro="--select macro--" AdvSceneSwitcher.selectItem="--select item--" AdvSceneSwitcher.selectProfile="--select profile--" +AdvSceneSwitcher.selectSceneCollection="--select scene collection--" AdvSceneSwitcher.enterPath="--enter path--" AdvSceneSwitcher.enterText="--enter text--" AdvSceneSwitcher.invaildEntriesWillNotBeSaved="invalid entries will not be saved" diff --git a/src/headers/macro-action-scene-collection.hpp b/src/headers/macro-action-scene-collection.hpp new file mode 100644 index 00000000..988011fe --- /dev/null +++ b/src/headers/macro-action-scene-collection.hpp @@ -0,0 +1,52 @@ +#pragma once +#include "macro-action-edit.hpp" + +class MacroActionSceneCollection : public MacroAction { +public: + bool PerformAction(); + void LogAction(); + 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(); + } + + std::string _sceneCollection; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroActionSceneCollectionEdit : public QWidget { + Q_OBJECT + +public: + MacroActionSceneCollectionEdit( + QWidget *parent, + std::shared_ptr entryData = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr action) + { + return new MacroActionSceneCollectionEdit( + parent, + std::dynamic_pointer_cast( + action)); + } + +private slots: + void SceneCollectionChanged(const QString &text); +signals: + void HeaderInfoChanged(const QString &); + +protected: + QComboBox *_sceneCollections; + std::shared_ptr _entryData; + +private: + bool _loading = true; +}; diff --git a/src/macro-action-scene-collection.cpp b/src/macro-action-scene-collection.cpp new file mode 100644 index 00000000..170e1eb9 --- /dev/null +++ b/src/macro-action-scene-collection.cpp @@ -0,0 +1,117 @@ +#include "headers/macro-action-scene-collection.hpp" +#include "headers/advanced-scene-switcher.hpp" +#include "headers/utility.hpp" + +const std::string MacroActionSceneCollection::id = "scene_collection"; + +bool MacroActionSceneCollection::_registered = MacroActionFactory::Register( + MacroActionSceneCollection::id, + {MacroActionSceneCollection::Create, + MacroActionSceneCollectionEdit::Create, + "AdvSceneSwitcher.action.sceneCollection"}); + +bool MacroActionSceneCollection::PerformAction() +{ + // Changing the scene collection will also reload the settings of the + // scene switcher, so to avoid issues of not being able to change + // settings ignore this action if the settings dialog is opened. + if (switcher->settingsWindowOpened) { + return false; + } + obs_frontend_set_current_scene_collection(_sceneCollection.c_str()); + // It does not make sense to continue as the current settings will be + // invalid after switching scene collection. + return false; +} + +void MacroActionSceneCollection::LogAction() +{ + vblog(LOG_INFO, "set scene collection type to \"%s\"", + _sceneCollection.c_str()); +} + +bool MacroActionSceneCollection::Save(obs_data_t *obj) +{ + MacroAction::Save(obj); + obs_data_set_string(obj, "sceneCollection", _sceneCollection.c_str()); + return true; +} + +bool MacroActionSceneCollection::Load(obs_data_t *obj) +{ + MacroAction::Load(obj); + _sceneCollection = obs_data_get_string(obj, "sceneCollection"); + return true; +} + +std::string MacroActionSceneCollection::GetShortDesc() +{ + return _sceneCollection; +} + +void populateSceneCollectionSelection(QComboBox *box) +{ + auto sceneCollections = obs_frontend_get_scene_collections(); + char **temp = sceneCollections; + while (*temp) { + const char *name = *temp; + box->addItem(name); + temp++; + } + bfree(sceneCollections); + box->model()->sort(0); + addSelectionEntry( + box, obs_module_text("AdvSceneSwitcher.selectSceneCollection"), + false); + box->setCurrentIndex(0); +} + +MacroActionSceneCollectionEdit::MacroActionSceneCollectionEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent) +{ + _sceneCollections = new QComboBox(); + populateSceneCollectionSelection(_sceneCollections); + QWidget::connect(_sceneCollections, + SIGNAL(currentTextChanged(const QString &)), this, + SLOT(SceneCollectionChanged(const QString &))); + + QHBoxLayout *entryLayout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{sceneCollections}}", _sceneCollections}, + }; + placeWidgets(obs_module_text( + "AdvSceneSwitcher.action.sceneCollection.entry"), + entryLayout, widgetPlaceholders); + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(entryLayout); + mainLayout->addWidget(new QLabel(obs_module_text( + "AdvSceneSwitcher.action.sceneCollection.warning"))); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroActionSceneCollectionEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _sceneCollections->setCurrentText( + QString::fromStdString(_entryData->_sceneCollection)); +} + +void MacroActionSceneCollectionEdit::SceneCollectionChanged(const QString &text) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_sceneCollection = text.toStdString(); + emit HeaderInfoChanged( + QString::fromStdString(_entryData->GetShortDesc())); +}