From 6131e6a68795d4b3f866abd877f13a6ce91a79cc Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Tue, 3 Dec 2019 22:09:55 +0100 Subject: [PATCH] Implement Animation-specific fadeout --- include/Animation/Animation.h | 36 ++++++++++++++++++++++- include/Animation/AnimationController.h | 6 ++-- include/Animation/ConnectingAnimation.h | 13 ++++++++- src/Animation/AnimationController.cpp | 39 ++++++++++++++++--------- src/Animation/ConnectingAnimation.cpp | 10 +++++-- src/main.cpp | 3 +- 6 files changed, 87 insertions(+), 20 deletions(-) diff --git a/include/Animation/Animation.h b/include/Animation/Animation.h index 8dea270..dd8a254 100644 --- a/include/Animation/Animation.h +++ b/include/Animation/Animation.h @@ -8,11 +8,45 @@ class Animation { public: Animation(Fader *fader) - : m_fader(fader) + : m_fader(fader), m_running(true) {} + /*! + * The animation's main function. Will be called once per frame. + * + * \param frame The current frame since the animation's start. + */ virtual void loop(uint64_t frame) = 0; + /*! + * Stop the animation. After this function is called, the animation code + * might start some transition to black (all LEDs off). + */ + virtual void stop(void) + { + m_running = false; + } + + /*! + * A function for checking wether the animation has stopped. This must + * return true after the stop transition has finished. + * + * \returns True if all activity of the animation code has stopped. + */ + virtual bool finished(void) + { + return !m_running; + } + + /*! + * Reset function of the animation code. This should clear any + * internal state. + * + * By default does nothing. + */ + virtual void reset(void) {}; + protected: Fader *m_fader; + bool m_running; }; diff --git a/include/Animation/AnimationController.h b/include/Animation/AnimationController.h index a77482e..91ef412 100644 --- a/include/Animation/AnimationController.h +++ b/include/Animation/AnimationController.h @@ -9,13 +9,15 @@ class AnimationController public: AnimationController(Fader *fader); - void setAnimation(std::unique_ptr anim, bool transition = true); + void changeAnimation(std::unique_ptr anim, bool transition = true); void loop(void); + void restart(void); + private: Fader *m_fader; std::unique_ptr m_animation; + std::unique_ptr m_nextAnimation; - uint32_t m_transitionTime; uint64_t m_frame; }; diff --git a/include/Animation/ConnectingAnimation.h b/include/Animation/ConnectingAnimation.h index 3fbed28..a66e527 100644 --- a/include/Animation/ConnectingAnimation.h +++ b/include/Animation/ConnectingAnimation.h @@ -9,6 +9,17 @@ class ConnectingAnimation : public Animation void loop(uint64_t frame) override; + void stop(void) override + { + m_stopping = true; + } + + void reset(void) override + { + m_stopping = false; + m_running = true; + } + private: - uint32_t m_loop; + bool m_stopping; }; diff --git a/src/Animation/AnimationController.cpp b/src/Animation/AnimationController.cpp index 962ce13..5ef55d1 100644 --- a/src/Animation/AnimationController.cpp +++ b/src/Animation/AnimationController.cpp @@ -1,30 +1,43 @@ +#include + #include "Animation/AnimationController.h" AnimationController::AnimationController(Fader *fader) - : m_fader(fader), m_transitionTime(0), m_frame(0) + : m_fader(fader), m_animation(nullptr), m_frame(0) {} -void AnimationController::setAnimation(std::unique_ptr anim, bool transition) +void AnimationController::changeAnimation(std::unique_ptr anim, bool transition) { - m_frame = 0; + if(transition && m_animation) { + m_nextAnimation = std::move(anim); + m_animation->stop(); + } else { + m_frame = 0; - m_animation = std::move(anim); - - if(transition) { - m_transitionTime = 256/8; - - m_fader->set_fadestep(8); - m_fader->fade_color(Fader::Color{0, 0, 0, 0}); + m_animation = std::move(anim); + m_nextAnimation.reset(nullptr); } } void AnimationController::loop(void) { - if(m_transitionTime > 0) { - m_transitionTime--; - } else if(m_animation) { + if(m_animation && !m_animation->finished()) { m_animation->loop(m_frame); } + if(m_nextAnimation && + (!m_animation || m_animation->finished())) { + // old animation has finished or is unset -> start the new one + m_frame = 0; + m_animation.swap(m_nextAnimation); + m_nextAnimation.reset(nullptr); + } + m_frame++; } + +void AnimationController::restart(void) +{ + m_animation->reset(); + m_frame = 0; +} diff --git a/src/Animation/ConnectingAnimation.cpp b/src/Animation/ConnectingAnimation.cpp index db1e28d..3fd1184 100644 --- a/src/Animation/ConnectingAnimation.cpp +++ b/src/Animation/ConnectingAnimation.cpp @@ -3,24 +3,30 @@ #include "Animation/ConnectingAnimation.h" ConnectingAnimation::ConnectingAnimation(Fader *fader) - : Animation(fader) + : Animation(fader), m_stopping(false) {} void ConnectingAnimation::loop(uint64_t frame) { std::size_t nled = m_fader->modules_per_strip(); std::size_t nstrip = m_fader->strips(); + uint8_t intensity = 0; if(frame == 0) { m_fader->fade_color(Fader::Color{0, 0, 0, 0}); } for(std::size_t strip = 0; strip < nstrip; strip++) { - uint8_t intensity = (fasttrigon::fastsin(1 * frame * fasttrigon::LUT_SIZE / 60) + 127) / 4; + intensity = (fasttrigon::fastsin(1 * frame * fasttrigon::LUT_SIZE / 60) + 127) / 4; Fader::Color c; c.b = intensity; m_fader->set_color(strip, 0, c); } + + // stop the animation if everything is dark + if(m_stopping && intensity == 0) { + m_running = false; + } } diff --git a/src/main.cpp b/src/main.cpp index fd57135..f8d3642 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -209,7 +209,8 @@ void setup() Serial.println(); Serial.println(); - animController.setAnimation(std::unique_ptr(new ConnectingAnimation(&ledFader))); + ledFader.set_color(Fader::Color{0, 1, 0, 0}); + animController.changeAnimation(std::unique_ptr(new ConnectingAnimation(&ledFader))); xTaskCreate( ledTask, /* Task function. */