From 8b9f03a3495a1c1cfda5bdcd1f5292ea967fb892 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 16 Oct 2021 09:48:28 +0200 Subject: [PATCH] Add timer action This action can be used to control the state of the timers on macro conditions --- CMakeLists.txt | 2 + data/locale/en-US.ini | 6 + src/headers/macro-action-timer.hpp | 72 +++++++++ src/macro-action-timer.cpp | 228 +++++++++++++++++++++++++++++ 4 files changed, 308 insertions(+) create mode 100644 src/headers/macro-action-timer.hpp create mode 100644 src/macro-action-timer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 237807ba..fd884eb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,7 @@ set(advanced-scene-switcher_HEADERS src/headers/macro-action-scene-visibility.hpp src/headers/macro-action-source.hpp src/headers/macro-action-streaming.hpp + src/headers/macro-action-timer.hpp src/headers/macro-action-transition.hpp src/headers/macro-action-virtual-cam.hpp src/headers/macro-action-wait.hpp @@ -309,6 +310,7 @@ set(advanced-scene-switcher_SOURCES src/macro-action-scene-visibility.cpp src/macro-action-source.cpp src/macro-action-streaming.cpp + src/macro-action-timer.cpp src/macro-action-transition.cpp src/macro-action-virtual-cam.cpp src/macro-action-wait.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 5c2da909..43535daa 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -334,6 +334,12 @@ AdvSceneSwitcher.action.SceneSwap.entry="Swap preview and program scene in studi AdvSceneSwitcher.action.transition="Transition" AdvSceneSwitcher.action.transition.entry.line1="{{setType}}Set transition type to {{transitions}}" AdvSceneSwitcher.action.transition.entry.line2="{{setDuration}}Set transition duration to {{duration}}seconds" +AdvSceneSwitcher.action.timer="Timer" +AdvSceneSwitcher.action.timer.type.pause="Pause" +AdvSceneSwitcher.action.timer.type.continue="Continue" +AdvSceneSwitcher.action.timer.type.reset="Reset" +AdvSceneSwitcher.action.timer.type.setTimeRemaining="Set time remaining of" +AdvSceneSwitcher.action.timer.entry="{{timerAction}} timers on {{macros}} {{duration}}" ; Transition Tab AdvSceneSwitcher.transitionTab.title="Transition" diff --git a/src/headers/macro-action-timer.hpp b/src/headers/macro-action-timer.hpp new file mode 100644 index 00000000..e45b2e62 --- /dev/null +++ b/src/headers/macro-action-timer.hpp @@ -0,0 +1,72 @@ +#pragma once +#include "macro-action-edit.hpp" +#include "duration-control.hpp" +#include "macro-selection.hpp" + +#include +#include + +enum class TimerAction { + PAUSE, + CONTINUE, + RESET, + SET_TIME_REMAINING, +}; + +class MacroActionTimer : public MacroRefAction { +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(); + } + Duration _duration; + TimerAction _actionType = TimerAction::PAUSE; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroActionTimerEdit : public QWidget { + Q_OBJECT + +public: + MacroActionTimerEdit( + QWidget *parent, + std::shared_ptr entryData = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr action) + { + return new MacroActionTimerEdit( + parent, + std::dynamic_pointer_cast(action)); + } + +private slots: + void MacroChanged(const QString &text); + void MacroRemove(const QString &name); + void DurationChanged(double value); + void DurationUnitChanged(DurationUnit unit); + void ActionTypeChanged(int value); +signals: + void HeaderInfoChanged(const QString &); + +protected: + void SetWidgetVisibility(); + + MacroSelection *_macros; + DurationSelection *_duration; + QComboBox *_timerAction; + std::shared_ptr _entryData; + +private: + QHBoxLayout *_mainLayout; + bool _loading = true; +}; diff --git a/src/macro-action-timer.cpp b/src/macro-action-timer.cpp new file mode 100644 index 00000000..8de6cb23 --- /dev/null +++ b/src/macro-action-timer.cpp @@ -0,0 +1,228 @@ +#include "headers/macro-action-timer.hpp" +#include "headers/macro-condition-timer.hpp" +#include "headers/advanced-scene-switcher.hpp" +#include "headers/utility.hpp" + +#include + +const std::string MacroActionTimer::id = "timer"; + +bool MacroActionTimer::_registered = MacroActionFactory::Register( + MacroActionTimer::id, + {MacroActionTimer::Create, MacroActionTimerEdit::Create, + "AdvSceneSwitcher.action.Timer"}); + +static std::map timerActions = { + {TimerAction::PAUSE, "AdvSceneSwitcher.action.timer.type.pause"}, + {TimerAction::CONTINUE, "AdvSceneSwitcher.action.timer.type.continue"}, + {TimerAction::RESET, "AdvSceneSwitcher.action.timer.type.reset"}, + {TimerAction::SET_TIME_REMAINING, + "AdvSceneSwitcher.action.timer.type.setTimeRemaining"}, +}; + +bool MacroActionTimer::PerformAction() +{ + if (!_macro.get()) { + return true; + } + for (auto c : _macro->Conditions()) { + if (c->GetId() != "timer") { + continue; + } + auto timerCondition = + dynamic_cast(c.get()); + if (!timerCondition) { + continue; + } + + switch (_actionType) { + case TimerAction::PAUSE: + timerCondition->Pause(); + break; + case TimerAction::CONTINUE: + timerCondition->Continue(); + break; + case TimerAction::RESET: + timerCondition->Reset(); + break; + case TimerAction::SET_TIME_REMAINING: + timerCondition->_duration.SetTimeRemaining( + _duration.seconds); + break; + default: + break; + } + } + return true; +} + +void MacroActionTimer::LogAction() +{ + if (!_macro.get()) { + return; + } + switch (_actionType) { + case TimerAction::PAUSE: + vblog(LOG_INFO, "paused timers on \"%s\"", + _macro->Name().c_str()); + break; + case TimerAction::CONTINUE: + vblog(LOG_INFO, "continued timers on \"%s\"", + _macro->Name().c_str()); + break; + case TimerAction::RESET: + vblog(LOG_INFO, "reset timers on \"%s\"", + _macro->Name().c_str()); + break; + case TimerAction::SET_TIME_REMAINING: + vblog(LOG_INFO, + "set time remaining of timers on \"%s\" to \"%s\"", + _macro->Name().c_str(), _duration.ToString().c_str()); + break; + default: + break; + } +} + +bool MacroActionTimer::Save(obs_data_t *obj) +{ + MacroAction::Save(obj); + _macro.Save(obj); + _duration.Save(obj); + obs_data_set_int(obj, "actionType", static_cast(_actionType)); + return true; +} + +bool MacroActionTimer::Load(obs_data_t *obj) +{ + MacroAction::Load(obj); + _macro.Load(obj); + _duration.Load(obj); + _actionType = + static_cast(obs_data_get_int(obj, "actionType")); + return true; +} + +std::string MacroActionTimer::GetShortDesc() +{ + if (_macro.get()) { + return _macro->Name(); + } + return ""; +} + +static inline void populateTypeSelection(QComboBox *list) +{ + for (auto entry : timerActions) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + +MacroActionTimerEdit::MacroActionTimerEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent) +{ + _macros = new MacroSelection(parent); + _duration = new DurationSelection(); + _timerAction = new QComboBox(); + + populateTypeSelection(_timerAction); + + QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)), + this, SLOT(MacroChanged(const QString &))); + QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this, + SLOT(MacroRemove(const QString &))); + QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this, + SLOT(DurationChanged(double))); + QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this, + SLOT(DurationUnitChanged(DurationUnit))); + QWidget::connect(_timerAction, SIGNAL(currentIndexChanged(int)), this, + SLOT(ActionTypeChanged(int))); + + _mainLayout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{macros}}", _macros}, + {"{{duration}}", _duration}, + {"{{timerAction}}", _timerAction}, + }; + placeWidgets(obs_module_text("AdvSceneSwitcher.action.timer.entry"), + _mainLayout, widgetPlaceholders); + setLayout(_mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroActionTimerEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _macros->SetCurrentMacro(_entryData->_macro.get()); + _duration->SetDuration(_entryData->_duration); + _timerAction->setCurrentIndex( + static_cast(_entryData->_actionType)); + SetWidgetVisibility(); +} + +void MacroActionTimerEdit::ActionTypeChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_actionType = static_cast(value); + SetWidgetVisibility(); +} + +void MacroActionTimerEdit::SetWidgetVisibility() +{ + if (!_entryData) { + return; + } + _duration->setVisible(_entryData->_actionType == + TimerAction::SET_TIME_REMAINING); + adjustSize(); +} + +void MacroActionTimerEdit::DurationChanged(double seconds) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_duration.seconds = seconds; +} + +void MacroActionTimerEdit::DurationUnitChanged(DurationUnit unit) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_duration.displayUnit = unit; +} + +void MacroActionTimerEdit::MacroChanged(const QString &text) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_macro.UpdateRef(text); + emit HeaderInfoChanged( + QString::fromStdString(_entryData->GetShortDesc())); +} + +void MacroActionTimerEdit::MacroRemove(const QString &) +{ + if (_entryData) { + _entryData->_macro.UpdateRef(); + } +}