HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
animator.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../macros.hpp"
8#include "../utility/utility.hpp"
9#include "../time/time.hpp"
10#include <cmath>
11#include <chrono>
12#include <algorithm>
13
14hi_export_module(hikogui.algorithm.animator);
15
16hi_export namespace hi::inline v1 {
17
18enum class animator_state {
19 uninitialized, idle, running, end
20};
21
24template<arithmetic T>
25class animator {
26public:
27 using value_type = T;
28
32 animator(std::chrono::nanoseconds animation_duration) noexcept :
33 _animation_duration(animation_duration), _old_value(), _new_value(), _start_time(), _current_time(std::chrono::utc_clock::now()), _state(animator_state::uninitialized)
34 {
35 }
36
42 [[nodiscard]] animator_state update(value_type new_value, utc_nanoseconds current_time) noexcept
43 {
44 if (_state == animator_state::uninitialized) {
45 _state = animator_state::idle;
46 _old_value = new_value;
47 _new_value = new_value;
48 _start_time = {};
49 } else if (new_value != _new_value) {
50 _state = animator_state::running;
51 _old_value = _new_value;
52 _new_value = new_value;
53 _start_time = current_time;
54 }
55 _current_time = current_time;
56 return is_animating();
57 }
58
62 [[nodiscard]] animator_state is_animating() const noexcept
63 {
64 switch (_state) {
65 case animator_state::uninitialized:
66 return animator_state::uninitialized;
67 case animator_state::idle:
68 return animator_state::idle;
69 case animator_state::running:
70 if (progress() < 1.0f) {
71 return animator_state::running;
72 } else {
73 return _state = animator_state::end;
74 }
75 case animator_state::end:
76 return _state = animator_state::idle;
77 default:
78 hi_no_default();
79 }
80 }
81
84 value_type current_value() const noexcept
85 {
86 return std::lerp(_old_value, _new_value, progress());
87 }
88
89private:
90 std::chrono::nanoseconds _animation_duration;
91
92 value_type _old_value;
93 value_type _new_value;
94 utc_nanoseconds _start_time;
95 utc_nanoseconds _current_time;
96 mutable animator_state _state;
97
98 float progress() const noexcept
99 {
100 using namespace std::chrono_literals;
101
102 auto const dt = _current_time - _start_time;
103 auto const p = static_cast<float>(dt / 1ms) / static_cast<float>(_animation_duration / 1ms);
104 return std::clamp(p, 0.0f, 1.0f);
105 }
106};
107
108} // namespace hi::inline v1
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
A type that gets animated between two values.
Definition animator.hpp:25
animator(std::chrono::nanoseconds animation_duration) noexcept
Constructor.
Definition animator.hpp:32
value_type current_value() const noexcept
The interpolated value between start and end value.
Definition animator.hpp:84
animator_state is_animating() const noexcept
Check if the animation is currently running.
Definition animator.hpp:62
animator_state update(value_type new_value, utc_nanoseconds current_time) noexcept
Update the value and time.
Definition animator.hpp:42
T end(T... args)