yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
animator.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cmath>
5
7#include "imgui/imgui.h"
8
9namespace yaze {
10namespace gui {
11
12float Animator::Lerp(float a, float b, float t) {
13 return a + (b - a) * t;
14}
15
16float Animator::EaseOutCubic(float t) {
17 float inv = 1.0f - t;
18 return 1.0f - (inv * inv * inv);
19}
20
22 return t < 0.5f ? 4.0f * t * t * t
23 : 1.0f - std::pow(-2.0f * t + 2.0f, 3.0f) / 2.0f;
24}
25
27 const float c4 = (2.0f * 3.14159265f) / 3.0f;
28 if (t <= 0.0f) return 0.0f;
29 if (t >= 1.0f) return 1.0f;
30 return std::pow(2.0f, -10.0f * t) * std::sin((t * 10.0f - 0.75f) * c4) + 1.0f;
31}
32
33float Animator::EaseOutBack(float t) {
34 const float c1 = 1.70158f;
35 const float c3 = c1 + 1.0f;
36 float tm1 = t - 1.0f;
37 return 1.0f + c3 * tm1 * tm1 * tm1 + c1 * tm1 * tm1;
38}
39
40ImVec4 Animator::LerpColor(ImVec4 a, ImVec4 b, float t) {
41 return ImVec4(Lerp(a.x, b.x, t), Lerp(a.y, b.y, t), Lerp(a.z, b.z, t),
42 Lerp(a.w, b.w, t));
43}
44
45float Animator::Animate(const std::string& panel_id,
46 const std::string& anim_id, float target,
47 float speed) {
48 auto& state = GetState(panel_id, anim_id);
49 if (!state.has_value) {
50 state.value = target;
51 state.has_value = true;
52 }
53
54 if (!IsEnabled()) {
55 state.value = target;
56 return target;
57 }
58
59 float t = ComputeStep(speed);
60 state.value = Lerp(state.value, target, t);
61 return state.value;
62}
63
64ImVec4 Animator::AnimateColor(const std::string& panel_id,
65 const std::string& anim_id, ImVec4 target,
66 float speed) {
67 auto& state = GetState(panel_id, anim_id);
68 if (!state.has_color) {
69 state.color = target;
70 state.has_color = true;
71 }
72
73 if (!IsEnabled()) {
74 state.color = target;
75 return target;
76 }
77
78 float t = ComputeStep(speed);
79 state.color = LerpColor(state.color, target, t);
80 return state.color;
81}
82
83void Animator::ClearAnimationsForPanel(const std::string& panel_id) {
84 panels_.erase(panel_id);
85 panel_transitions_.erase(panel_id);
86 pushed_transition_alpha_.erase(panel_id);
87}
88
94
96 if (raw_profile <= static_cast<int>(MotionProfile::kSnappy)) {
98 }
99 if (raw_profile >= static_cast<int>(MotionProfile::kRelaxed)) {
101 }
103}
104
105void Animator::SetMotionPreferences(bool reduced_motion,
106 MotionProfile profile) {
108 motion_profile_ = profile;
109}
110
111void Animator::BeginPanelTransition(const std::string& panel_id,
112 TransitionType type) {
113 if (!IsEnabled() || type == TransitionType::kNone) {
114 return;
115 }
116
117 auto& state = panel_transitions_[panel_id];
118 state.type = type;
119 state.progress = 0.0f;
120 state.active = true;
121
122 // Set initial offsets based on transition type
123 switch (type) {
125 state.initial_offset_x = -50.0f;
126 state.initial_offset_y = 0.0f;
127 break;
129 state.initial_offset_x = 50.0f;
130 state.initial_offset_y = 0.0f;
131 break;
133 state.initial_offset_x = 0.0f;
134 state.initial_offset_y = 50.0f;
135 break;
137 state.initial_offset_x = 0.0f;
138 state.initial_offset_y = -50.0f;
139 break;
140 default:
141 state.initial_offset_x = 0.0f;
142 state.initial_offset_y = 0.0f;
143 break;
144 }
145}
146
148 const std::string& panel_id, float speed) {
149 PanelTransition result;
150
151 if (!IsEnabled()) {
152 return result; // Return default (fully visible, no offset)
153 }
154
155 auto iter = panel_transitions_.find(panel_id);
156 if (iter == panel_transitions_.end() || !iter->second.active) {
157 return result; // No active transition
158 }
159
160 auto& state = iter->second;
161
162 // Update progress
163 float step = ComputeStep(speed);
164 state.progress = std::min(state.progress + step, 1.0f);
165
166 // Apply profile-specific easing for editor/workspace transitions.
167 float eased = ApplyTransitionEasing(state.progress);
168
169 // Calculate current values based on transition type
170 switch (state.type) {
172 result.alpha = eased;
173 break;
174
179 result.alpha = eased;
180 result.offset_x = state.initial_offset_x * (1.0f - eased);
181 result.offset_y = state.initial_offset_y * (1.0f - eased);
182 break;
183
185 result.alpha = eased;
186 result.scale = 0.8f + (0.2f * eased); // Scale from 0.8 to 1.0
187 break;
188
190 result.alpha = eased;
191 result.scale = eased; // Scale from 0 to 1
192 break;
193
195 default:
196 break;
197 }
198
199 // Mark as complete when done
200 if (state.progress >= 1.0f) {
201 state.active = false;
202 result.is_complete = true;
203 } else {
204 result.is_complete = false;
205 }
206
207 return result;
208}
209
210bool Animator::IsPanelTransitioning(const std::string& panel_id) const {
211 auto iter = panel_transitions_.find(panel_id);
212 return iter != panel_transitions_.end() && iter->second.active;
213}
214
215void Animator::ApplyPanelTransitionPre(const std::string& panel_id) {
216 auto iter = panel_transitions_.find(panel_id);
217 if (iter == panel_transitions_.end() || !iter->second.active) {
218 return;
219 }
220
221 auto transition = UpdatePanelTransition(panel_id);
222 if (transition.is_complete) {
223 return;
224 }
225
226 // Set window position offset for slide transitions
227 if (transition.offset_x != 0.0f || transition.offset_y != 0.0f) {
228 ImVec2 window_pos = ImGui::GetCursorScreenPos();
229 ImGui::SetNextWindowPos(
230 ImVec2(window_pos.x + transition.offset_x,
231 window_pos.y + transition.offset_y),
232 ImGuiCond_Always);
233 }
234
235 // Apply alpha and record stack push so post-pass can pop safely.
236 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, transition.alpha);
237 pushed_transition_alpha_.insert(panel_id);
238}
239
240void Animator::ApplyPanelTransitionPost(const std::string& panel_id) {
241 // Pop only when pre-pass pushed this frame.
242 if (pushed_transition_alpha_.erase(panel_id) > 0) {
243 ImGui::PopStyleVar();
244 }
245}
246
248 if (ImGui::GetCurrentContext() == nullptr) {
249 return false;
250 }
251 if (reduced_motion_) {
252 return false;
253 }
254 const auto& theme = ThemeManager::Get().GetCurrentTheme();
255 return theme.enable_animations;
256}
257
258Animator::AnimationState& Animator::GetState(const std::string& panel_id,
259 const std::string& anim_id) {
260 return panels_[panel_id][anim_id];
261}
262
263float Animator::ComputeStep(float speed) const {
264 if (ImGui::GetCurrentContext() == nullptr) {
265 return 1.0f;
266 }
267
268 const auto& theme = ThemeManager::Get().GetCurrentTheme();
269 const float scaled_speed =
271 const float delta = ImGui::GetIO().DeltaTime;
272 const float t = 1.0f - std::exp(-scaled_speed * delta);
273 return std::clamp(t, 0.0f, 1.0f);
274}
275
277 switch (motion_profile_) {
279 return 1.35f;
281 return 0.72f;
283 default:
284 return 1.0f;
285 }
286}
287
289 t = std::clamp(t, 0.0f, 1.0f);
290 switch (motion_profile_) {
292 return EaseOutCubic(t);
294 return t * t * (3.0f - 2.0f * t); // Smoothstep
296 default:
297 return EaseInOutCubic(t);
298 }
299}
300
302 static Animator animator;
303 return animator;
304}
305
306} // namespace gui
307} // namespace yaze
static float EaseOutBack(float t)
Definition animator.cc:33
void ClearAnimationsForPanel(const std::string &panel_id)
Definition animator.cc:83
bool IsPanelTransitioning(const std::string &panel_id) const
Definition animator.cc:210
static MotionProfile ClampMotionProfile(int raw_profile)
Definition animator.cc:95
float ComputeStep(float speed) const
Definition animator.cc:263
PanelTransition UpdatePanelTransition(const std::string &panel_id, float speed=8.0f)
Definition animator.cc:147
static float EaseInOutCubic(float t)
Definition animator.cc:21
void SetMotionPreferences(bool reduced_motion, MotionProfile profile)
Definition animator.cc:105
void ApplyPanelTransitionPre(const std::string &panel_id)
Definition animator.cc:215
AnimationState & GetState(const std::string &panel_id, const std::string &anim_id)
Definition animator.cc:258
float ApplyTransitionEasing(float t) const
Definition animator.cc:288
static float Lerp(float a, float b, float t)
Definition animator.cc:12
ImVec4 AnimateColor(const std::string &panel_id, const std::string &anim_id, ImVec4 target, float speed=5.0f)
Definition animator.cc:64
bool reduced_motion() const
Definition animator.h:77
static float EaseOutElastic(float t)
Definition animator.cc:26
static ImVec4 LerpColor(ImVec4 a, ImVec4 b, float t)
Definition animator.cc:40
std::unordered_set< std::string > pushed_transition_alpha_
Definition animator.h:108
float Animate(const std::string &panel_id, const std::string &anim_id, float target, float speed=5.0f)
Definition animator.cc:45
MotionProfile motion_profile_
Definition animator.h:111
float GetProfileSpeedMultiplier() const
Definition animator.cc:276
std::unordered_map< std::string, AnimationMap > panels_
Definition animator.h:106
void ApplyPanelTransitionPost(const std::string &panel_id)
Definition animator.cc:240
bool IsEnabled() const
Definition animator.cc:247
void BeginPanelTransition(const std::string &panel_id, TransitionType type)
Definition animator.cc:111
void ClearAllAnimations()
Definition animator.cc:89
static float EaseOutCubic(float t)
Definition animator.cc:16
std::unordered_map< std::string, PanelTransitionState > panel_transitions_
Definition animator.h:107
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
Animator & GetAnimator()
Definition animator.cc:301