1/**************************************************************************/
2/* animation_player.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 ANIMATION_PLAYER_H
32#define ANIMATION_PLAYER_H
33
34#include "scene/2d/node_2d.h"
35#include "scene/3d/mesh_instance_3d.h"
36#include "scene/3d/node_3d.h"
37#include "scene/3d/skeleton_3d.h"
38#include "scene/resources/animation.h"
39#include "scene/resources/animation_library.h"
40#include "scene/resources/audio_stream_polyphonic.h"
41
42#ifdef TOOLS_ENABLED
43class AnimatedValuesBackup : public RefCounted {
44 GDCLASS(AnimatedValuesBackup, RefCounted);
45
46 struct Entry {
47 Object *object = nullptr;
48 Vector<StringName> subpath; // Unused if bone
49 int bone_idx = -1; // -1 if not a bone
50 Variant value;
51 };
52 Vector<Entry> entries;
53
54 friend class AnimationPlayer;
55
56protected:
57 static void _bind_methods();
58
59public:
60 void update_skeletons();
61 void restore() const;
62};
63#endif
64
65class AnimationPlayer : public Node {
66 GDCLASS(AnimationPlayer, Node);
67
68public:
69 enum AnimationProcessCallback {
70 ANIMATION_PROCESS_PHYSICS,
71 ANIMATION_PROCESS_IDLE,
72 ANIMATION_PROCESS_MANUAL,
73 };
74
75 enum AnimationMethodCallMode {
76 ANIMATION_METHOD_CALL_DEFERRED,
77 ANIMATION_METHOD_CALL_IMMEDIATE,
78 };
79
80private:
81 enum {
82 NODE_CACHE_UPDATE_MAX = 1024,
83 BLEND_FROM_MAX = 3
84 };
85
86 enum SpecialProperty {
87 SP_NONE,
88 SP_NODE2D_POS,
89 SP_NODE2D_ROT,
90 SP_NODE2D_SCALE,
91 };
92
93 uint32_t setup_pass = 1;
94
95 struct TrackNodeCache {
96 NodePath path;
97 uint32_t id = 0;
98 Ref<Resource> resource;
99 Node *node = nullptr;
100 Node2D *node_2d = nullptr;
101#ifndef _3D_DISABLED
102 Node3D *node_3d = nullptr;
103 Skeleton3D *skeleton = nullptr;
104 MeshInstance3D *node_blend_shape = nullptr;
105 int blend_shape_idx = -1;
106#endif // _3D_DISABLED
107 int bone_idx = -1;
108 // accumulated transforms
109
110 bool loc_used = false;
111 bool rot_used = false;
112 bool scale_used = false;
113 Vector3 init_loc = Vector3(0, 0, 0);
114 Quaternion init_rot = Quaternion(0, 0, 0, 1);
115 Vector3 init_scale = Vector3(1, 1, 1);
116
117 Vector3 loc_accum;
118 Quaternion rot_accum;
119 Vector3 scale_accum;
120 float blend_shape_accum = 0;
121 uint64_t accum_pass = 0;
122
123 bool audio_playing = false;
124 float audio_start = 0.0;
125 float audio_len = 0.0;
126
127 bool animation_playing = false;
128
129 struct PropertyAnim {
130 TrackNodeCache *owner = nullptr;
131 SpecialProperty special = SP_NONE; //small optimization
132 Vector<StringName> subpath;
133 Object *object = nullptr;
134 Variant value_accum;
135 uint64_t accum_pass = 0;
136 Variant capture;
137 };
138
139 HashMap<StringName, PropertyAnim> property_anim;
140
141 struct BezierAnim {
142 Vector<StringName> bezier_property;
143 TrackNodeCache *owner = nullptr;
144 float bezier_accum = 0.0;
145 Object *object = nullptr;
146 uint64_t accum_pass = 0;
147 };
148
149 HashMap<StringName, BezierAnim> bezier_anim;
150
151 struct PlayingAudioStreamInfo {
152 AudioStreamPlaybackPolyphonic::ID index = -1;
153 double start = 0.0;
154 double len = 0.0;
155 };
156
157 struct AudioAnim {
158 Ref<AudioStreamPolyphonic> audio_stream;
159 Ref<AudioStreamPlaybackPolyphonic> audio_stream_playback;
160 HashMap<int, PlayingAudioStreamInfo> playing_streams;
161 Object *object = nullptr;
162 uint64_t accum_pass = 0;
163 double length = 0.0;
164 double time = 0.0;
165 bool loop = false;
166 bool backward = false;
167 };
168
169 HashMap<StringName, AudioAnim> audio_anim;
170
171 uint32_t last_setup_pass = 0;
172 TrackNodeCache() {}
173 };
174
175 struct TrackNodeCacheKey {
176 ObjectID id;
177 int bone_idx = -1;
178 int blend_shape_idx = -1;
179
180 static uint32_t hash(const TrackNodeCacheKey &p_key) {
181 uint32_t h = hash_one_uint64(p_key.id);
182 h = hash_murmur3_one_32(p_key.bone_idx, h);
183 return hash_fmix32(hash_murmur3_one_32(p_key.blend_shape_idx, h));
184 }
185
186 inline bool operator==(const TrackNodeCacheKey &p_right) const {
187 return id == p_right.id && bone_idx == p_right.bone_idx && blend_shape_idx == p_right.blend_shape_idx;
188 }
189
190 inline bool operator<(const TrackNodeCacheKey &p_right) const {
191 if (id == p_right.id) {
192 if (blend_shape_idx == p_right.blend_shape_idx) {
193 return bone_idx < p_right.bone_idx;
194 } else {
195 return blend_shape_idx < p_right.blend_shape_idx;
196 }
197 } else {
198 return id < p_right.id;
199 }
200 }
201 };
202
203 HashMap<TrackNodeCacheKey, TrackNodeCache, TrackNodeCacheKey> node_cache_map;
204
205 TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX];
206 int cache_update_size = 0;
207 TrackNodeCache::PropertyAnim *cache_update_prop[NODE_CACHE_UPDATE_MAX];
208 int cache_update_prop_size = 0;
209 TrackNodeCache::BezierAnim *cache_update_bezier[NODE_CACHE_UPDATE_MAX];
210 int cache_update_bezier_size = 0;
211 TrackNodeCache::AudioAnim *cache_update_audio[NODE_CACHE_UPDATE_MAX];
212 int cache_update_audio_size = 0;
213 HashSet<TrackNodeCache *> playing_caches;
214 Vector<Node *> playing_audio_stream_players;
215
216 uint64_t accum_pass = 1;
217 float speed_scale = 1.0;
218 double default_blend_time = 0.0;
219 bool is_stopping = false;
220
221 struct AnimationData {
222 String name;
223 StringName next;
224 Vector<TrackNodeCache *> node_cache;
225 Ref<Animation> animation;
226 StringName animation_library;
227 uint64_t last_update = 0;
228 };
229
230 HashMap<StringName, AnimationData> animation_set;
231
232 struct AnimationLibraryData {
233 StringName name;
234 Ref<AnimationLibrary> library;
235 bool operator<(const AnimationLibraryData &p_data) const { return name.operator String() < p_data.name.operator String(); }
236 };
237
238 LocalVector<AnimationLibraryData> animation_libraries;
239
240 struct BlendKey {
241 StringName from;
242 StringName to;
243 static uint32_t hash(const BlendKey &p_key) {
244 return hash_one_uint64((uint64_t(p_key.from.hash()) << 32) | uint32_t(p_key.to.hash()));
245 }
246 bool operator==(const BlendKey &bk) const {
247 return from == bk.from && to == bk.to;
248 }
249 bool operator<(const BlendKey &bk) const {
250 if (from == bk.from) {
251 return to < bk.to;
252 } else {
253 return from < bk.from;
254 }
255 }
256 };
257
258 HashMap<BlendKey, double, BlendKey> blend_times;
259
260 struct PlaybackData {
261 AnimationData *from = nullptr;
262 double pos = 0.0;
263 float speed_scale = 1.0;
264 };
265
266 struct Blend {
267 PlaybackData data;
268
269 double blend_time = 0.0;
270 double blend_left = 0.0;
271 };
272
273 struct Playback {
274 List<Blend> blend;
275 PlaybackData current;
276 StringName assigned;
277 bool seeked = false;
278 bool started = false;
279 } playback;
280
281 List<StringName> queued;
282
283 bool end_reached = false;
284 bool end_notify = false;
285
286 String autoplay;
287 bool reset_on_save = true;
288 AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE;
289 AnimationMethodCallMode method_call_mode = ANIMATION_METHOD_CALL_DEFERRED;
290 int audio_max_polyphony = 32;
291 bool movie_quit_on_finish = false;
292 bool processing = false;
293 bool active = true;
294
295 NodePath root;
296
297 void _animation_process_animation(AnimationData *p_anim, double p_prev_time, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE);
298
299 void _ensure_node_caches(AnimationData *p_anim, Node *p_root_override = nullptr);
300 void _animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started);
301 void _animation_process2(double p_delta, bool p_started);
302 void _animation_update_transforms();
303 void _animation_process(double p_delta);
304
305 void _node_removed(Node *p_node);
306 void _clear_audio_streams();
307 void _stop_playing_caches(bool p_reset);
308
309 // bind helpers
310 Vector<String> _get_animation_list() const {
311 List<StringName> animations;
312 get_animation_list(&animations);
313 Vector<String> ret;
314 while (animations.size()) {
315 ret.push_back(animations.front()->get());
316 animations.pop_front();
317 }
318 return ret;
319 }
320
321 void _animation_changed(const StringName &p_name);
322
323 void _set_process(bool p_process, bool p_force = false);
324 void _stop_internal(bool p_reset, bool p_keep_state);
325
326 bool playing = false;
327
328 uint64_t animation_set_update_pass = 1;
329 void _animation_set_cache_update();
330 void _animation_added(const StringName &p_name, const StringName &p_library);
331 void _animation_removed(const StringName &p_name, const StringName &p_library);
332 void _animation_renamed(const StringName &p_name, const StringName &p_to_name, const StringName &p_library);
333 void _rename_animation(const StringName &p_from_name, const StringName &p_to_name);
334
335 TypedArray<StringName> _get_animation_library_list() const;
336
337protected:
338 bool _set(const StringName &p_name, const Variant &p_value);
339 bool _get(const StringName &p_name, Variant &r_ret) const;
340 void _validate_property(PropertyInfo &p_property) const;
341 void _get_property_list(List<PropertyInfo> *p_list) const;
342 void _notification(int p_what);
343
344 static void _bind_methods();
345
346 GDVIRTUAL5RC(Variant, _post_process_key_value, Ref<Animation>, int, Variant, Object *, int);
347 Variant post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1);
348 virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1);
349
350public:
351 StringName find_animation(const Ref<Animation> &p_animation) const;
352 StringName find_animation_library(const Ref<Animation> &p_animation) const;
353
354 Error add_animation_library(const StringName &p_name, const Ref<AnimationLibrary> &p_animation_library);
355 void remove_animation_library(const StringName &p_name);
356 void rename_animation_library(const StringName &p_name, const StringName &p_new_name);
357 Ref<AnimationLibrary> get_animation_library(const StringName &p_name) const;
358 void get_animation_library_list(List<StringName> *p_animations) const;
359 bool has_animation_library(const StringName &p_name) const;
360
361 Ref<Animation> get_animation(const StringName &p_name) const;
362 void get_animation_list(List<StringName> *p_animations) const;
363 bool has_animation(const StringName &p_name) const;
364
365 void set_blend_time(const StringName &p_animation1, const StringName &p_animation2, double p_time);
366 double get_blend_time(const StringName &p_animation1, const StringName &p_animation2) const;
367
368 void animation_set_next(const StringName &p_animation, const StringName &p_next);
369 StringName animation_get_next(const StringName &p_animation) const;
370
371 void set_default_blend_time(double p_default);
372 double get_default_blend_time() const;
373
374 void play(const StringName &p_name = StringName(), double p_custom_blend = -1, float p_custom_scale = 1.0, bool p_from_end = false);
375 void play_backwards(const StringName &p_name = StringName(), double p_custom_blend = -1);
376 void queue(const StringName &p_name);
377 Vector<String> get_queue();
378 void clear_queue();
379 void pause();
380 void stop(bool p_keep_state = false);
381 bool is_playing() const;
382 String get_current_animation() const;
383 void set_current_animation(const String &p_anim);
384 String get_assigned_animation() const;
385 void set_assigned_animation(const String &p_anim);
386 void set_active(bool p_active);
387 bool is_active() const;
388 bool is_valid() const;
389
390 void set_speed_scale(float p_speed);
391 float get_speed_scale() const;
392 float get_playing_speed() const;
393
394 void set_autoplay(const String &p_name);
395 String get_autoplay() const;
396
397 void set_reset_on_save_enabled(bool p_enabled);
398 bool is_reset_on_save_enabled() const;
399
400 void set_process_callback(AnimationProcessCallback p_mode);
401 AnimationProcessCallback get_process_callback() const;
402
403 void set_method_call_mode(AnimationMethodCallMode p_mode);
404 AnimationMethodCallMode get_method_call_mode() const;
405
406 void set_audio_max_polyphony(int p_audio_max_polyphony);
407 int get_audio_max_polyphony() const;
408
409 void set_movie_quit_on_finish_enabled(bool p_enabled);
410 bool is_movie_quit_on_finish_enabled() const;
411
412 void seek(double p_time, bool p_update = false);
413 void seek_delta(double p_time, double p_delta);
414 double get_current_animation_position() const;
415 double get_current_animation_length() const;
416
417 void advance(double p_time);
418
419 void set_root(const NodePath &p_root);
420 NodePath get_root() const;
421
422 void clear_caches(); ///< must be called by hand if an animation was modified after added
423
424 void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
425
426#ifdef TOOLS_ENABLED
427 Ref<AnimatedValuesBackup> backup_animated_values(Node *p_root_override = nullptr);
428 Ref<AnimatedValuesBackup> apply_reset(bool p_user_initiated = false);
429 bool can_apply_reset() const;
430#endif
431
432 AnimationPlayer();
433 ~AnimationPlayer();
434};
435
436VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessCallback);
437VARIANT_ENUM_CAST(AnimationPlayer::AnimationMethodCallMode);
438
439#endif // ANIMATION_PLAYER_H
440