int main() { initialize(); for (;;) { sequential_animation<animation_loop, repeat<speed<to_grb888<rainbow_animation>, 8>, 8>, repeat<speed<to_grb888<rainbow_animation>, 4>, 4>, repeat<speed<to_grb888<rainbow_animation>, 2>, 2>>(); } return 0; }
I’m working on animation framework that’s semi-type driven. If you’re not sure how it works I’ll try to explain.
Let’s examine the rainbow_animation, this is an animation object that storing current animation progress. It has three methods:
- value(), that’s storing current rgb value of animation
- step(), after call step, animation will do one iteration
- is_finished(), hold state of end condition
Basic use of rainbow_animation will be looking like this:
rainbow_animation animation; while (!animation.is_finished()) { const auto current_color = animation.value(); doSomethingWithColor(current_color); animation.step(); }
To hide details about animation loop, we can create a templated function like this:
run_animation<doSomethingWithColorFunction, rainbow_animation>()
But if we want to run multiple animations we will end with:
run_animation<doSomethingWithColorFunction, rainbow_animation>(); run_animation<doSomethingWithColorFunction, custom_color_animation>(); run_animation<doSomethingWithColorFunction, other_color_animation>();
Until we’ll take advantage of variadic template that will call run_annimation multiple times, for every type that we’ll pass.
sequential_animation<doSomethingWithColorFunction, rainbow_animation, custom_color_animation, other_color_animation>();
But what if we want repeat a custom_color_animation 5 times?
sequential_animation<doSomethingWithColorFunction, rainbow_animation, custom_color_animation, custom_color_animation, custom_color_animation, custom_color_animation, custom_color_animation, other_color_animation>();
Is this a little ugly? To fix this problem we can create a class wrapper that will call custom_color_animation as many times as we declare.
template <animation_interface animation_type, auto times> class repeat { static_assert(times > 0); public: constexpr auto value() const noexcept { return m_animation.value(); } void step() { m_animation.step(); if (m_animation.is_finished()) { m_finished = (--m_steps) == 0; m_animation = decltype(m_animation){}; } } constexpr bool is_finished() const noexcept { return m_finished; } private: int m_steps = times; animation_type m_animation; bool m_finished{false}; };
And now we can fix code using repeat wrapper:
sequential_animation<doSomethingWithColorFunction, rainbow_animation, repeat<custom_color_animation, 5>, other_color_animation>();
For palette conversion and animation speed, we can do similar wrappers. You can find more code there: https://github.com/dev-0x7C6/ledboard/tree/master/src/animation