#pragma once #include "macro-action.hpp" #include "macro-condition.hpp" #include "macro-helpers.hpp" #include "macro-input.hpp" #include "macro-ref.hpp" #include "variable-string.hpp" #include "temp-variable.hpp" #include #include #include #include #include #include #include #include #include namespace advss { class MacroDock; class Macro { public: Macro(const std::string &name = "", const bool addHotkey = false); virtual ~Macro(); std::string Name() const { return _name; } void SetName(const std::string &name); bool CeckMatch(bool ignorePause = false); bool Matched() const { return _matched; } int64_t MsSinceLastCheck() const; bool ShouldRunActions() const; bool PerformActions(bool match, bool forceParallel = false, bool ignorePause = false); void SetPaused(bool pause = true); bool Paused() const { return _paused; } bool WasPausedSince( const std::chrono::high_resolution_clock::time_point &) const; void Stop(); bool GetStop() const { return _stop; } void ResetTimers(); void SetMatchOnChange(bool onChange); bool MatchOnChange() const { return _performActionsOnChange; } void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; } bool SkipExecOnStart() const { return _skipExecOnStart; } void SetStopActionsIfNotDone(bool stopActionsIfNotDone); bool StopActionsIfNotDone() const { return _stopActionsIfNotDone; } int RunCount() const { return _runCount; }; void ResetRunCount() { _runCount = 0; }; void AddHelperThread(std::thread &&); void SetRunInParallel(bool parallel) { _runInParallel = parallel; } bool RunInParallel() const { return _runInParallel; } // Input variables MacroInputVariables GetInputVariables() const; void SetInputVariables(const MacroInputVariables &); // Temporary variable helpers std::vector GetTempVars(MacroSegment *filter) const; std::optional GetTempVar(const MacroSegment *, const std::string &id) const; void InvalidateTempVarValues() const; // Macro segments std::deque> &Conditions(); std::deque> &Actions(); std::deque> &ElseActions(); void UpdateActionIndices(); void UpdateElseActionIndices(); void UpdateConditionIndices(); // Group controls static std::shared_ptr CreateGroup(const std::string &name, std::vector> &children); static void RemoveGroup(std::shared_ptr); static void PrepareMoveToGroup(Macro *group, std::shared_ptr item); static void PrepareMoveToGroup(std::shared_ptr group, std::shared_ptr item); bool IsGroup() const { return _isGroup; } uint32_t GroupSize() const { return _groupSize; } void ResetGroupSize() { _groupSize = 0; } bool IsSubitem() const { return !_parent.expired(); } void SetCollapsed(bool val) { _isCollapsed = val; } bool IsCollapsed() const { return _isCollapsed; } void SetParent(std::shared_ptr m) { _parent = m; } std::shared_ptr Parent() const; // Saving and loading bool Save(obs_data_t *obj) const; bool Load(obs_data_t *obj); // Some macros can refer to other macros, which are not yet loaded. // Use this function to set these references after loading is complete. bool PostLoad(); // Helper function for plugin state condition regarding scene change bool SwitchesScene() const; // UI helpers void SetActionConditionSplitterPosition(const QList); const QList &GetActionConditionSplitterPosition() const; void SetElseActionSplitterPosition(const QList); const QList &GetElseActionSplitterPosition() const; bool HasValidSplitterPositions() const; bool WasExecutedSince( const std::chrono::high_resolution_clock::time_point &) const; bool OnChangePreventedActionsRecently(); void ResetUIHelpers(); // Hotkeys void EnablePauseHotkeys(bool); bool PauseHotkeysEnabled() const; // Docks void EnableDock(bool); bool DockEnabled() const { return _registerDock; } void SetDockHasRunButton(bool value); bool DockHasRunButton() const { return _dockHasRunButton; } void SetDockHasPauseButton(bool value); bool DockHasPauseButton() const { return _dockHasPauseButton; } void SetDockHasStatusLabel(bool value); bool DockHasStatusLabel() const { return _dockHasStatusLabel; } void SetHighlightEnable(bool value); bool DockHighlightEnabled() const { return _dockHighlight; } StringVariable RunButtonText() const { return _runButtonText; } void SetRunButtonText(const std::string &text); StringVariable PauseButtonText() const { return _pauseButtonText; } void SetPauseButtonText(const std::string &text); StringVariable UnpauseButtonText() const { return _unpauseButtonText; } void SetUnpauseButtonText(const std::string &text); void SetConditionsTrueStatusText(const std::string &text); StringVariable ConditionsTrueStatusText() const; void SetConditionsFalseStatusText(const std::string &text); StringVariable ConditionsFalseStatusText() const; private: void SetupHotkeys(); void ClearHotkeys() const; void SetHotkeysDesc() const; bool RunActionsHelper( const std::deque> &actions, bool ignorePause); bool RunActions(bool ignorePause); bool RunElseActions(bool ignorePause); bool DockIsVisible() const; void SetDockWidgetName() const; void SaveDockSettings(obs_data_t *obj) const; void LoadDockSettings(obs_data_t *obj); void RemoveDock(); std::string _name = ""; bool _die = false; bool _stop = false; bool _done = true; std::chrono::high_resolution_clock::time_point _lastCheckTime{}; std::chrono::high_resolution_clock::time_point _lastUnpauseTime{}; std::chrono::high_resolution_clock::time_point _lastExecutionTime{}; std::thread _backgroundThread; std::vector _helperThreads; std::deque> _conditions; std::deque> _actions; std::deque> _elseActions; std::weak_ptr _parent; uint32_t _groupSize = 0; bool _isGroup = false; bool _isCollapsed = false; bool _runInParallel = false; bool _matched = false; bool _lastMatched = false; bool _conditionSateChanged = false; bool _performActionsOnChange = true; bool _skipExecOnStart = false; bool _stopActionsIfNotDone = false; bool _paused = false; int _runCount = 0; bool _registerHotkeys = true; obs_hotkey_id _pauseHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID; MacroInputVariables _inputVariables; // UI helpers bool _onPreventedActionExecution = false; QList _actionConditionSplitterPosition; QList _elseActionSplitterPosition; bool _registerDock = false; bool _dockHasRunButton = true; bool _dockHasPauseButton = true; bool _dockHasStatusLabel = false; bool _dockHighlight = false; StringVariable _runButtonText = obs_module_text("AdvSceneSwitcher.macroDock.run"); StringVariable _pauseButtonText = obs_module_text("AdvSceneSwitcher.macroDock.pause"); StringVariable _unpauseButtonText = obs_module_text("AdvSceneSwitcher.macroDock.unpause"); StringVariable _conditionsTrueStatusText = obs_module_text("AdvSceneSwitcher.macroDock.statusLabel.true"); StringVariable _conditionsFalseStatusText = obs_module_text("AdvSceneSwitcher.macroDock.statusLabel.false"); bool _dockIsFloating = true; bool _dockIsVisible = false; Qt::DockWidgetArea _dockArea; QByteArray _dockGeo; MacroDock *_dock = nullptr; QAction *_dockAction = nullptr; }; void LoadMacros(obs_data_t *obj); void SaveMacros(obs_data_t *obj); std::deque> &GetMacros(); bool CheckMacros(); bool RunMacros(); void StopAllMacros(); Macro *GetMacroByName(const char *name); Macro *GetMacroByQString(const QString &name); std::weak_ptr GetWeakMacroByName(const char *name); void InvalidateMacroTempVarValues(); } // namespace advss