From f9730b1bc24701a96efd9b6ab550a24803175905 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 3 Aug 2024 18:31:57 +0200 Subject: [PATCH] Refactor DurationModifier to enable testing --- CMakeLists.txt | 2 + lib/macro/macro-condition-edit.hpp | 1 + lib/macro/macro-condition.cpp | 119 ++++------------------------- lib/macro/macro-condition.hpp | 43 +++-------- lib/macro/macro.cpp | 3 +- lib/utils/duration-modifier.cpp | 110 ++++++++++++++++++++++++++ lib/utils/duration-modifier.hpp | 31 ++++++++ lib/utils/duration.cpp | 2 +- 8 files changed, 169 insertions(+), 142 deletions(-) create mode 100644 lib/utils/duration-modifier.cpp create mode 100644 lib/utils/duration-modifier.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fb3d989d..dd7d2ddc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,6 +165,8 @@ target_sources( lib/utils/double-slider.hpp lib/utils/duration-control.cpp lib/utils/duration-control.hpp + lib/utils/duration-modifier.cpp + lib/utils/duration-modifier.hpp lib/utils/duration.cpp lib/utils/duration.hpp lib/utils/export-symbol-helper.hpp diff --git a/lib/macro/macro-condition-edit.hpp b/lib/macro/macro-condition-edit.hpp index e1adfb69..b4700484 100644 --- a/lib/macro/macro-condition-edit.hpp +++ b/lib/macro/macro-condition-edit.hpp @@ -2,6 +2,7 @@ #include "macro-condition.hpp" #include "macro-condition-factory.hpp" #include "filter-combo-box.hpp" +#include "duration-control.hpp" #include diff --git a/lib/macro/macro-condition.cpp b/lib/macro/macro-condition.cpp index cf9c2cdc..bd9a58a0 100644 --- a/lib/macro/macro-condition.cpp +++ b/lib/macro/macro-condition.cpp @@ -2,69 +2,6 @@ namespace advss { -void DurationModifier::Save(obs_data_t *obj, const char *condName, - const char *duration) const -{ - obs_data_set_int(obj, condName, static_cast(_type)); - _dur.Save(obj, duration); -} - -void DurationModifier::Load(obs_data_t *obj, const char *condName, - const char *duration) -{ - // For backwards compatibility check if duration value exist without - // time constraint condition - if so assume DurationCondition::MORE - if (!obs_data_has_user_value(obj, condName) && - obs_data_has_user_value(obj, duration)) { - obs_data_set_int(obj, condName, static_cast(Type::MORE)); - } - - _type = static_cast(obs_data_get_int(obj, condName)); - _dur.Load(obj, duration); - - // TODO: remove this fallback - if (obs_data_has_user_value(obj, "displayUnit")) { - _dur.SetUnit(static_cast( - obs_data_get_int(obj, "displayUnit"))); - } -} - -bool DurationModifier::DurationReached() -{ - switch (_type) { - case DurationModifier::Type::NONE: - return true; - break; - case DurationModifier::Type::MORE: - return _dur.DurationReached(); - break; - case DurationModifier::Type::EQUAL: - if (_dur.DurationReached() && !_timeReached) { - _timeReached = true; - return true; - } - break; - case DurationModifier::Type::LESS: - return !_dur.DurationReached(); - break; - case DurationModifier::Type::WITHIN: - if (_dur.IsReset()) { - return false; - } - return !_dur.DurationReached(); - break; - default: - break; - } - return false; -} - -void DurationModifier::Reset() -{ - _timeReached = false; - _dur.Reset(); -} - MacroCondition::MacroCondition(Macro *m, bool supportsVariableValue) : MacroSegment(m, supportsVariableValue) { @@ -75,14 +12,7 @@ bool MacroCondition::Save(obs_data_t *obj) const MacroSegment::Save(obj); obs_data_set_string(obj, "id", GetId().c_str()); _logic.Save(obj, "logic"); - - // To avoid conflicts with conditions which also use the Duration class - // save the duration modifier in a separate obj - auto durObj = obs_data_create(); - _duration.Save(durObj); - obs_data_set_obj(obj, "durationModifier", durObj); - obs_data_release(durObj); - + _durationModifier.Save(obj); return true; } @@ -90,14 +20,7 @@ bool MacroCondition::Load(obs_data_t *obj) { MacroSegment::Load(obj); _logic.Load(obj, "logic"); - if (obs_data_has_user_value(obj, "durationModifier")) { - auto durObj = obs_data_get_obj(obj, "durationModifier"); - _duration.Load(durObj); - obs_data_release(durObj); - } else { - // For backwards compatibility - _duration.Load(obj); - } + _durationModifier.Load(obj); return true; } @@ -124,44 +47,28 @@ void MacroCondition::ValidateLogicSelection(bool isRootCondition, void MacroCondition::ResetDuration() { - _duration.Reset(); + _durationModifier.ResetDuration(); } -void MacroCondition::CheckDurationModifier(bool &val) +bool MacroCondition::CheckDurationModifier(bool conditionValue) { - if (_duration.GetType() != DurationModifier::Type::WITHIN && !val) { - _duration.Reset(); - } - if (_duration.GetType() == DurationModifier::Type::WITHIN && val) { - _duration.Reset(); - } - switch (_duration.GetType()) { - case DurationModifier::Type::NONE: - case DurationModifier::Type::MORE: - case DurationModifier::Type::EQUAL: - case DurationModifier::Type::LESS: - val = val && _duration.DurationReached(); - return; - case DurationModifier::Type::WITHIN: - if (val) { - _duration.SetTimeRemaining( - _duration.GetDuration().Seconds()); - } - val = val || _duration.DurationReached(); - break; - default: - break; - } + return _durationModifier.CheckConditionWithDurationModifier( + conditionValue); +} + +DurationModifier MacroCondition::GetDurationModifier() const +{ + return _durationModifier; } void MacroCondition::SetDurationModifier(DurationModifier::Type m) { - _duration.SetModifier(m); + _durationModifier.SetModifier(m); } void MacroCondition::SetDuration(const Duration &duration) { - _duration.SetValue(duration); + _durationModifier.SetDuration(duration); } std::string_view MacroCondition::GetDefaultID() diff --git a/lib/macro/macro-condition.hpp b/lib/macro/macro-condition.hpp index 9f5694a1..8cac06b3 100644 --- a/lib/macro/macro-condition.hpp +++ b/lib/macro/macro-condition.hpp @@ -1,40 +1,11 @@ #pragma once #include "macro-segment.hpp" #include "condition-logic.hpp" -#include "duration-control.hpp" +#include "duration-modifier.hpp" #include "macro-ref.hpp" namespace advss { -class DurationModifier { -public: - enum class Type { - NONE, - MORE, - EQUAL, - LESS, - WITHIN, // Condition will remain true for a set a amount of time - // regardless of current state - }; - - void Save(obs_data_t *obj, const char *condName = "time_constraint", - const char *duration = "seconds") const; - void Load(obs_data_t *obj, const char *condName = "time_constraint", - const char *duration = "seconds"); - void SetModifier(Type cond) { _type = cond; } - void SetTimeRemaining(const double &val) { _dur.SetTimeRemaining(val); } - void SetValue(const Duration &value) { _dur = value; } - Type GetType() { return _type; } - Duration GetDuration() { return _dur; } - bool DurationReached(); - void Reset(); - -private: - Type _type = Type::NONE; - Duration _dur; - bool _timeReached = false; -}; - class EXPORT MacroCondition : public MacroSegment { public: MacroCondition(Macro *m, bool supportsVariableValue = false); @@ -42,20 +13,24 @@ public: virtual bool CheckCondition() = 0; virtual bool Save(obs_data_t *obj) const = 0; virtual bool Load(obs_data_t *obj) = 0; + Logic::Type GetLogicType() const { return _logic.GetType(); } void SetLogicType(const Logic::Type &logic) { _logic.SetType(logic); } + void ValidateLogicSelection(bool isRootCondition, const char *context); - void ResetDuration(); - void CheckDurationModifier(bool &val); - DurationModifier GetDurationModifier() { return _duration; } + + DurationModifier GetDurationModifier() const; void SetDurationModifier(DurationModifier::Type m); void SetDuration(const Duration &duration); + void ResetDuration(); + bool CheckDurationModifier(bool conditionValue); + static std::string_view GetDefaultID(); private: Logic _logic = Logic(Logic::Type::ROOT_NONE); - DurationModifier _duration; + DurationModifier _durationModifier; }; class EXPORT MacroRefCondition : virtual public MacroCondition { diff --git a/lib/macro/macro.cpp b/lib/macro/macro.cpp index cb81ea45..ecbe3451 100644 --- a/lib/macro/macro.cpp +++ b/lib/macro/macro.cpp @@ -138,7 +138,8 @@ bool Macro::CeckMatch(bool ignorePause) } bool conditionMatched = checkCondition(condition); - condition->CheckDurationModifier(conditionMatched); + conditionMatched = + condition->CheckDurationModifier(conditionMatched); const auto logicType = condition->GetLogicType(); if (logicType == Logic::Type::NONE) { diff --git a/lib/utils/duration-modifier.cpp b/lib/utils/duration-modifier.cpp new file mode 100644 index 00000000..a38b069e --- /dev/null +++ b/lib/utils/duration-modifier.cpp @@ -0,0 +1,110 @@ +#include "duration-modifier.hpp" + +namespace advss { + +void DurationModifier::Save(obs_data_t *obj, const char *name, + const char *duration) const +{ + auto data = obs_data_create(); + obs_data_set_int(data, name, static_cast(_type)); + _duration.Save(data, duration); + obs_data_set_obj(obj, "durationModifier", data); + obs_data_release(data); +} + +void DurationModifier::Load(obs_data_t *obj, const char *name, + const char *duration) +{ + obs_data_t *data = nullptr; + if (obs_data_has_user_value(obj, "durationModifier")) { + data = obs_data_get_obj(obj, "durationModifier"); + } else { + // For backwards compatibility + obs_data_addref(obj); + data = obj; + } + + // For backwards compatibility check if duration value exist without + // time constraint condition - if so assume DurationCondition::MORE + if (!obs_data_has_user_value(data, name) && + obs_data_has_user_value(data, duration)) { + obs_data_set_int(data, name, static_cast(Type::MORE)); + } + + _type = static_cast(obs_data_get_int(data, name)); + _duration.Load(data, duration); + + // TODO: remove this fallback + if (obs_data_has_user_value(data, "displayUnit")) { + _duration.SetUnit(static_cast( + obs_data_get_int(data, "displayUnit"))); + } + + obs_data_release(data); +} + +void DurationModifier::SetTimeRemaining(double seconds) +{ + _duration.SetTimeRemaining(seconds); +} + +bool DurationModifier::DurationReached() +{ + switch (_type) { + case DurationModifier::Type::NONE: + return true; + case DurationModifier::Type::MORE: + return _duration.DurationReached(); + case DurationModifier::Type::EQUAL: + if (_duration.DurationReached() && !_durationWasReached) { + _durationWasReached = true; + return true; + } + break; + case DurationModifier::Type::LESS: + return !_duration.DurationReached(); + case DurationModifier::Type::WITHIN: + if (_duration.IsReset()) { + return false; + } + return !_duration.DurationReached(); + default: + break; + } + return false; +} + +void DurationModifier::ResetDuration() +{ + _durationWasReached = false; + _duration.Reset(); +} + +bool DurationModifier::CheckConditionWithDurationModifier(bool conditionValue) +{ + if (_type != DurationModifier::Type::WITHIN && !conditionValue) { + ResetDuration(); + } + if (_type == DurationModifier::Type::WITHIN && conditionValue) { + ResetDuration(); + } + + switch (_type) { + case DurationModifier::Type::NONE: + case DurationModifier::Type::MORE: + case DurationModifier::Type::EQUAL: + case DurationModifier::Type::LESS: + return conditionValue && DurationReached(); + case DurationModifier::Type::WITHIN: + if (conditionValue) { + SetTimeRemaining(_duration.Seconds()); + } + return conditionValue || DurationReached(); + default: + break; + } + + return conditionValue; +} + +} // namespace advss diff --git a/lib/utils/duration-modifier.hpp b/lib/utils/duration-modifier.hpp new file mode 100644 index 00000000..bf81f1fe --- /dev/null +++ b/lib/utils/duration-modifier.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "duration.hpp" + +namespace advss { + +class DurationModifier { +public: + enum class Type { NONE, MORE, EQUAL, LESS, WITHIN }; + + void Save(obs_data_t *obj, const char *name = "time_constraint", + const char *duration = "seconds") const; + void Load(obs_data_t *obj, const char *name = "time_constraint", + const char *duration = "seconds"); + void SetModifier(Type type) { _type = type; } + void SetDuration(const Duration &duration) { _duration = duration; } + Type GetType() const { return _type; } + Duration GetDuration() const { return _duration; } + void ResetDuration(); + + bool CheckConditionWithDurationModifier(bool conditionValue); + +private: + void SetTimeRemaining(double seconds); + bool DurationReached(); + + Type _type = Type::NONE; + Duration _duration; + bool _durationWasReached = false; +}; + +} // namespace advss diff --git a/lib/utils/duration.cpp b/lib/utils/duration.cpp index 11fde9d0..73ae35a5 100644 --- a/lib/utils/duration.cpp +++ b/lib/utils/duration.cpp @@ -101,7 +101,7 @@ double Duration::TimeRemaining() const void Duration::SetTimeRemaining(double remaining) { - long long msPassed = (Seconds() - remaining) * 1000; + long long msPassed = (long long)((Seconds() - remaining) * 1000); _startTime = std::chrono::high_resolution_clock::now() - std::chrono::milliseconds(msPassed); }