diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 8136545e..91b2e349 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -129,7 +129,7 @@ AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDat AdvSceneSwitcher.condition.media="Media" AdvSceneSwitcher.condition.media.anyOnScene="Any media source on" AdvSceneSwitcher.condition.media.allOnScene="All media sources on" -AdvSceneSwitcher.condition.media.matchOnChange="Only match on change (Note: This option will be removed in a future version - please use time constraints instead)" +AdvSceneSwitcher.condition.media.matchOnChange="Only match on change (Note: This option will be removed in a future version - please use duration modifiers instead)" AdvSceneSwitcher.condition.media.inconsistencyInfo="Unfortunately not all media source types behave the same (e.g. Media Source vs. VLC Video Source \"Stopped\" state).\nSo please experiment what works for your setup!" AdvSceneSwitcher.condition.media.entry="{{mediaSources}}{{scenes}} state is {{states}} and {{timeRestrictions}} {{time}}" AdvSceneSwitcher.condition.video="Video" @@ -763,7 +763,8 @@ AdvSceneSwitcher.unit.milliseconds="milliseconds" AdvSceneSwitcher.unit.secends="seconds" AdvSceneSwitcher.unit.minutes="minutes" AdvSceneSwitcher.unit.hours="hours" -AdvSceneSwitcher.duration.condition.none="No time constraint" +AdvSceneSwitcher.duration.condition.none="No duration modifier" AdvSceneSwitcher.duration.condition.more="For at least" AdvSceneSwitcher.duration.condition.equal="For exactly" AdvSceneSwitcher.duration.condition.less="For at most" +AdvSceneSwitcher.duration.condition.within="Within the last" diff --git a/src/duration-control.cpp b/src/duration-control.cpp index d61b2cf3..ad69f3ca 100644 --- a/src/duration-control.cpp +++ b/src/duration-control.cpp @@ -23,7 +23,7 @@ void Duration::Load(obs_data_t *obj, const char *secondsName, bool Duration::DurationReached() { - if (_startTime.time_since_epoch().count() == 0) { + if (IsReset()) { _startTime = std::chrono::high_resolution_clock::now(); } @@ -32,9 +32,14 @@ bool Duration::DurationReached() return runTime.count() >= seconds * 1000; } +bool Duration::IsReset() +{ + return _startTime.time_since_epoch().count() == 0; +} + double Duration::TimeRemaining() { - if (_startTime.time_since_epoch().count() == 0) { + if (IsReset()) { return seconds; } auto runTime = std::chrono::duration_cast( diff --git a/src/headers/duration-control.hpp b/src/headers/duration-control.hpp index 87cf061e..9a6d8fad 100644 --- a/src/headers/duration-control.hpp +++ b/src/headers/duration-control.hpp @@ -21,6 +21,7 @@ public: const char *unitName = "displayUnit"); bool DurationReached(); + bool IsReset(); double TimeRemaining(); void SetTimeRemaining(double); void Reset(); diff --git a/src/headers/macro-condition-edit.hpp b/src/headers/macro-condition-edit.hpp index 12a43889..504e31b3 100644 --- a/src/headers/macro-condition-edit.hpp +++ b/src/headers/macro-condition-edit.hpp @@ -10,7 +10,7 @@ struct MacroConditionInfo { TCreateMethod _createFunc = nullptr; TCreateWidgetMethod _createWidgetFunc = nullptr; std::string _name; - bool _useDurationConstraint = true; + bool _useDurationModifier = true; }; class MacroConditionFactory { @@ -24,27 +24,27 @@ public: static auto GetConditionTypes() { return _methods; } static std::string GetConditionName(const std::string &); static std::string GetIdByName(const QString &name); - static bool UsesDurationConstraint(const std::string &id); + static bool UsesDurationModifier(const std::string &id); private: static std::map _methods; }; -class DurationConstraintEdit : public QWidget { +class DurationModifierEdit : public QWidget { Q_OBJECT public: - DurationConstraintEdit(QWidget *parent = nullptr); - void SetValue(DurationConstraint &value); + DurationModifierEdit(QWidget *parent = nullptr); + void SetValue(DurationModifier &value); void SetUnit(DurationUnit u); void SetDuration(const Duration &d); private slots: - void _ConditionChanged(int value); + void _ModifierChanged(int value); void ToggleClicked(); signals: void DurationChanged(double value); void UnitChanged(DurationUnit u); - void ConditionChanged(DurationCondition value); + void ModifierChanged(DurationModifier::Type value); private: void Collapse(bool collapse); @@ -70,7 +70,7 @@ private slots: void LogicSelectionChanged(int idx); void ConditionSelectionChanged(const QString &text); void DurationChanged(double seconds); - void DurationConditionChanged(DurationCondition cond); + void DurationModifierChanged(DurationModifier::Type m); void DurationUnitChanged(DurationUnit unit); private: @@ -79,7 +79,7 @@ private: QComboBox *_logicSelection; QComboBox *_conditionSelection; - DurationConstraintEdit *_dur; + DurationModifierEdit *_dur; std::shared_ptr *_entryData; bool _isRoot = true; diff --git a/src/headers/macro-condition.hpp b/src/headers/macro-condition.hpp index 3a968890..db503956 100644 --- a/src/headers/macro-condition.hpp +++ b/src/headers/macro-condition.hpp @@ -27,32 +27,34 @@ struct LogicTypeInfo { std::string _name; }; -enum class DurationCondition { - NONE, - MORE, - EQUAL, - LESS, -}; - -class DurationConstraint { +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 *secondsName = "seconds", const char *unitName = "displayUnit"); void Load(obs_data_t *obj, const char *condName = "time_constraint", const char *secondsName = "seconds", const char *unitName = "displayUnit"); - void SetCondition(DurationCondition cond) { _type = cond; } - void SetDuration(const Duration &dur) { _dur = dur; } + void SetModifier(Type cond) { _type = cond; } + void SetTimeRemaining(const double &val) { _dur.SetTimeRemaining(val); } void SetValue(double value) { _dur.seconds = value; } void SetUnit(DurationUnit u) { _dur.displayUnit = u; } - DurationCondition GetCondition() { return _type; } + Type GetType() { return _type; } Duration GetDuration() { return _dur; } bool DurationReached(); void Reset(); private: - DurationCondition _type = DurationCondition::NONE; + Type _type = Type::NONE; Duration _dur; bool _timeReached = false; }; @@ -66,18 +68,16 @@ public: LogicType GetLogicType() { return _logic; } void SetLogicType(LogicType logic) { _logic = logic; } static const std::map logicTypes; - - bool DurationReached() { return _duration.DurationReached(); } - void ResetDuration() { _duration.Reset(); } - DurationConstraint GetDurationConstraint() { return _duration; } - void SetDurationConstraint(const DurationConstraint &dur); - void SetDurationCondition(DurationCondition cond); + void ResetDuration(); + void CheckDurationModifier(bool &val); + DurationModifier GetDurationModifier() { return _duration; } + void SetDurationModifier(DurationModifier::Type m); void SetDurationUnit(DurationUnit u); void SetDuration(double seconds); private: LogicType _logic = LogicType::ROOT_NONE; - DurationConstraint _duration; + DurationModifier _duration; }; class MacroRefCondition : public MacroCondition { diff --git a/src/macro-condition-edit.cpp b/src/macro-condition-edit.cpp index fad386ec..10aed481 100644 --- a/src/macro-condition-edit.cpp +++ b/src/macro-condition-edit.cpp @@ -53,10 +53,10 @@ std::string MacroConditionFactory::GetIdByName(const QString &name) return ""; } -bool MacroConditionFactory::UsesDurationConstraint(const std::string &id) +bool MacroConditionFactory::UsesDurationModifier(const std::string &id) { if (auto it = _methods.find(id); it != _methods.end()) { - return it->second._useDurationConstraint; + return it->second._useDurationModifier; } return false; } @@ -97,7 +97,7 @@ static inline void populateConditionSelection(QComboBox *list) list->model()->sort(0); } -static void populateDurationConstraintTypes(QComboBox *list) +static void populateDurationModifierTypes(QComboBox *list) { list->addItem( obs_module_text("AdvSceneSwitcher.duration.condition.none")); @@ -107,9 +107,11 @@ static void populateDurationConstraintTypes(QComboBox *list) obs_module_text("AdvSceneSwitcher.duration.condition.equal")); list->addItem( obs_module_text("AdvSceneSwitcher.duration.condition.less")); + list->addItem( + obs_module_text("AdvSceneSwitcher.duration.condition.within")); } -DurationConstraintEdit::DurationConstraintEdit(QWidget *parent) +DurationModifierEdit::DurationModifierEdit(QWidget *parent) { _condition = new QComboBox(parent); _duration = new DurationSelection(parent); @@ -117,13 +119,13 @@ DurationConstraintEdit::DurationConstraintEdit(QWidget *parent) _toggle->setMaximumSize(22, 22); _toggle->setIcon( QIcon(QString::fromStdString(getDataFilePath("res/time.svg")))); - populateDurationConstraintTypes(_condition); + populateDurationModifierTypes(_condition); QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this, - SLOT(_ConditionChanged(int))); + SLOT(_ModifierChanged(int))); QObject::connect(_duration, &DurationSelection::DurationChanged, this, - &DurationConstraintEdit::DurationChanged); + &DurationModifierEdit::DurationChanged); QObject::connect(_duration, &DurationSelection::UnitChanged, this, - &DurationConstraintEdit::UnitChanged); + &DurationModifierEdit::UnitChanged); QWidget::connect(_toggle, SIGNAL(clicked()), this, SLOT(ToggleClicked())); @@ -137,36 +139,36 @@ DurationConstraintEdit::DurationConstraintEdit(QWidget *parent) Collapse(true); } -void DurationConstraintEdit::SetValue(DurationConstraint &value) +void DurationModifierEdit::SetValue(DurationModifier &value) { _duration->SetDuration(value.GetDuration()); - _condition->setCurrentIndex(static_cast(value.GetCondition())); - _duration->setVisible(value.GetCondition() != DurationCondition::NONE); + _condition->setCurrentIndex(static_cast(value.GetType())); + _duration->setVisible(value.GetType() != DurationModifier::Type::NONE); } -void DurationConstraintEdit::SetUnit(DurationUnit u) +void DurationModifierEdit::SetUnit(DurationUnit u) { _duration->SetUnit(u); } -void DurationConstraintEdit::SetDuration(const Duration &d) +void DurationModifierEdit::SetDuration(const Duration &d) { _duration->SetDuration(d); } -void DurationConstraintEdit::_ConditionChanged(int value) +void DurationModifierEdit::_ModifierChanged(int value) { - auto cond = static_cast(value); - Collapse(cond == DurationCondition::NONE); - emit ConditionChanged(cond); + auto m = static_cast(value); + Collapse(m == DurationModifier::Type::NONE); + emit ModifierChanged(m); } -void DurationConstraintEdit::ToggleClicked() +void DurationModifierEdit::ToggleClicked() { Collapse(false); } -void DurationConstraintEdit::Collapse(bool collapse) +void DurationModifierEdit::Collapse(bool collapse) { _toggle->setVisible(collapse); _duration->setVisible(!collapse); @@ -180,7 +182,7 @@ MacroConditionEdit::MacroConditionEdit( parent), _logicSelection(new QComboBox()), _conditionSelection(new QComboBox()), - _dur(new DurationConstraintEdit()), + _dur(new DurationModifierEdit()), _entryData(entryData), _isRoot(root) { @@ -193,9 +195,9 @@ MacroConditionEdit::MacroConditionEdit( SLOT(DurationChanged(double))); QWidget::connect(_dur, SIGNAL(UnitChanged(DurationUnit)), this, SLOT(DurationUnitChanged(DurationUnit))); - QWidget::connect(_dur, SIGNAL(ConditionChanged(DurationCondition)), + QWidget::connect(_dur, SIGNAL(ModifierChanged(DurationModifier::Type)), this, - SLOT(DurationConditionChanged(DurationCondition))); + SLOT(DurationModifierChanged(DurationModifier::Type))); QWidget::connect(window(), SIGNAL(HighlightConditionsChanged(bool)), this, SLOT(EnableHighlight(bool))); @@ -277,9 +279,9 @@ void MacroConditionEdit::UpdateEntryData(const std::string &id) SetLogicSelection(); _section->SetContent(widget, (*_entryData)->GetCollapsed()); - _dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id)); - auto constraint = (*_entryData)->GetDurationConstraint(); - _dur->SetValue(constraint); + _dur->setVisible(MacroConditionFactory::UsesDurationModifier(id)); + auto modifier = (*_entryData)->GetDurationModifier(); + _dur->SetValue(modifier); SetFocusPolicyOfWidgets(); } @@ -298,7 +300,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text) auto macro = _entryData->get()->GetMacro(); std::string id = MacroConditionFactory::GetIdByName(text); - auto temp = DurationConstraint(); + auto temp = DurationModifier(); _dur->SetValue(temp); HeaderInfoChanged(""); { @@ -314,7 +316,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text) QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)), this, SLOT(HeaderInfoChanged(const QString &))); _section->SetContent(widget); - _dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id)); + _dur->setVisible(MacroConditionFactory::UsesDurationModifier(id)); SetFocusPolicyOfWidgets(); } @@ -328,14 +330,14 @@ void MacroConditionEdit::DurationChanged(double seconds) (*_entryData)->SetDuration(seconds); } -void MacroConditionEdit::DurationConditionChanged(DurationCondition cond) +void MacroConditionEdit::DurationModifierChanged(DurationModifier::Type m) { if (_loading || !_entryData) { return; } std::lock_guard lock(switcher->m); - (*_entryData)->SetDurationCondition(cond); + (*_entryData)->SetDurationModifier(m); } void MacroConditionEdit::DurationUnitChanged(DurationUnit unit) diff --git a/src/macro-condition.cpp b/src/macro-condition.cpp index 6b03c0c2..985be8d0 100644 --- a/src/macro-condition.cpp +++ b/src/macro-condition.cpp @@ -11,44 +11,49 @@ const std::map MacroCondition::logicTypes = { {LogicType::ROOT_NOT, {"AdvSceneSwitcher.logic.not"}}, }; -void DurationConstraint::Save(obs_data_t *obj, const char *condName, - const char *secondsName, const char *unitName) +void DurationModifier::Save(obs_data_t *obj, const char *condName, + const char *secondsName, const char *unitName) { obs_data_set_int(obj, condName, static_cast(_type)); _dur.Save(obj, secondsName, unitName); } -void DurationConstraint::Load(obs_data_t *obj, const char *condName, - const char *secondsName, const char *unitName) +void DurationModifier::Load(obs_data_t *obj, const char *condName, + const char *secondsName, const char *unitName) { // For backwards compatability 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, secondsName)) { - obs_data_set_int(obj, condName, - static_cast(DurationCondition::MORE)); + obs_data_set_int(obj, condName, static_cast(Type::MORE)); } - _type = static_cast(obs_data_get_int(obj, condName)); + _type = static_cast(obs_data_get_int(obj, condName)); _dur.Load(obj, secondsName, unitName); } -bool DurationConstraint::DurationReached() +bool DurationModifier::DurationReached() { switch (_type) { - case DurationCondition::NONE: + case DurationModifier::Type::NONE: return true; break; - case DurationCondition::MORE: + case DurationModifier::Type::MORE: return _dur.DurationReached(); break; - case DurationCondition::EQUAL: + case DurationModifier::Type::EQUAL: if (_dur.DurationReached() && !_timeReached) { _timeReached = true; return true; } break; - case DurationCondition::LESS: + case DurationModifier::Type::LESS: + return !_dur.DurationReached(); + break; + case DurationModifier::Type::WITHIN: + if (_dur.IsReset()) { + return false; + } return !_dur.DurationReached(); break; default: @@ -57,7 +62,7 @@ bool DurationConstraint::DurationReached() return false; } -void DurationConstraint::Reset() +void DurationModifier::Reset() { _timeReached = false; _dur.Reset(); @@ -80,14 +85,44 @@ bool MacroCondition::Load(obs_data_t *obj) return true; } -void MacroCondition::SetDurationConstraint(const DurationConstraint &dur) +void MacroCondition::ResetDuration() { - _duration = dur; + _duration.Reset(); } -void MacroCondition::SetDurationCondition(DurationCondition cond) +void MacroCondition::CheckDurationModifier(bool &val) { - _duration.SetCondition(cond); + 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: + if (!val) { + _duration.Reset(); + } + val = val && _duration.DurationReached(); + return; + case DurationModifier::Type::WITHIN: + if (val) { + _duration.SetTimeRemaining( + _duration.GetDuration().seconds); + } + val = val || _duration.DurationReached(); + break; + default: + break; + } +} + +void MacroCondition::SetDurationModifier(DurationModifier::Type m) +{ + _duration.SetModifier(m); } void MacroCondition::SetDurationUnit(DurationUnit u) diff --git a/src/macro.cpp b/src/macro.cpp index 8d98c0fc..c1e6c3d5 100644 --- a/src/macro.cpp +++ b/src/macro.cpp @@ -43,10 +43,7 @@ bool Macro::CeckMatch() ms.count(), c->GetId().c_str(), Name().c_str()); } - if (!cond) { - c->ResetDuration(); - } - cond = cond && c->DurationReached(); + c->CheckDurationModifier(cond); switch (c->GetLogicType()) { case LogicType::NONE: