diff --git a/theatre/effects/randomselecteffect.h b/theatre/effects/randomselecteffect.h index d6585c3..3ebb6df 100644 --- a/theatre/effects/randomselecteffect.h +++ b/theatre/effects/randomselecteffect.h @@ -20,30 +20,48 @@ class RandomSelectEffect final : public Effect { size_t Count() const { return _count; } void SetCount(size_t count) { _count = count; } + void SetTransition(const Transition &transition) { transition_ = transition; } + const Transition &GetTransition() const { return transition_; } + private: virtual void MixImplementation(const ControlValue *values, const Timing &timing, bool primary) final { size_t n_active = std::min(_count, Connections().size()); if (values[0] && n_active != 0) { std::vector &activeConnections = _activeConnections[primary]; + std::vector &transition_connections = + transition_connections_[primary]; if (Connections().size() != activeConnections.size()) { activeConnections.resize(Connections().size()); - for (size_t i = 0; i != activeConnections.size(); ++i) + for (size_t i = 0; i != activeConnections.size(); ++i) { activeConnections[i] = i; + } + transition_connections = activeConnections; Shuffle(activeConnections, timing, false); + active_transition_[primary] = false; } - if (!_active[primary] || - timing.TimeInMS() - _startTime[primary] > _delay) { + const bool delay_expired = + timing.TimeInMS() - _startTime[primary] >= _delay; + if (!_active[primary] || delay_expired) { _active[primary] = true; _startTime[primary] = timing.TimeInMS(); + transition_connections = activeConnections; Shuffle(activeConnections, timing, true); + active_transition_[primary] = delay_expired; } - for (size_t i = 0; i != n_active; ++i) { - if (activeConnections[i] < Connections().size()) { - const std::pair &connection = - Connections()[activeConnections[i]]; - connection.first->MixInput(connection.second, values[0]); - } + double transition_time; + if (active_transition_[primary]) { + transition_time = timing.TimeInMS() - _startTime[primary]; + active_transition_[primary] = + transition_time < transition_.LengthInMs(); + } + if (active_transition_[primary]) { + MixDirect(transition_connections, + values[0] * transition_.OutValue(transition_time, timing)); + MixDirect(activeConnections, + values[0] * transition_.InValue(transition_time, timing)); + } else { + MixDirect(activeConnections, values[0]); } } else { _active[primary] = false; @@ -63,12 +81,27 @@ class RandomSelectEffect final : public Effect { } } + void MixDirect(const std::vector &connections, + const ControlValue value) { + size_t n_active = std::min(_count, Connections().size()); + for (size_t i = 0; i != n_active; ++i) { + if (connections[i] < Connections().size()) { + const std::pair &connection = + Connections()[connections[i]]; + connection.first->MixInput(connection.second, value); + } + } + } + bool _active[2] = {false, false}; std::array, 2> _activeConnections; + std::array, 2> transition_connections_; double _startTime[2] = {0.0, 0.0}; + bool active_transition_[2] = {false, false}; double _delay = 10000.0; size_t _count = 1; + Transition transition_; }; } // namespace glight::theatre diff --git a/theatre/properties/randomselecteffectps.h b/theatre/properties/randomselecteffectps.h index 52e6ae9..70a2036 100644 --- a/theatre/properties/randomselecteffectps.h +++ b/theatre/properties/randomselecteffectps.h @@ -13,11 +13,12 @@ class RandomSelectEffectPS final : public PropertySet { addProperty( Property("delay", "Delay for reselection", PropertyType::Duration)); addProperty(Property("count", "Number of outputs", PropertyType::Integer)); + addProperty(Property("transition", "Transition", PropertyType::Transition)); } protected: virtual void setDuration(FolderObject &object, size_t index, - double value) const final override { + double value) const final { RandomSelectEffect &rfx = static_cast(object); switch (index) { case 0: @@ -27,7 +28,7 @@ class RandomSelectEffectPS final : public PropertySet { } virtual double getDuration(const FolderObject &object, - size_t index) const final override { + size_t index) const final { const RandomSelectEffect &rfx = static_cast(object); switch (index) { @@ -38,7 +39,7 @@ class RandomSelectEffectPS final : public PropertySet { } virtual void setInteger(FolderObject &object, size_t index, - int value) const final override { + int value) const final { RandomSelectEffect &rfx = static_cast(object); switch (index) { case 1: @@ -47,8 +48,7 @@ class RandomSelectEffectPS final : public PropertySet { } } - virtual int getInteger(const FolderObject &object, - size_t index) const final override { + virtual int getInteger(const FolderObject &object, size_t index) const final { const RandomSelectEffect &rfx = static_cast(object); switch (index) { @@ -57,6 +57,23 @@ class RandomSelectEffectPS final : public PropertySet { } return 0; } + + virtual void setTransition(FolderObject &object, size_t index, + const Transition &value) const final { + RandomSelectEffect &rfx = static_cast(object); + switch (index) { + case 2: + rfx.SetTransition(value); + break; + } + } + + virtual Transition getTransition(const FolderObject &object, + size_t index) const final { + const RandomSelectEffect &rfx = + static_cast(object); + return rfx.GetTransition(); + } }; } // namespace glight::theatre diff --git a/theatre/transition.cpp b/theatre/transition.cpp index 111ac1b..87cbbd5 100644 --- a/theatre/transition.cpp +++ b/theatre/transition.cpp @@ -73,26 +73,22 @@ ControlValue Transition::InValue(double transition_time, return ControlValue::Zero(); } case TransitionType::SlowStrobe: - return timing.TimestepNumber() % 8 == 0 ? ControlValue::Max() - : ControlValue::Zero(); + return (timing.TimestepNumber() % 8) == 0 ? ControlValue::Max() + : ControlValue::Zero(); case TransitionType::FastStrobe: - return timing.TimestepNumber() % 2 == 0 ? ControlValue::Max() - : ControlValue::Zero(); + return (timing.TimestepNumber() % 2) == 0 ? ControlValue::Max() + : ControlValue::Zero(); case TransitionType::StrobeAB: - return transition_time * 2.0 < length_in_ms_ && + return transition_time * 2.0 >= length_in_ms_ && timing.TimestepNumber() % 2 == 0 ? ControlValue::Max() : ControlValue::Zero(); case TransitionType::Black: + case TransitionType::FadeToBlack: return ControlValue::Zero(); case TransitionType::Full: case TransitionType::FadeFromFull: return ControlValue::Max(); - case TransitionType::FadeToBlack: { - const unsigned ratio = (unsigned)((transition_time / length_in_ms_) * - ControlValue::MaxUInt()); - return ControlValue(ControlValue::MaxUInt() - ratio); - } } assert(false); return ControlValue::Zero(); @@ -173,14 +169,14 @@ ControlValue Transition::OutValue(double transition_time, return ControlValue::Zero(); } case TransitionType::SlowStrobe: - return timing.TimestepNumber() % 8 + 4 == 0 ? ControlValue::Max() - : ControlValue::Zero(); + return (timing.TimestepNumber() % 8) == 4 ? ControlValue::Max() + : ControlValue::Zero(); case TransitionType::FastStrobe: - return timing.TimestepNumber() % 2 == 1 ? ControlValue::Max() - : ControlValue::Zero(); + return (timing.TimestepNumber() % 2) == 1 ? ControlValue::Max() + : ControlValue::Zero(); case TransitionType::StrobeAB: - return transition_time * 2.0 >= length_in_ms_ && - timing.TimestepNumber() % 2 == 0 + return transition_time * 2.0 < length_in_ms_ && + timing.TimestepNumber() % 2 == 1 ? ControlValue::Max() : ControlValue::Zero(); case TransitionType::Black: diff --git a/theatre/transition.h b/theatre/transition.h index 84b9209..93d142f 100644 --- a/theatre/transition.h +++ b/theatre/transition.h @@ -185,6 +185,8 @@ class Transition { constexpr Transition(double length_in_ms, TransitionType type) noexcept : length_in_ms_(length_in_ms), type_(type) {} + constexpr bool operator==(const Transition &rhs) const = default; + constexpr TransitionType Type() const { return type_; } void SetType(TransitionType type) { type_ = type; }