1/**************************************************************************/
2/* tween.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef TWEEN_H
32#define TWEEN_H
33
34#include "core/object/ref_counted.h"
35
36class Tween;
37class Node;
38
39class Tweener : public RefCounted {
40 GDCLASS(Tweener, RefCounted);
41
42public:
43 virtual void set_tween(const Ref<Tween> &p_tween);
44 virtual void start() = 0;
45 virtual bool step(double &r_delta) = 0;
46 void clear_tween();
47
48protected:
49 static void _bind_methods();
50
51 Ref<Tween> tween;
52 double elapsed_time = 0;
53 bool finished = false;
54};
55
56class PropertyTweener;
57class IntervalTweener;
58class CallbackTweener;
59class MethodTweener;
60
61class Tween : public RefCounted {
62 GDCLASS(Tween, RefCounted);
63
64 friend class PropertyTweener;
65
66public:
67 enum TweenProcessMode {
68 TWEEN_PROCESS_PHYSICS,
69 TWEEN_PROCESS_IDLE,
70 };
71
72 enum TweenPauseMode {
73 TWEEN_PAUSE_BOUND,
74 TWEEN_PAUSE_STOP,
75 TWEEN_PAUSE_PROCESS,
76 };
77
78 enum TransitionType {
79 TRANS_LINEAR,
80 TRANS_SINE,
81 TRANS_QUINT,
82 TRANS_QUART,
83 TRANS_QUAD,
84 TRANS_EXPO,
85 TRANS_ELASTIC,
86 TRANS_CUBIC,
87 TRANS_CIRC,
88 TRANS_BOUNCE,
89 TRANS_BACK,
90 TRANS_SPRING,
91 TRANS_MAX
92 };
93
94 enum EaseType {
95 EASE_IN,
96 EASE_OUT,
97 EASE_IN_OUT,
98 EASE_OUT_IN,
99 EASE_MAX
100 };
101
102private:
103 TweenProcessMode process_mode = TweenProcessMode::TWEEN_PROCESS_IDLE;
104 TweenPauseMode pause_mode = TweenPauseMode::TWEEN_PAUSE_BOUND;
105 TransitionType default_transition = TransitionType::TRANS_LINEAR;
106 EaseType default_ease = EaseType::EASE_IN_OUT;
107 ObjectID bound_node;
108
109 Vector<List<Ref<Tweener>>> tweeners;
110 double total_time = 0;
111 int current_step = -1;
112 int loops = 1;
113 int loops_done = 0;
114 float speed_scale = 1;
115
116 bool is_bound = false;
117 bool started = false;
118 bool running = true;
119 bool dead = false;
120 bool valid = false;
121 bool default_parallel = false;
122 bool parallel_enabled = false;
123#ifdef DEBUG_ENABLED
124 bool is_infinite = false;
125#endif
126
127 typedef real_t (*interpolater)(real_t t, real_t b, real_t c, real_t d);
128 static interpolater interpolaters[TRANS_MAX][EASE_MAX];
129
130 void _start_tweeners();
131 void _stop_internal(bool p_reset);
132 bool _validate_type_match(const Variant &p_from, Variant &r_to);
133
134protected:
135 static void _bind_methods();
136
137public:
138 virtual String to_string() override;
139
140 Ref<PropertyTweener> tween_property(const Object *p_target, const NodePath &p_property, Variant p_to, double p_duration);
141 Ref<IntervalTweener> tween_interval(double p_time);
142 Ref<CallbackTweener> tween_callback(const Callable &p_callback);
143 Ref<MethodTweener> tween_method(const Callable &p_callback, const Variant p_from, Variant p_to, double p_duration);
144 void append(Ref<Tweener> p_tweener);
145
146 bool custom_step(double p_delta);
147 void stop();
148 void pause();
149 void play();
150 void kill();
151
152 bool is_running();
153 bool is_valid();
154 void clear();
155
156 Ref<Tween> bind_node(const Node *p_node);
157 Ref<Tween> set_process_mode(TweenProcessMode p_mode);
158 TweenProcessMode get_process_mode();
159 Ref<Tween> set_pause_mode(TweenPauseMode p_mode);
160 TweenPauseMode get_pause_mode();
161
162 Ref<Tween> set_parallel(bool p_parallel);
163 Ref<Tween> set_loops(int p_loops);
164 int get_loops_left() const;
165 Ref<Tween> set_speed_scale(float p_speed);
166 Ref<Tween> set_trans(TransitionType p_trans);
167 TransitionType get_trans();
168 Ref<Tween> set_ease(EaseType p_ease);
169 EaseType get_ease();
170
171 Ref<Tween> parallel();
172 Ref<Tween> chain();
173
174 static real_t run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d);
175 static Variant interpolate_variant(const Variant &p_initial_val, const Variant &p_delta_val, double p_time, double p_duration, Tween::TransitionType p_trans, Tween::EaseType p_ease);
176
177 bool step(double p_delta);
178 bool can_process(bool p_tree_paused) const;
179 Node *get_bound_node() const;
180 double get_total_time() const;
181
182 Tween();
183 Tween(bool p_valid);
184};
185
186VARIANT_ENUM_CAST(Tween::TweenPauseMode);
187VARIANT_ENUM_CAST(Tween::TweenProcessMode);
188VARIANT_ENUM_CAST(Tween::TransitionType);
189VARIANT_ENUM_CAST(Tween::EaseType);
190
191class PropertyTweener : public Tweener {
192 GDCLASS(PropertyTweener, Tweener);
193
194public:
195 Ref<PropertyTweener> from(const Variant &p_value);
196 Ref<PropertyTweener> from_current();
197 Ref<PropertyTweener> as_relative();
198 Ref<PropertyTweener> set_trans(Tween::TransitionType p_trans);
199 Ref<PropertyTweener> set_ease(Tween::EaseType p_ease);
200 Ref<PropertyTweener> set_delay(double p_delay);
201
202 void set_tween(const Ref<Tween> &p_tween) override;
203 void start() override;
204 bool step(double &r_delta) override;
205
206 PropertyTweener(const Object *p_target, const Vector<StringName> &p_property, const Variant &p_to, double p_duration);
207 PropertyTweener();
208
209protected:
210 static void _bind_methods();
211
212private:
213 ObjectID target;
214 Vector<StringName> property;
215 Variant initial_val;
216 Variant base_final_val;
217 Variant final_val;
218 Variant delta_val;
219
220 Ref<RefCounted> ref_copy; // Makes sure that RefCounted objects are not freed too early.
221
222 double duration = 0;
223 Tween::TransitionType trans_type = Tween::TRANS_MAX; // This is set inside set_tween();
224 Tween::EaseType ease_type = Tween::EASE_MAX;
225
226 double delay = 0;
227 bool do_continue = true;
228 bool relative = false;
229};
230
231class IntervalTweener : public Tweener {
232 GDCLASS(IntervalTweener, Tweener);
233
234public:
235 void start() override;
236 bool step(double &r_delta) override;
237
238 IntervalTweener(double p_time);
239 IntervalTweener();
240
241private:
242 double duration = 0;
243};
244
245class CallbackTweener : public Tweener {
246 GDCLASS(CallbackTweener, Tweener);
247
248public:
249 Ref<CallbackTweener> set_delay(double p_delay);
250
251 void start() override;
252 bool step(double &r_delta) override;
253
254 CallbackTweener(const Callable &p_callback);
255 CallbackTweener();
256
257protected:
258 static void _bind_methods();
259
260private:
261 Callable callback;
262 double delay = 0;
263
264 Ref<RefCounted> ref_copy;
265};
266
267class MethodTweener : public Tweener {
268 GDCLASS(MethodTweener, Tweener);
269
270public:
271 Ref<MethodTweener> set_trans(Tween::TransitionType p_trans);
272 Ref<MethodTweener> set_ease(Tween::EaseType p_ease);
273 Ref<MethodTweener> set_delay(double p_delay);
274
275 void set_tween(const Ref<Tween> &p_tween) override;
276 void start() override;
277 bool step(double &r_delta) override;
278
279 MethodTweener(const Callable &p_callback, const Variant &p_from, const Variant &p_to, double p_duration);
280 MethodTweener();
281
282protected:
283 static void _bind_methods();
284
285private:
286 double duration = 0;
287 double delay = 0;
288 Tween::TransitionType trans_type = Tween::TRANS_MAX;
289 Tween::EaseType ease_type = Tween::EASE_MAX;
290
291 Ref<Tween> tween;
292 Variant initial_val;
293 Variant delta_val;
294 Variant final_val;
295 Callable callback;
296
297 Ref<RefCounted> ref_copy;
298};
299
300#endif // TWEEN_H
301