From 9a3d381cf0fb9c7ec735a4d5bf8af75971e66ae1 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 9 Oct 2022 00:40:58 +0200 Subject: [PATCH] Improve macro examples --- BUILDING.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 4 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 5ab95a3b..e3ae16bd 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -15,7 +15,7 @@ cd obs-studio/UI/frontend-plugins/ git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git ``` -Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher: +Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt Example and add an entry for the scene switcher: ``` add_subdirectory(SceneSwitcher) ``` @@ -66,11 +66,123 @@ Finally, start the plugin build using your provided generator. (E.g. Ninja on Li Contributions to the plugin are always welcome and if you need any assistance do not hesitate to reach out. +If you would like to expand upon the macro system by adding a new condition or action type have a loot at the examples in `src/macro-core`. In general changes in the `src/legacy` folder should be avoided. -If you would like to expand upon the macro system by adding a new condition or action type have a loot at the examples in `src/macro-core`. -The key functions to add conditions or are the Register() functions. +## Macro condition +Macro conditions should inherit from the `MacroCondition` class and must implement the following functions: +``` +class MacroConditionExample : public MacroCondition { +public: + MacroConditionExample(Macro *m) : MacroCondition(m) {} + // This function should perfrom the condition check + bool CheckCondition(); + // This function should store the required condition data to "obj" + // For example called on OBS shutdown + bool Save(obs_data_t *obj); + // This function should load the condition data from "obj" + // For example called on OBS startup + bool Load(obs_data_t *obj); + // This function should return a unique id for this condition type + // The _id is defined below + std::string GetId() { return _id; }; + // Helper function called when new conditions are created + // Will be used later when regeistering the new condition type + static std::shared_ptr Create(Macro *m) + { + return std::make_shared(m); + } + +private: + // Used to register new condition type + static bool _registered; + // Unique id identifying this condition type + static const std::string _id; +}; +``` +When defining the widget used to control the settings of the condition type, it is important to add a static `Create()` method. +It will be called whenever a new condition MacroConditionExample is created. (See `MacroConditionFactory::Register()`) +``` +class MacroConditionExampleEdit : public QWidget { + Q_OBJECT + +public: + // ... + MacroConditionExampleEdit( + QWidget *parent, + std::shared_ptr cond = nullptr); + + // Function will be used to create the widget for editing the settings of the condition + static QWidget *Create(QWidget *parent, + std::shared_ptr cond) + { + return new MacroConditionExampleEdit( + parent, + std::dynamic_pointer_cast(cond)); + } + // ... +}; +``` + +To finally register the new condition type you will have to add the following call to `MacroConditionFactory::Register()`. + +``` +bool MacroConditionExample::_registered = MacroConditionFactory::Register( + MacroConditionExample::id, // Unique string identifying this condition type + { + MacroConditionExample::Create, // Function called to create the object performing the condition + MacroConditionExampleEdit::Create, // Function called to create the widget configure the condition + "AdvSceneSwitcher.condition.example", // User facing name of the condition type (will be translated) + true // Condition type supports duration modifiers (default true) + } +); +``` + +## Macro action + +The process of adding a new action type is very similar to adding a new condition. +The differences are highlighted in the comments below. + +``` +class MacroActionExample : public MacroAction { +public: + MacroActionExample(Macro *m) : MacroAction(m) {} + // This function should perfrom the action + // If false is returned the macro will aborted + bool PerformAction(); + bool Save(obs_data_t *obj); + bool Load(obs_data_t *obj); + std::string GetId() { return _id; }; + static std::shared_ptr Create(Macro *m) + { + return std::make_shared(m); + } + +private: + static bool _registered; + static const std::string _id; +}; +``` +``` +class MacroActionExampleEdit : public QWidget { + Q_OBJECT + +public: + // ... + MacroActionExampleEdit( + QWidget *parent, + std::shared_ptr entryData = nullptr); + static QWidget *Create(QWidget *parent, + std::shared_ptr action) + { + return new MacroActionExampleEdit( + parent, + std::dynamic_pointer_cast(action)); + } + // ... +}; +``` ``` MacroActionFactory::Register( MacroActionExample::id, // Unique string identifying this action type @@ -81,6 +193,6 @@ MacroActionFactory::Register( } ); ``` - +## External dependencies If your intention is to add macro functionality which depends on external libraries, which is likely not to exist on all user setups, try to follow the examples under `src/macro-external`. These are basically plugins themselves that get attempted to be loaded on startup of the advanced scene switcher.