Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/animation/animation_mixer.cpp
9896 views
1
/**************************************************************************/
2
/* animation_mixer.cpp */
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
#include "animation_mixer.h"
32
#include "animation_mixer.compat.inc"
33
34
#include "core/config/engine.h"
35
#include "core/config/project_settings.h"
36
#include "core/string/string_name.h"
37
#include "scene/2d/audio_stream_player_2d.h"
38
#include "scene/animation/animation_player.h"
39
#include "scene/audio/audio_stream_player.h"
40
#include "scene/resources/animation.h"
41
#include "servers/audio/audio_stream.h"
42
#include "servers/audio_server.h"
43
44
#ifndef _3D_DISABLED
45
#include "scene/3d/audio_stream_player_3d.h"
46
#include "scene/3d/mesh_instance_3d.h"
47
#include "scene/3d/node_3d.h"
48
#include "scene/3d/skeleton_3d.h"
49
#endif // _3D_DISABLED
50
51
#ifdef TOOLS_ENABLED
52
#include "editor/editor_undo_redo_manager.h"
53
#endif // TOOLS_ENABLED
54
55
bool AnimationMixer::_set(const StringName &p_name, const Variant &p_value) {
56
String name = p_name;
57
58
#ifndef DISABLE_DEPRECATED
59
if (name.begins_with("anims/")) {
60
// Backwards compatibility with 3.x, add them to "default" library.
61
String which = name.get_slicec('/', 1);
62
63
Ref<Animation> anim = p_value;
64
Ref<AnimationLibrary> al;
65
if (!has_animation_library(StringName())) {
66
al.instantiate();
67
add_animation_library(StringName(), al);
68
} else {
69
al = get_animation_library(StringName());
70
}
71
al->add_animation(which, anim);
72
} else if (name.begins_with("libraries")) {
73
#else
74
if (name.begins_with("libraries")) {
75
#endif // DISABLE_DEPRECATED
76
Dictionary d = p_value;
77
while (animation_libraries.size()) {
78
remove_animation_library(animation_libraries[0].name);
79
}
80
for (const KeyValue<Variant, Variant> &kv : d) {
81
Ref<AnimationLibrary> lib = kv.value;
82
add_animation_library(kv.key, lib);
83
}
84
emit_signal(SNAME("animation_libraries_updated"));
85
86
} else {
87
return false;
88
}
89
90
return true;
91
}
92
93
bool AnimationMixer::_get(const StringName &p_name, Variant &r_ret) const {
94
String name = p_name;
95
96
if (name.begins_with("libraries")) {
97
Dictionary d;
98
for (const AnimationLibraryData &lib : animation_libraries) {
99
d[lib.name] = lib.library;
100
}
101
r_ret = d;
102
} else {
103
return false;
104
}
105
106
return true;
107
}
108
109
void AnimationMixer::_get_property_list(List<PropertyInfo> *p_list) const {
110
p_list->push_back(PropertyInfo(Variant::DICTIONARY, PNAME("libraries"), PROPERTY_HINT_DICTIONARY_TYPE, "StringName;AnimationLibrary"));
111
}
112
113
void AnimationMixer::_validate_property(PropertyInfo &p_property) const {
114
#ifdef TOOLS_ENABLED // `editing` is surrounded by TOOLS_ENABLED so this should also be.
115
if (Engine::get_singleton()->is_editor_hint() && editing && (p_property.name == "active" || p_property.name == "deterministic" || p_property.name == "root_motion_track")) {
116
p_property.usage |= PROPERTY_USAGE_READ_ONLY;
117
}
118
#endif // TOOLS_ENABLED
119
if (root_motion_track.is_empty() && p_property.name == "root_motion_local") {
120
p_property.usage = PROPERTY_USAGE_NONE;
121
}
122
}
123
124
/* -------------------------------------------- */
125
/* -- Data lists ------------------------------ */
126
/* -------------------------------------------- */
127
128
void AnimationMixer::_animation_set_cache_update() {
129
// Relatively fast function to update all animations.
130
animation_set_update_pass++;
131
bool clear_cache_needed = false;
132
133
// Update changed and add otherwise.
134
for (const AnimationLibraryData &lib : animation_libraries) {
135
for (const KeyValue<StringName, Ref<Animation>> &K : lib.library->animations) {
136
StringName key = lib.name == StringName() ? K.key : StringName(String(lib.name) + "/" + String(K.key));
137
if (!animation_set.has(key)) {
138
AnimationData ad;
139
ad.animation = K.value;
140
ad.animation_library = lib.name;
141
ad.name = key;
142
ad.last_update = animation_set_update_pass;
143
animation_set.insert(ad.name, ad);
144
cache_valid = false; // No need to delete the cache, but it must be updated to add track caches.
145
} else {
146
AnimationData &ad = animation_set[key];
147
if (ad.last_update != animation_set_update_pass) {
148
// Was not updated, update. If the animation is duplicated, the second one will be ignored.
149
if (ad.animation != K.value || ad.animation_library != lib.name) {
150
// Animation changed, update and clear caches.
151
clear_cache_needed = true;
152
ad.animation = K.value;
153
ad.animation_library = lib.name;
154
}
155
156
ad.last_update = animation_set_update_pass;
157
}
158
}
159
}
160
}
161
162
// Check removed.
163
List<StringName> to_erase;
164
for (const KeyValue<StringName, AnimationData> &E : animation_set) {
165
if (E.value.last_update != animation_set_update_pass) {
166
// Was not updated, must be erased.
167
to_erase.push_back(E.key);
168
clear_cache_needed = true;
169
}
170
}
171
172
while (to_erase.size()) {
173
animation_set.erase(to_erase.front()->get());
174
to_erase.pop_front();
175
}
176
177
if (clear_cache_needed) {
178
// If something was modified or removed, caches need to be cleared.
179
_clear_caches();
180
}
181
182
emit_signal(SNAME("animation_list_changed"));
183
}
184
185
void AnimationMixer::_animation_added(const StringName &p_name, const StringName &p_library) {
186
_animation_set_cache_update();
187
}
188
189
void AnimationMixer::_animation_removed(const StringName &p_name, const StringName &p_library) {
190
StringName name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name));
191
192
if (!animation_set.has(name)) {
193
return; // No need to update because not the one from the library being used.
194
}
195
196
_animation_set_cache_update();
197
198
_remove_animation(name);
199
}
200
201
void AnimationMixer::_animation_renamed(const StringName &p_name, const StringName &p_to_name, const StringName &p_library) {
202
StringName from_name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name));
203
StringName to_name = p_library == StringName() ? p_to_name : StringName(String(p_library) + "/" + String(p_to_name));
204
205
if (!animation_set.has(from_name)) {
206
return; // No need to update because not the one from the library being used.
207
}
208
_animation_set_cache_update();
209
210
_rename_animation(from_name, to_name);
211
}
212
213
void AnimationMixer::_animation_changed(const StringName &p_name) {
214
_clear_caches();
215
}
216
217
void AnimationMixer::_set_active(bool p_active) {
218
//
219
}
220
221
void AnimationMixer::_remove_animation(const StringName &p_name) {
222
//
223
}
224
225
void AnimationMixer::_rename_animation(const StringName &p_from_name, const StringName &p_to_name) {
226
//
227
}
228
229
TypedArray<StringName> AnimationMixer::_get_animation_library_list() const {
230
TypedArray<StringName> ret;
231
for (const AnimationLibraryData &lib : animation_libraries) {
232
ret.push_back(lib.name);
233
}
234
return ret;
235
}
236
237
void AnimationMixer::get_animation_library_list(List<StringName> *p_libraries) const {
238
for (const AnimationLibraryData &lib : animation_libraries) {
239
p_libraries->push_back(lib.name);
240
}
241
}
242
243
Ref<AnimationLibrary> AnimationMixer::get_animation_library(const StringName &p_name) const {
244
for (const AnimationLibraryData &lib : animation_libraries) {
245
if (lib.name == p_name) {
246
return lib.library;
247
}
248
}
249
ERR_FAIL_V(Ref<AnimationLibrary>());
250
}
251
252
bool AnimationMixer::has_animation_library(const StringName &p_name) const {
253
for (const AnimationLibraryData &lib : animation_libraries) {
254
if (lib.name == p_name) {
255
return true;
256
}
257
}
258
259
return false;
260
}
261
262
StringName AnimationMixer::get_animation_library_name(const Ref<AnimationLibrary> &p_animation_library) const {
263
ERR_FAIL_COND_V(p_animation_library.is_null(), StringName());
264
for (const AnimationLibraryData &lib : animation_libraries) {
265
if (lib.library == p_animation_library) {
266
return lib.name;
267
}
268
}
269
return StringName();
270
}
271
272
StringName AnimationMixer::find_animation_library(const Ref<Animation> &p_animation) const {
273
for (const KeyValue<StringName, AnimationData> &E : animation_set) {
274
if (E.value.animation == p_animation) {
275
return E.value.animation_library;
276
}
277
}
278
return StringName();
279
}
280
281
Error AnimationMixer::add_animation_library(const StringName &p_name, const Ref<AnimationLibrary> &p_animation_library) {
282
ERR_FAIL_COND_V(p_animation_library.is_null(), ERR_INVALID_PARAMETER);
283
#ifdef DEBUG_ENABLED
284
ERR_FAIL_COND_V_MSG(String(p_name).contains_char('/') || String(p_name).contains_char(':') || String(p_name).contains_char(',') || String(p_name).contains_char('['), ERR_INVALID_PARAMETER, "Invalid animation name: " + String(p_name) + ".");
285
#endif
286
287
int insert_pos = 0;
288
289
for (const AnimationLibraryData &lib : animation_libraries) {
290
ERR_FAIL_COND_V_MSG(lib.name == p_name, ERR_ALREADY_EXISTS, "Can't add animation library twice with name: " + String(p_name));
291
ERR_FAIL_COND_V_MSG(lib.library == p_animation_library, ERR_ALREADY_EXISTS, "Can't add animation library twice (adding as '" + p_name.operator String() + "', exists as '" + lib.name.operator String() + "'.");
292
293
if (lib.name.operator String() >= p_name.operator String()) {
294
break;
295
}
296
297
insert_pos++;
298
}
299
300
AnimationLibraryData ald;
301
ald.name = p_name;
302
ald.library = p_animation_library;
303
304
animation_libraries.insert(insert_pos, ald);
305
306
ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationMixer::_animation_added).bind(p_name));
307
ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationMixer::_animation_removed).bind(p_name));
308
ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationMixer::_animation_renamed).bind(p_name));
309
ald.library->connect(SceneStringName(animation_changed), callable_mp(this, &AnimationMixer::_animation_changed));
310
311
_animation_set_cache_update();
312
313
notify_property_list_changed();
314
315
return OK;
316
}
317
318
void AnimationMixer::remove_animation_library(const StringName &p_name) {
319
int at_pos = -1;
320
321
for (uint32_t i = 0; i < animation_libraries.size(); i++) {
322
if (animation_libraries[i].name == p_name) {
323
at_pos = i;
324
break;
325
}
326
}
327
328
ERR_FAIL_COND(at_pos == -1);
329
330
animation_libraries[at_pos].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationMixer::_animation_added));
331
animation_libraries[at_pos].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationMixer::_animation_removed));
332
animation_libraries[at_pos].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationMixer::_animation_renamed));
333
animation_libraries[at_pos].library->disconnect(SceneStringName(animation_changed), callable_mp(this, &AnimationMixer::_animation_changed));
334
335
animation_libraries.remove_at(at_pos);
336
_animation_set_cache_update();
337
338
notify_property_list_changed();
339
}
340
341
void AnimationMixer::rename_animation_library(const StringName &p_name, const StringName &p_new_name) {
342
if (p_name == p_new_name) {
343
return;
344
}
345
#ifdef DEBUG_ENABLED
346
ERR_FAIL_COND_MSG(String(p_new_name).contains_char('/') || String(p_new_name).contains_char(':') || String(p_new_name).contains_char(',') || String(p_new_name).contains_char('['), "Invalid animation library name: " + String(p_new_name) + ".");
347
#endif
348
349
bool found = false;
350
for (AnimationLibraryData &lib : animation_libraries) {
351
ERR_FAIL_COND_MSG(lib.name == p_new_name, "Can't rename animation library to another existing name: " + String(p_new_name) + ".");
352
if (lib.name == p_name) {
353
found = true;
354
lib.name = p_new_name;
355
// rename connections
356
lib.library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationMixer::_animation_added));
357
lib.library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationMixer::_animation_removed));
358
lib.library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationMixer::_animation_renamed));
359
360
lib.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationMixer::_animation_added).bind(p_new_name));
361
lib.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationMixer::_animation_removed).bind(p_new_name));
362
lib.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationMixer::_animation_renamed).bind(p_new_name));
363
364
for (const KeyValue<StringName, Ref<Animation>> &K : lib.library->animations) {
365
StringName old_name = p_name == StringName() ? K.key : StringName(String(p_name) + "/" + String(K.key));
366
StringName new_name = p_new_name == StringName() ? K.key : StringName(String(p_new_name) + "/" + String(K.key));
367
_rename_animation(old_name, new_name);
368
}
369
}
370
}
371
372
ERR_FAIL_COND(!found);
373
374
animation_libraries.sort(); // Must keep alphabetical order.
375
376
_animation_set_cache_update(); // Update cache.
377
378
notify_property_list_changed();
379
}
380
381
void AnimationMixer::get_animation_list(List<StringName> *p_animations) const {
382
List<String> anims;
383
for (const KeyValue<StringName, AnimationData> &E : animation_set) {
384
anims.push_back(E.key);
385
}
386
anims.sort();
387
for (const String &E : anims) {
388
p_animations->push_back(E);
389
}
390
}
391
392
Ref<Animation> AnimationMixer::get_animation(const StringName &p_name) const {
393
ERR_FAIL_COND_V_MSG(!animation_set.has(p_name), Ref<Animation>(), vformat("Animation not found: \"%s\".", p_name));
394
const AnimationData &anim_data = animation_set[p_name];
395
return anim_data.animation;
396
}
397
398
bool AnimationMixer::has_animation(const StringName &p_name) const {
399
return animation_set.has(p_name);
400
}
401
402
StringName AnimationMixer::find_animation(const Ref<Animation> &p_animation) const {
403
for (const KeyValue<StringName, AnimationData> &E : animation_set) {
404
if (E.value.animation == p_animation) {
405
return E.key;
406
}
407
}
408
return StringName();
409
}
410
411
/* -------------------------------------------- */
412
/* -- General settings for animation ---------- */
413
/* -------------------------------------------- */
414
415
void AnimationMixer::_set_process(bool p_process, bool p_force) {
416
if (processing == p_process && !p_force) {
417
return;
418
}
419
420
switch (callback_mode_process) {
421
case ANIMATION_CALLBACK_MODE_PROCESS_PHYSICS:
422
#ifdef TOOLS_ENABLED
423
set_physics_process_internal(p_process && active && !editing);
424
#else
425
set_physics_process_internal(p_process && active);
426
#endif // TOOLS_ENABLED
427
break;
428
case ANIMATION_CALLBACK_MODE_PROCESS_IDLE:
429
#ifdef TOOLS_ENABLED
430
set_process_internal(p_process && active && !editing);
431
#else
432
set_process_internal(p_process && active);
433
#endif // TOOLS_ENABLED
434
break;
435
case ANIMATION_CALLBACK_MODE_PROCESS_MANUAL:
436
break;
437
}
438
439
processing = p_process;
440
}
441
442
void AnimationMixer::set_active(bool p_active) {
443
if (active == p_active) {
444
return;
445
}
446
447
active = p_active;
448
_set_active(active);
449
_set_process(processing, true);
450
451
if (!active && is_inside_tree()) {
452
_clear_caches();
453
}
454
}
455
456
bool AnimationMixer::is_active() const {
457
return active;
458
}
459
460
void AnimationMixer::set_root_node(const NodePath &p_path) {
461
root_node = p_path;
462
_clear_caches();
463
}
464
465
NodePath AnimationMixer::get_root_node() const {
466
return root_node;
467
}
468
469
void AnimationMixer::set_deterministic(bool p_deterministic) {
470
deterministic = p_deterministic;
471
_clear_caches();
472
}
473
474
bool AnimationMixer::is_deterministic() const {
475
return deterministic;
476
}
477
478
void AnimationMixer::set_callback_mode_process(AnimationCallbackModeProcess p_mode) {
479
if (callback_mode_process == p_mode) {
480
return;
481
}
482
483
bool was_active = is_active();
484
if (was_active) {
485
set_active(false);
486
}
487
488
callback_mode_process = p_mode;
489
490
if (was_active) {
491
set_active(true);
492
}
493
}
494
495
AnimationMixer::AnimationCallbackModeProcess AnimationMixer::get_callback_mode_process() const {
496
return callback_mode_process;
497
}
498
499
void AnimationMixer::set_callback_mode_method(AnimationCallbackModeMethod p_mode) {
500
callback_mode_method = p_mode;
501
emit_signal(SNAME("mixer_updated"));
502
}
503
504
AnimationMixer::AnimationCallbackModeMethod AnimationMixer::get_callback_mode_method() const {
505
return callback_mode_method;
506
}
507
508
void AnimationMixer::set_callback_mode_discrete(AnimationCallbackModeDiscrete p_mode) {
509
callback_mode_discrete = p_mode;
510
_clear_caches();
511
emit_signal(SNAME("mixer_updated"));
512
}
513
514
AnimationMixer::AnimationCallbackModeDiscrete AnimationMixer::get_callback_mode_discrete() const {
515
return callback_mode_discrete;
516
}
517
518
void AnimationMixer::set_audio_max_polyphony(int p_audio_max_polyphony) {
519
ERR_FAIL_COND(p_audio_max_polyphony < 0 || p_audio_max_polyphony > 128);
520
audio_max_polyphony = p_audio_max_polyphony;
521
}
522
523
int AnimationMixer::get_audio_max_polyphony() const {
524
return audio_max_polyphony;
525
}
526
527
#ifdef TOOLS_ENABLED
528
void AnimationMixer::set_editing(bool p_editing) {
529
if (editing == p_editing) {
530
return;
531
}
532
533
editing = p_editing;
534
_set_process(processing, true);
535
536
if (editing && is_inside_tree()) {
537
_clear_caches();
538
}
539
540
notify_property_list_changed(); // To make active readonly.
541
}
542
543
bool AnimationMixer::is_editing() const {
544
return editing;
545
}
546
547
void AnimationMixer::set_dummy(bool p_dummy) {
548
dummy = p_dummy;
549
}
550
551
bool AnimationMixer::is_dummy() const {
552
return dummy;
553
}
554
#endif // TOOLS_ENABLED
555
556
/* -------------------------------------------- */
557
/* -- Caches for blending --------------------- */
558
/* -------------------------------------------- */
559
560
void AnimationMixer::_clear_caches() {
561
_init_root_motion_cache();
562
_clear_audio_streams();
563
_clear_playing_caches();
564
for (KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) {
565
memdelete(K.value);
566
}
567
track_cache.clear();
568
animation_track_num_to_track_cache.clear();
569
cache_valid = false;
570
capture_cache.clear();
571
572
emit_signal(SNAME("caches_cleared"));
573
}
574
575
void AnimationMixer::_clear_audio_streams() {
576
for (int i = 0; i < playing_audio_stream_players.size(); i++) {
577
playing_audio_stream_players[i]->call(SNAME("stop"));
578
playing_audio_stream_players[i]->call(SNAME("set_stream"), Ref<AudioStream>());
579
}
580
playing_audio_stream_players.clear();
581
}
582
583
void AnimationMixer::_clear_playing_caches() {
584
for (const TrackCache *E : playing_caches) {
585
Object *t_obj = ObjectDB::get_instance(E->object_id);
586
if (t_obj) {
587
t_obj->call(SNAME("stop"), true);
588
}
589
}
590
playing_caches.clear();
591
}
592
593
void AnimationMixer::_init_root_motion_cache() {
594
root_motion_cache.loc = Vector3(0, 0, 0);
595
root_motion_cache.rot = Quaternion(0, 0, 0, 1);
596
root_motion_cache.scale = Vector3(1, 1, 1);
597
root_motion_position = Vector3(0, 0, 0);
598
root_motion_rotation = Quaternion(0, 0, 0, 1);
599
root_motion_scale = Vector3(0, 0, 0);
600
root_motion_position_accumulator = Vector3(0, 0, 0);
601
root_motion_rotation_accumulator = Quaternion(0, 0, 0, 1);
602
root_motion_scale_accumulator = Vector3(1, 1, 1);
603
}
604
605
void AnimationMixer::_create_track_num_to_track_cache_for_animation(Ref<Animation> &p_animation) {
606
if (animation_track_num_to_track_cache.has(p_animation)) {
607
// In AnimationMixer::_update_caches, it retrieves all animations via AnimationMixer::get_animation_list
608
// Since multiple AnimationLibraries can share the same Animation, it is possible that the cache is already created.
609
return;
610
}
611
LocalVector<TrackCache *> &track_num_to_track_cache = animation_track_num_to_track_cache.insert_new(p_animation, LocalVector<TrackCache *>())->value;
612
const Vector<Animation::Track *> &tracks = p_animation->get_tracks();
613
614
track_num_to_track_cache.resize(tracks.size());
615
for (int i = 0; i < tracks.size(); i++) {
616
TrackCache **track_ptr = track_cache.getptr(tracks[i]->thash);
617
if (track_ptr == nullptr) {
618
track_num_to_track_cache[i] = nullptr;
619
} else {
620
track_num_to_track_cache[i] = *track_ptr;
621
}
622
}
623
}
624
625
bool AnimationMixer::_update_caches() {
626
setup_pass++;
627
628
root_motion_cache.loc = Vector3(0, 0, 0);
629
root_motion_cache.rot = Quaternion(0, 0, 0, 1);
630
root_motion_cache.scale = Vector3(1, 1, 1);
631
632
List<StringName> sname_list;
633
get_animation_list(&sname_list);
634
635
bool check_path = GLOBAL_GET_CACHED(bool, "animation/warnings/check_invalid_track_paths");
636
bool check_angle_interpolation = GLOBAL_GET_CACHED(bool, "animation/warnings/check_angle_interpolation_type_conflicting");
637
638
Node *parent = get_node_or_null(root_node);
639
if (!parent) {
640
cache_valid = false;
641
return false;
642
}
643
644
#ifdef TOOLS_ENABLED
645
String mixer_name = "AnimationMixer";
646
const Node *owner = get_owner();
647
if (owner) {
648
const String scene_path = owner->get_scene_file_path();
649
if (!scene_path.is_empty()) {
650
mixer_name += vformat(" (at: %s)", scene_path.get_file());
651
}
652
}
653
#else
654
const String mixer_name = "AnimationMixer";
655
#endif
656
657
Ref<Animation> reset_anim;
658
bool has_reset_anim = has_animation(SceneStringName(RESET));
659
if (has_reset_anim) {
660
reset_anim = get_animation(SceneStringName(RESET));
661
}
662
for (const StringName &E : sname_list) {
663
Ref<Animation> anim = get_animation(E);
664
for (int i = 0; i < anim->get_track_count(); i++) {
665
NodePath path = anim->track_get_path(i);
666
Animation::TypeHash thash = anim->track_get_type_hash(i);
667
Animation::TrackType track_src_type = anim->track_get_type(i);
668
Animation::TrackType track_cache_type = Animation::get_cache_type(track_src_type);
669
670
TrackCache *track = nullptr;
671
if (track_cache.has(thash)) {
672
track = track_cache.get(thash);
673
}
674
675
// If not valid, delete track.
676
if (track && (track->type != track_cache_type || ObjectDB::get_instance(track->object_id) == nullptr)) {
677
playing_caches.erase(track);
678
memdelete(track);
679
track_cache.erase(thash);
680
track = nullptr;
681
}
682
683
if (!track) {
684
Ref<Resource> resource;
685
Vector<StringName> leftover_path;
686
687
Node *child = parent->get_node_and_resource(path, resource, leftover_path);
688
if (!child) {
689
if (check_path) {
690
WARN_PRINT_ED(mixer_name + ": '" + String(E) + "', couldn't resolve track: '" + String(path) + "'. This warning can be disabled in Project Settings.");
691
}
692
continue;
693
}
694
695
switch (track_src_type) {
696
case Animation::TYPE_BEZIER:
697
case Animation::TYPE_VALUE: {
698
// If a value track without a key is cached first, the initial value cannot be determined.
699
// It is a corner case, but which may cause problems with blending.
700
ERR_CONTINUE_MSG(anim->track_get_key_count(i) == 0, mixer_name + ": '" + String(E) + "', Value Track: '" + String(path) + "' must have at least one key to cache for blending.");
701
702
TrackCacheValue *track_value = memnew(TrackCacheValue);
703
704
if (resource.is_valid()) {
705
track_value->object_id = resource->get_instance_id();
706
} else {
707
track_value->object_id = child->get_instance_id();
708
}
709
710
track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE;
711
712
track_value->subpath = leftover_path;
713
714
track = track_value;
715
716
bool is_value = track_src_type == Animation::TYPE_VALUE;
717
718
track_value->init_value = is_value ? anim->track_get_key_value(i, 0) : (anim->track_get_key_value(i, 0).operator Array())[0];
719
track_value->init_value.zero();
720
721
track_value->is_init = false;
722
723
// Can't interpolate them, need to convert.
724
track_value->is_variant_interpolatable = Animation::is_variant_interpolatable(track_value->init_value);
725
726
// If there is a Reset Animation, it takes precedence by overwriting.
727
if (has_reset_anim) {
728
int rt = reset_anim->find_track(path, track_src_type);
729
if (rt >= 0) {
730
if (is_value) {
731
if (reset_anim->track_get_key_count(rt) > 0) {
732
track_value->init_value = reset_anim->track_get_key_value(rt, 0);
733
}
734
} else {
735
if (reset_anim->track_get_key_count(rt) > 0) {
736
track_value->init_value = (reset_anim->track_get_key_value(rt, 0).operator Array())[0];
737
}
738
}
739
}
740
}
741
742
if (is_value && callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS) {
743
if (child) {
744
PropertyInfo prop_info;
745
ClassDB::get_property_info(child->get_class_name(), path.get_concatenated_subnames(), &prop_info);
746
if (prop_info.hint == PROPERTY_HINT_ONESHOT) {
747
WARN_PRINT_ED(vformat("%s: '%s', Value Track: '%s' is oneshot property, but will be continuously updated. Consider setting a value other than ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS to AnimationMixer.callback_mode_dominant.", mixer_name, String(E), String(path)));
748
}
749
}
750
}
751
} break;
752
case Animation::TYPE_POSITION_3D:
753
case Animation::TYPE_ROTATION_3D:
754
case Animation::TYPE_SCALE_3D: {
755
#ifndef _3D_DISABLED
756
Node3D *node_3d = Object::cast_to<Node3D>(child);
757
758
if (!node_3d) {
759
ERR_PRINT(mixer_name + ": '" + String(E) + "', transform track does not point to Node3D: '" + String(path) + "'.");
760
continue;
761
}
762
763
TrackCacheTransform *track_xform = memnew(TrackCacheTransform);
764
track_xform->type = Animation::TYPE_POSITION_3D;
765
766
track_xform->bone_idx = -1;
767
768
bool has_rest = false;
769
Skeleton3D *sk = Object::cast_to<Skeleton3D>(node_3d);
770
if (sk && path.get_subname_count() == 1) {
771
track_xform->skeleton_id = sk->get_instance_id();
772
int bone_idx = sk->find_bone(path.get_subname(0));
773
if (bone_idx != -1) {
774
has_rest = true;
775
track_xform->bone_idx = bone_idx;
776
Transform3D rest = sk->get_bone_rest(bone_idx);
777
track_xform->init_loc = rest.origin;
778
track_xform->init_rot = rest.basis.get_rotation_quaternion();
779
track_xform->init_scale = rest.basis.get_scale();
780
}
781
}
782
783
track_xform->object_id = node_3d->get_instance_id();
784
785
track = track_xform;
786
787
switch (track_src_type) {
788
case Animation::TYPE_POSITION_3D: {
789
track_xform->loc_used = true;
790
} break;
791
case Animation::TYPE_ROTATION_3D: {
792
track_xform->rot_used = true;
793
} break;
794
case Animation::TYPE_SCALE_3D: {
795
track_xform->scale_used = true;
796
} break;
797
default: {
798
}
799
}
800
801
// For non Skeleton3D bone animation.
802
if (has_reset_anim && !has_rest) {
803
int rt = reset_anim->find_track(path, track_src_type);
804
if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
805
switch (track_src_type) {
806
case Animation::TYPE_POSITION_3D: {
807
track_xform->init_loc = reset_anim->track_get_key_value(rt, 0);
808
} break;
809
case Animation::TYPE_ROTATION_3D: {
810
track_xform->init_rot = reset_anim->track_get_key_value(rt, 0);
811
} break;
812
case Animation::TYPE_SCALE_3D: {
813
track_xform->init_scale = reset_anim->track_get_key_value(rt, 0);
814
} break;
815
default: {
816
}
817
}
818
}
819
}
820
#endif // _3D_DISABLED
821
} break;
822
case Animation::TYPE_BLEND_SHAPE: {
823
#ifndef _3D_DISABLED
824
if (path.get_subname_count() != 1) {
825
ERR_PRINT(mixer_name + ": '" + String(E) + "', blend shape track does not contain a blend shape subname: '" + String(path) + "'.");
826
continue;
827
}
828
MeshInstance3D *mesh_3d = Object::cast_to<MeshInstance3D>(child);
829
830
if (!mesh_3d) {
831
ERR_PRINT(mixer_name + ": '" + String(E) + "', blend shape track does not point to MeshInstance3D: '" + String(path) + "'.");
832
continue;
833
}
834
835
StringName blend_shape_name = path.get_subname(0);
836
int blend_shape_idx = mesh_3d->find_blend_shape_by_name(blend_shape_name);
837
if (blend_shape_idx == -1) {
838
ERR_PRINT(mixer_name + ": '" + String(E) + "', blend shape track points to a non-existing name: '" + String(blend_shape_name) + "'.");
839
continue;
840
}
841
842
TrackCacheBlendShape *track_bshape = memnew(TrackCacheBlendShape);
843
844
track_bshape->shape_index = blend_shape_idx;
845
track_bshape->object_id = mesh_3d->get_instance_id();
846
track = track_bshape;
847
848
if (has_reset_anim) {
849
int rt = reset_anim->find_track(path, track_src_type);
850
if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
851
track_bshape->init_value = reset_anim->track_get_key_value(rt, 0);
852
}
853
}
854
#endif
855
} break;
856
case Animation::TYPE_METHOD: {
857
TrackCacheMethod *track_method = memnew(TrackCacheMethod);
858
859
if (resource.is_valid()) {
860
track_method->object_id = resource->get_instance_id();
861
} else {
862
track_method->object_id = child->get_instance_id();
863
}
864
865
track = track_method;
866
867
} break;
868
case Animation::TYPE_AUDIO: {
869
TrackCacheAudio *track_audio = memnew(TrackCacheAudio);
870
871
track_audio->object_id = child->get_instance_id();
872
track_audio->audio_stream.instantiate();
873
track_audio->audio_stream->set_polyphony(audio_max_polyphony);
874
track_audio->playback_type = (AudioServer::PlaybackType)(int)(child->call(SNAME("get_playback_type")));
875
track_audio->bus = (StringName)(child->call(SNAME("get_bus")));
876
877
track = track_audio;
878
879
} break;
880
case Animation::TYPE_ANIMATION: {
881
TrackCacheAnimation *track_animation = memnew(TrackCacheAnimation);
882
883
track_animation->object_id = child->get_instance_id();
884
885
track = track_animation;
886
887
} break;
888
default: {
889
ERR_PRINT("Animation corrupted (invalid track type).");
890
continue;
891
}
892
}
893
track->path = path;
894
track_cache[thash] = track;
895
} else if (track_cache_type == Animation::TYPE_POSITION_3D) {
896
TrackCacheTransform *track_xform = static_cast<TrackCacheTransform *>(track);
897
if (track->setup_pass != setup_pass) {
898
track_xform->loc_used = false;
899
track_xform->rot_used = false;
900
track_xform->scale_used = false;
901
}
902
switch (track_src_type) {
903
case Animation::TYPE_POSITION_3D: {
904
track_xform->loc_used = true;
905
} break;
906
case Animation::TYPE_ROTATION_3D: {
907
track_xform->rot_used = true;
908
} break;
909
case Animation::TYPE_SCALE_3D: {
910
track_xform->scale_used = true;
911
} break;
912
default: {
913
}
914
}
915
} else if (track_cache_type == Animation::TYPE_VALUE) {
916
TrackCacheValue *track_value = static_cast<TrackCacheValue *>(track);
917
// If it has at least one angle interpolation, it also uses angle interpolation for blending.
918
bool was_using_angle = track_value->is_using_angle;
919
if (track_src_type == Animation::TYPE_VALUE) {
920
if (track_value->init_value.is_string() && anim->value_track_get_update_mode(i) != Animation::UPDATE_DISCRETE) {
921
WARN_PRINT_ONCE_ED(mixer_name + ": '" + String(E) + "', Value Track: '" + String(path) + "' blends String types. This is an experimental algorithm.");
922
}
923
track_value->is_using_angle = track_value->is_using_angle || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE;
924
}
925
if (check_angle_interpolation && (was_using_angle != track_value->is_using_angle)) {
926
WARN_PRINT_ED(mixer_name + ": '" + String(E) + "', Value Track: '" + String(path) + "' has different interpolation types for rotation between some animations which may be blended together. Blending prioritizes angle interpolation, so the blending result uses the shortest path referenced to the initial (RESET animation) value.");
927
}
928
}
929
930
track->setup_pass = setup_pass;
931
}
932
}
933
934
List<Animation::TypeHash> to_delete;
935
936
for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) {
937
if (K.value->setup_pass != setup_pass) {
938
to_delete.push_back(K.key);
939
}
940
}
941
942
while (to_delete.front()) {
943
Animation::TypeHash thash = to_delete.front()->get();
944
memdelete(track_cache[thash]);
945
track_cache.erase(thash);
946
to_delete.pop_front();
947
}
948
949
track_map.clear();
950
951
int idx = 0;
952
for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) {
953
track_map[K.value->path] = idx;
954
idx++;
955
}
956
957
for (KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) {
958
K.value->blend_idx = track_map[K.value->path];
959
}
960
961
animation_track_num_to_track_cache.clear();
962
for (const StringName &E : sname_list) {
963
Ref<Animation> anim = get_animation(E);
964
_create_track_num_to_track_cache_for_animation(anim);
965
}
966
967
track_count = idx;
968
969
cache_valid = true;
970
971
return true;
972
}
973
974
/* -------------------------------------------- */
975
/* -- Blending processor ---------------------- */
976
/* -------------------------------------------- */
977
978
void AnimationMixer::_process_animation(double p_delta, bool p_update_only) {
979
_blend_init();
980
if (_blend_pre_process(p_delta, track_count, track_map)) {
981
_blend_capture(p_delta);
982
_blend_calc_total_weight();
983
_blend_process(p_delta, p_update_only);
984
_blend_apply();
985
_blend_post_process();
986
emit_signal(SNAME("mixer_applied"));
987
};
988
clear_animation_instances();
989
}
990
991
Variant AnimationMixer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant &p_value, ObjectID p_object_id, int p_object_sub_idx) {
992
#ifndef _3D_DISABLED
993
switch (p_anim->track_get_type(p_track)) {
994
case Animation::TYPE_POSITION_3D: {
995
if (p_object_sub_idx >= 0) {
996
Skeleton3D *skel = ObjectDB::get_instance<Skeleton3D>(p_object_id);
997
if (skel) {
998
return Vector3(p_value) * skel->get_motion_scale();
999
}
1000
}
1001
return p_value;
1002
} break;
1003
default: {
1004
} break;
1005
}
1006
#endif // _3D_DISABLED
1007
return p_value;
1008
}
1009
1010
Variant AnimationMixer::post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx) {
1011
if (is_GDVIRTUAL_CALL_post_process_key_value) {
1012
Variant res;
1013
if (GDVIRTUAL_CALL(_post_process_key_value, p_anim, p_track, p_value, p_object_id, p_object_sub_idx, res)) {
1014
return res;
1015
}
1016
is_GDVIRTUAL_CALL_post_process_key_value = false;
1017
}
1018
return _post_process_key_value(p_anim, p_track, p_value, p_object_id, p_object_sub_idx);
1019
}
1020
1021
void AnimationMixer::_blend_init() {
1022
// Check all tracks, see if they need modification.
1023
root_motion_position = Vector3(0, 0, 0);
1024
root_motion_rotation = Quaternion(0, 0, 0, 1);
1025
root_motion_scale = Vector3(0, 0, 0);
1026
root_motion_position_accumulator = Vector3(0, 0, 0);
1027
root_motion_rotation_accumulator = Quaternion(0, 0, 0, 1);
1028
root_motion_scale_accumulator = Vector3(1, 1, 1);
1029
1030
if (!cache_valid) {
1031
if (!_update_caches()) {
1032
return;
1033
}
1034
}
1035
1036
// Init all value/transform/blend/bezier tracks that track_cache has.
1037
for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) {
1038
TrackCache *track = K.value;
1039
1040
track->total_weight = 0.0;
1041
1042
switch (track->type) {
1043
case Animation::TYPE_POSITION_3D: {
1044
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
1045
if (track->root_motion) {
1046
root_motion_cache.loc = Vector3(0, 0, 0);
1047
root_motion_cache.rot = Quaternion(0, 0, 0, 1);
1048
root_motion_cache.scale = Vector3(1, 1, 1);
1049
}
1050
t->loc = t->init_loc;
1051
t->rot = t->init_rot;
1052
t->scale = t->init_scale;
1053
} break;
1054
case Animation::TYPE_BLEND_SHAPE: {
1055
TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track);
1056
t->value = t->init_value;
1057
} break;
1058
case Animation::TYPE_VALUE: {
1059
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
1060
t->value = Animation::cast_to_blendwise(t->init_value);
1061
t->element_size = t->init_value.is_string() ? (real_t)(t->init_value.operator String()).length() : 0;
1062
t->use_continuous = false;
1063
t->use_discrete = false;
1064
} break;
1065
case Animation::TYPE_AUDIO: {
1066
TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
1067
for (KeyValue<ObjectID, PlayingAudioTrackInfo> &L : t->playing_streams) {
1068
PlayingAudioTrackInfo &track_info = L.value;
1069
track_info.volume = 0.0;
1070
}
1071
} break;
1072
default: {
1073
} break;
1074
}
1075
}
1076
}
1077
1078
bool AnimationMixer::_blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) {
1079
return true;
1080
}
1081
1082
void AnimationMixer::_blend_post_process() {
1083
//
1084
}
1085
1086
void AnimationMixer::_blend_capture(double p_delta) {
1087
blend_capture(p_delta);
1088
}
1089
1090
void AnimationMixer::blend_capture(double p_delta) {
1091
if (capture_cache.animation.is_null()) {
1092
return;
1093
}
1094
1095
capture_cache.remain -= p_delta * capture_cache.step;
1096
if (Animation::is_less_or_equal_approx(capture_cache.remain, 0)) {
1097
if (capture_cache.animation.is_valid()) {
1098
animation_track_num_to_track_cache.erase(capture_cache.animation);
1099
}
1100
capture_cache.clear();
1101
return;
1102
}
1103
1104
real_t weight = Tween::run_equation(capture_cache.trans_type, capture_cache.ease_type, capture_cache.remain, 0.0, 1.0, 1.0);
1105
1106
// Blend with other animations.
1107
real_t inv = 1.0 - weight;
1108
for (AnimationInstance &ai : animation_instances) {
1109
ai.playback_info.weight *= inv;
1110
}
1111
1112
// Build capture animation instance.
1113
AnimationData ad;
1114
ad.animation = capture_cache.animation;
1115
1116
PlaybackInfo pi;
1117
pi.weight = weight;
1118
1119
AnimationInstance ai;
1120
ai.animation_data = ad;
1121
ai.playback_info = pi;
1122
1123
animation_instances.push_back(ai);
1124
}
1125
1126
void AnimationMixer::_blend_calc_total_weight() {
1127
for (const AnimationInstance &ai : animation_instances) {
1128
Ref<Animation> a = ai.animation_data.animation;
1129
real_t weight = ai.playback_info.weight;
1130
const real_t *track_weights_ptr = ai.playback_info.track_weights.ptr();
1131
int track_weights_count = ai.playback_info.track_weights.size();
1132
ERR_CONTINUE_EDMSG(!animation_track_num_to_track_cache.has(a), "No animation in cache.");
1133
LocalVector<TrackCache *> &track_num_to_track_cache = animation_track_num_to_track_cache[a];
1134
thread_local HashSet<Animation::TypeHash, HashHasher> processed_hashes;
1135
processed_hashes.clear();
1136
const Vector<Animation::Track *> tracks = a->get_tracks();
1137
Animation::Track *const *tracks_ptr = tracks.ptr();
1138
int count = tracks.size();
1139
for (int i = 0; i < count; i++) {
1140
Animation::Track *animation_track = tracks_ptr[i];
1141
if (!animation_track->enabled) {
1142
continue;
1143
}
1144
Animation::TypeHash thash = animation_track->thash;
1145
TrackCache *track = track_num_to_track_cache[i];
1146
if (track == nullptr || processed_hashes.has(thash)) {
1147
// No path, but avoid error spamming.
1148
// Or, there is the case different track type with same path; These can be distinguished by hash. So don't add the weight doubly.
1149
continue;
1150
}
1151
int blend_idx = track->blend_idx;
1152
ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count);
1153
real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight;
1154
track->total_weight += blend;
1155
processed_hashes.insert(thash);
1156
}
1157
}
1158
}
1159
1160
void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
1161
// Apply value/transform/blend/bezier blends to track caches and execute method/audio/animation tracks.
1162
#ifdef TOOLS_ENABLED
1163
bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint();
1164
#endif // TOOLS_ENABLED
1165
for (const AnimationInstance &ai : animation_instances) {
1166
Ref<Animation> a = ai.animation_data.animation;
1167
double time = ai.playback_info.time;
1168
double delta = ai.playback_info.delta;
1169
double start = ai.playback_info.start;
1170
double end = ai.playback_info.end;
1171
bool seeked = ai.playback_info.seeked;
1172
Animation::LoopedFlag looped_flag = ai.playback_info.looped_flag;
1173
bool is_external_seeking = ai.playback_info.is_external_seeking;
1174
real_t weight = ai.playback_info.weight;
1175
const real_t *track_weights_ptr = ai.playback_info.track_weights.ptr();
1176
int track_weights_count = ai.playback_info.track_weights.size();
1177
bool backward = std::signbit(delta); // This flag is used by the root motion calculates or detecting the end of audio stream.
1178
bool seeked_backward = std::signbit(p_delta);
1179
#ifndef _3D_DISABLED
1180
bool calc_root = !seeked || is_external_seeking;
1181
#endif // _3D_DISABLED
1182
ERR_CONTINUE_EDMSG(!animation_track_num_to_track_cache.has(a), "No animation in cache.");
1183
LocalVector<TrackCache *> &track_num_to_track_cache = animation_track_num_to_track_cache[a];
1184
const Vector<Animation::Track *> tracks = a->get_tracks();
1185
Animation::Track *const *tracks_ptr = tracks.ptr();
1186
real_t a_length = a->get_length();
1187
int count = tracks.size();
1188
for (int i = 0; i < count; i++) {
1189
const Animation::Track *animation_track = tracks_ptr[i];
1190
if (!animation_track->enabled) {
1191
continue;
1192
}
1193
TrackCache *track = track_num_to_track_cache[i];
1194
if (track == nullptr) {
1195
continue; // No path, but avoid error spamming.
1196
}
1197
int blend_idx = track->blend_idx;
1198
ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count);
1199
real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight;
1200
if (!deterministic) {
1201
// If non-deterministic, do normalization.
1202
// It would be better to make this if statement outside the for loop, but come here since too much code...
1203
if (Math::is_zero_approx(track->total_weight)) {
1204
continue;
1205
}
1206
blend = blend / track->total_weight;
1207
}
1208
Animation::TrackType ttype = animation_track->type;
1209
track->root_motion = root_motion_track == animation_track->path;
1210
switch (ttype) {
1211
case Animation::TYPE_POSITION_3D: {
1212
#ifndef _3D_DISABLED
1213
if (Math::is_zero_approx(blend)) {
1214
continue; // Nothing to blend.
1215
}
1216
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
1217
if (track->root_motion && calc_root) {
1218
int rot_track = -1;
1219
if (root_motion_local) {
1220
rot_track = a->find_track(a->track_get_path(i), Animation::TYPE_ROTATION_3D);
1221
}
1222
double prev_time = time - delta;
1223
if (!backward) {
1224
if (Animation::is_less_approx(prev_time, start)) {
1225
switch (a->get_loop_mode()) {
1226
case Animation::LOOP_NONE: {
1227
prev_time = start;
1228
} break;
1229
case Animation::LOOP_LINEAR: {
1230
prev_time = Math::fposmod(prev_time - start, end - start) + start;
1231
} break;
1232
case Animation::LOOP_PINGPONG: {
1233
prev_time = Math::pingpong(prev_time - start, end - start) + start;
1234
} break;
1235
default:
1236
break;
1237
}
1238
}
1239
} else {
1240
if (Animation::is_greater_approx(prev_time, end)) {
1241
switch (a->get_loop_mode()) {
1242
case Animation::LOOP_NONE: {
1243
prev_time = end;
1244
} break;
1245
case Animation::LOOP_LINEAR: {
1246
prev_time = Math::fposmod(prev_time - start, end - start) + start;
1247
} break;
1248
case Animation::LOOP_PINGPONG: {
1249
prev_time = Math::pingpong(prev_time - start, end - start) + start;
1250
} break;
1251
default:
1252
break;
1253
}
1254
}
1255
}
1256
if (rot_track >= 0) {
1257
Vector3 loc[2];
1258
Quaternion rot;
1259
if (!backward) {
1260
if (Animation::is_greater_approx(prev_time, time)) {
1261
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
1262
if (err != OK) {
1263
continue;
1264
}
1265
loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
1266
a->try_position_track_interpolate(i, end, &loc[1]);
1267
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
1268
1269
a->try_rotation_track_interpolate(rot_track, end, &rot);
1270
rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx);
1271
1272
root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend;
1273
prev_time = start;
1274
}
1275
} else {
1276
if (Animation::is_less_approx(prev_time, time)) {
1277
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
1278
if (err != OK) {
1279
continue;
1280
}
1281
loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
1282
a->try_position_track_interpolate(i, start, &loc[1]);
1283
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
1284
1285
a->try_rotation_track_interpolate(rot_track, start, &rot);
1286
rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx);
1287
1288
root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend;
1289
prev_time = end;
1290
}
1291
}
1292
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
1293
if (err != OK) {
1294
continue;
1295
}
1296
loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
1297
a->try_position_track_interpolate(i, time, &loc[1]);
1298
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
1299
1300
a->try_rotation_track_interpolate(rot_track, time, &rot);
1301
rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx);
1302
1303
root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend;
1304
prev_time = !backward ? start : end;
1305
} else {
1306
Vector3 loc[2];
1307
if (!backward) {
1308
if (Animation::is_greater_approx(prev_time, time)) {
1309
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
1310
if (err != OK) {
1311
continue;
1312
}
1313
loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
1314
a->try_position_track_interpolate(i, end, &loc[1]);
1315
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
1316
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
1317
prev_time = start;
1318
}
1319
} else {
1320
if (Animation::is_less_approx(prev_time, time)) {
1321
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
1322
if (err != OK) {
1323
continue;
1324
}
1325
loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
1326
a->try_position_track_interpolate(i, start, &loc[1]);
1327
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
1328
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
1329
prev_time = end;
1330
}
1331
}
1332
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
1333
if (err != OK) {
1334
continue;
1335
}
1336
loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
1337
a->try_position_track_interpolate(i, time, &loc[1]);
1338
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
1339
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
1340
prev_time = !backward ? start : end;
1341
}
1342
}
1343
{
1344
Vector3 loc;
1345
Error err = a->try_position_track_interpolate(i, time, &loc);
1346
if (err != OK) {
1347
continue;
1348
}
1349
loc = post_process_key_value(a, i, loc, t->object_id, t->bone_idx);
1350
t->loc += (loc - t->init_loc) * blend;
1351
}
1352
#endif // _3D_DISABLED
1353
} break;
1354
case Animation::TYPE_ROTATION_3D: {
1355
#ifndef _3D_DISABLED
1356
if (Math::is_zero_approx(blend)) {
1357
continue; // Nothing to blend.
1358
}
1359
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
1360
if (track->root_motion && calc_root) {
1361
double prev_time = time - delta;
1362
if (!backward) {
1363
if (Animation::is_less_approx(prev_time, start)) {
1364
switch (a->get_loop_mode()) {
1365
case Animation::LOOP_NONE: {
1366
prev_time = start;
1367
} break;
1368
case Animation::LOOP_LINEAR: {
1369
prev_time = Math::fposmod(prev_time - start, end - start) + start;
1370
} break;
1371
case Animation::LOOP_PINGPONG: {
1372
prev_time = Math::pingpong(prev_time - start, end - start) + start;
1373
} break;
1374
default:
1375
break;
1376
}
1377
}
1378
} else {
1379
if (Animation::is_greater_approx(prev_time, end)) {
1380
switch (a->get_loop_mode()) {
1381
case Animation::LOOP_NONE: {
1382
prev_time = end;
1383
} break;
1384
case Animation::LOOP_LINEAR: {
1385
prev_time = Math::fposmod(prev_time - start, end - start) + start;
1386
} break;
1387
case Animation::LOOP_PINGPONG: {
1388
prev_time = Math::pingpong(prev_time - start, end - start) + start;
1389
} break;
1390
default:
1391
break;
1392
}
1393
}
1394
}
1395
Quaternion rot[2];
1396
if (!backward) {
1397
if (Animation::is_greater_approx(prev_time, time)) {
1398
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
1399
if (err != OK) {
1400
continue;
1401
}
1402
rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx);
1403
a->try_rotation_track_interpolate(i, end, &rot[1]);
1404
rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx);
1405
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
1406
prev_time = start;
1407
}
1408
} else {
1409
if (Animation::is_less_approx(prev_time, time)) {
1410
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
1411
if (err != OK) {
1412
continue;
1413
}
1414
rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx);
1415
a->try_rotation_track_interpolate(i, start, &rot[1]);
1416
rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx);
1417
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
1418
prev_time = end;
1419
}
1420
}
1421
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
1422
if (err != OK) {
1423
continue;
1424
}
1425
rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx);
1426
a->try_rotation_track_interpolate(i, time, &rot[1]);
1427
rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx);
1428
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
1429
prev_time = !backward ? start : end;
1430
}
1431
{
1432
Quaternion rot;
1433
Error err = a->try_rotation_track_interpolate(i, time, &rot);
1434
if (err != OK) {
1435
continue;
1436
}
1437
rot = post_process_key_value(a, i, rot, t->object_id, t->bone_idx);
1438
t->rot = (t->rot * Quaternion().slerp(t->init_rot.inverse() * rot, blend)).normalized();
1439
}
1440
#endif // _3D_DISABLED
1441
} break;
1442
case Animation::TYPE_SCALE_3D: {
1443
#ifndef _3D_DISABLED
1444
if (Math::is_zero_approx(blend)) {
1445
continue; // Nothing to blend.
1446
}
1447
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
1448
if (track->root_motion && calc_root) {
1449
double prev_time = time - delta;
1450
if (!backward) {
1451
if (Animation::is_less_approx(prev_time, start)) {
1452
switch (a->get_loop_mode()) {
1453
case Animation::LOOP_NONE: {
1454
prev_time = start;
1455
} break;
1456
case Animation::LOOP_LINEAR: {
1457
prev_time = Math::fposmod(prev_time - start, end - start) + start;
1458
} break;
1459
case Animation::LOOP_PINGPONG: {
1460
prev_time = Math::pingpong(prev_time - start, end - start) + start;
1461
} break;
1462
default:
1463
break;
1464
}
1465
}
1466
} else {
1467
if (Animation::is_greater_approx(prev_time, end)) {
1468
switch (a->get_loop_mode()) {
1469
case Animation::LOOP_NONE: {
1470
prev_time = end;
1471
} break;
1472
case Animation::LOOP_LINEAR: {
1473
prev_time = Math::fposmod(prev_time - start, end - start) + start;
1474
} break;
1475
case Animation::LOOP_PINGPONG: {
1476
prev_time = Math::pingpong(prev_time - start, end - start) + start;
1477
} break;
1478
default:
1479
break;
1480
}
1481
}
1482
}
1483
Vector3 scale[2];
1484
if (!backward) {
1485
if (Animation::is_greater_approx(prev_time, time)) {
1486
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
1487
if (err != OK) {
1488
continue;
1489
}
1490
scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx);
1491
a->try_scale_track_interpolate(i, end, &scale[1]);
1492
scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx);
1493
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
1494
prev_time = start;
1495
}
1496
} else {
1497
if (Animation::is_less_approx(prev_time, time)) {
1498
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
1499
if (err != OK) {
1500
continue;
1501
}
1502
scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx);
1503
a->try_scale_track_interpolate(i, start, &scale[1]);
1504
scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx);
1505
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
1506
prev_time = end;
1507
}
1508
}
1509
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
1510
if (err != OK) {
1511
continue;
1512
}
1513
scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx);
1514
a->try_scale_track_interpolate(i, time, &scale[1]);
1515
scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx);
1516
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
1517
prev_time = !backward ? start : end;
1518
}
1519
{
1520
Vector3 scale;
1521
Error err = a->try_scale_track_interpolate(i, time, &scale);
1522
if (err != OK) {
1523
continue;
1524
}
1525
scale = post_process_key_value(a, i, scale, t->object_id, t->bone_idx);
1526
t->scale += (scale - t->init_scale) * blend;
1527
}
1528
#endif // _3D_DISABLED
1529
} break;
1530
case Animation::TYPE_BLEND_SHAPE: {
1531
#ifndef _3D_DISABLED
1532
if (Math::is_zero_approx(blend)) {
1533
continue; // Nothing to blend.
1534
}
1535
TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track);
1536
float value;
1537
Error err = a->try_blend_shape_track_interpolate(i, time, &value);
1538
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
1539
if (err != OK) {
1540
continue;
1541
}
1542
value = post_process_key_value(a, i, value, t->object_id, t->shape_index);
1543
t->value += (value - t->init_value) * blend;
1544
#endif // _3D_DISABLED
1545
} break;
1546
case Animation::TYPE_BEZIER:
1547
case Animation::TYPE_VALUE: {
1548
if (Math::is_zero_approx(blend)) {
1549
continue; // Nothing to blend.
1550
}
1551
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
1552
bool is_value = ttype == Animation::TYPE_VALUE;
1553
bool is_discrete = is_value && a->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE;
1554
bool force_continuous = callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS;
1555
if (!is_discrete || force_continuous) {
1556
t->use_continuous = true;
1557
1558
Variant value;
1559
if (t->is_variant_interpolatable) {
1560
value = is_value ? a->value_track_interpolate(i, time, is_discrete && force_continuous ? backward : false) : Variant(a->bezier_track_interpolate(i, time));
1561
value = post_process_key_value(a, i, value, t->object_id);
1562
if (value == Variant()) {
1563
continue;
1564
}
1565
} else {
1566
// Discrete track sets the value in the current _blend_process() function,
1567
// but Force Continuous track does not set the value here because the value must be set in the _blend_apply() function later.
1568
int idx = a->track_find_key(i, time, Animation::FIND_MODE_NEAREST, false, backward);
1569
if (idx < 0) {
1570
continue;
1571
}
1572
value = a->track_get_key_value(i, idx);
1573
value = post_process_key_value(a, i, value, t->object_id);
1574
if (value == Variant()) {
1575
continue;
1576
}
1577
t->value = value;
1578
continue;
1579
}
1580
1581
// Special case for angle interpolation.
1582
if (t->is_using_angle) {
1583
// For blending consistency, it prevents rotation of more than 180 degrees from init_value.
1584
// This is the same as for Quaternion blends.
1585
float rot_a = t->value;
1586
float rot_b = value;
1587
float rot_init = t->init_value;
1588
rot_a = Math::fposmod(rot_a, (float)Math::TAU);
1589
rot_b = Math::fposmod(rot_b, (float)Math::TAU);
1590
rot_init = Math::fposmod(rot_init, (float)Math::TAU);
1591
if (rot_init < Math::PI) {
1592
rot_a = rot_a > rot_init + Math::PI ? rot_a - Math::TAU : rot_a;
1593
rot_b = rot_b > rot_init + Math::PI ? rot_b - Math::TAU : rot_b;
1594
} else {
1595
rot_a = rot_a < rot_init - Math::PI ? rot_a + Math::TAU : rot_a;
1596
rot_b = rot_b < rot_init - Math::PI ? rot_b + Math::TAU : rot_b;
1597
}
1598
t->value = Math::fposmod(rot_a + (rot_b - rot_init) * (float)blend, (float)Math::TAU);
1599
} else {
1600
value = Animation::cast_to_blendwise(value);
1601
if (t->init_value.is_array()) {
1602
t->element_size = MAX(t->element_size.operator int(), (value.operator Array()).size());
1603
} else if (t->init_value.is_string()) {
1604
real_t length = Animation::subtract_variant((real_t)(value.operator Array()).size(), (real_t)(t->init_value.operator String()).length());
1605
t->element_size = Animation::blend_variant(t->element_size, length, blend);
1606
}
1607
value = Animation::subtract_variant(value, Animation::cast_to_blendwise(t->init_value));
1608
t->value = Animation::blend_variant(t->value, value, blend);
1609
}
1610
} else {
1611
if (seeked) {
1612
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT, false, seeked_backward);
1613
if (idx < 0) {
1614
continue;
1615
}
1616
t->use_discrete = true;
1617
Variant value = a->track_get_key_value(i, idx);
1618
value = post_process_key_value(a, i, value, t->object_id);
1619
Object *t_obj = ObjectDB::get_instance(t->object_id);
1620
if (t_obj) {
1621
t_obj->set_indexed(t->subpath, value);
1622
}
1623
} else {
1624
List<int> indices;
1625
a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag);
1626
for (int &F : indices) {
1627
t->use_discrete = true;
1628
Variant value = a->track_get_key_value(i, F);
1629
value = post_process_key_value(a, i, value, t->object_id);
1630
Object *t_obj = ObjectDB::get_instance(t->object_id);
1631
if (t_obj) {
1632
t_obj->set_indexed(t->subpath, value);
1633
}
1634
}
1635
}
1636
}
1637
} break;
1638
case Animation::TYPE_METHOD: {
1639
#ifdef TOOLS_ENABLED
1640
if (!can_call) {
1641
continue;
1642
}
1643
#endif // TOOLS_ENABLED
1644
if (p_update_only || Math::is_zero_approx(blend)) {
1645
continue;
1646
}
1647
TrackCacheMethod *t = static_cast<TrackCacheMethod *>(track);
1648
if (seeked) {
1649
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT, true);
1650
if (idx < 0) {
1651
continue;
1652
}
1653
StringName method = a->method_track_get_name(i, idx);
1654
Vector<Variant> params = a->method_track_get_params(i, idx);
1655
_call_object(t->object_id, method, params, callback_mode_method == ANIMATION_CALLBACK_MODE_METHOD_DEFERRED);
1656
} else {
1657
List<int> indices;
1658
a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag);
1659
for (int &F : indices) {
1660
StringName method = a->method_track_get_name(i, F);
1661
Vector<Variant> params = a->method_track_get_params(i, F);
1662
_call_object(t->object_id, method, params, callback_mode_method == ANIMATION_CALLBACK_MODE_METHOD_DEFERRED);
1663
}
1664
}
1665
} break;
1666
case Animation::TYPE_AUDIO: {
1667
// The end of audio should be observed even if the blend value is 0, build up the information and store to the cache for that.
1668
TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
1669
Object *t_obj = ObjectDB::get_instance(t->object_id);
1670
Node *asp = t_obj ? Object::cast_to<Node>(t_obj) : nullptr;
1671
if (!t_obj || !asp) {
1672
t->playing_streams.clear();
1673
continue;
1674
}
1675
ObjectID oid = a->get_instance_id();
1676
if (!t->playing_streams.has(oid)) {
1677
t->playing_streams[oid] = PlayingAudioTrackInfo();
1678
}
1679
1680
PlayingAudioTrackInfo &track_info = t->playing_streams[oid];
1681
track_info.length = a_length;
1682
track_info.time = time;
1683
track_info.volume += blend;
1684
track_info.loop = a->get_loop_mode() != Animation::LOOP_NONE;
1685
track_info.backward = backward;
1686
track_info.use_blend = a->audio_track_is_use_blend(i);
1687
AHashMap<int, PlayingAudioStreamInfo> &map = track_info.stream_info;
1688
1689
// Main process to fire key is started from here.
1690
if (p_update_only) {
1691
continue;
1692
}
1693
// Find stream.
1694
int idx = -1;
1695
if (seeked) {
1696
// Audio key may be playbacked from the middle, should use FIND_MODE_NEAREST.
1697
// Then, check the current playing stream to prevent to playback doubly.
1698
idx = a->track_find_key(i, time, Animation::FIND_MODE_NEAREST, true);
1699
// Discard previous stream when seeking.
1700
if (map.has(idx)) {
1701
t->audio_stream_playback->stop_stream(map[idx].index);
1702
map.erase(idx);
1703
}
1704
} else {
1705
List<int> to_play;
1706
a->track_get_key_indices_in_range(i, time, delta, &to_play, looped_flag);
1707
if (to_play.size()) {
1708
idx = to_play.back()->get();
1709
}
1710
}
1711
if (idx < 0) {
1712
continue;
1713
}
1714
1715
// Play stream.
1716
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
1717
if (stream.is_valid()) {
1718
double start_ofs = a->audio_track_get_key_start_offset(i, idx);
1719
double end_ofs = a->audio_track_get_key_end_offset(i, idx);
1720
double len = stream->get_length();
1721
if (seeked) {
1722
start_ofs += time - a->track_get_key_time(i, idx);
1723
}
1724
1725
if (t_obj->call(SNAME("get_stream")) != t->audio_stream) {
1726
t_obj->call(SNAME("set_stream"), t->audio_stream);
1727
t->audio_stream_playback.unref();
1728
if (!playing_audio_stream_players.has(asp)) {
1729
playing_audio_stream_players.push_back(asp);
1730
}
1731
}
1732
if (!t_obj->call(SNAME("is_playing"))) {
1733
t_obj->call(SNAME("play"));
1734
}
1735
if (!t_obj->call(SNAME("has_stream_playback"))) {
1736
t->audio_stream_playback.unref();
1737
continue;
1738
}
1739
if (t->audio_stream_playback.is_null()) {
1740
t->audio_stream_playback = t_obj->call(SNAME("get_stream_playback"));
1741
}
1742
1743
if (t_obj->call(SNAME("get_is_sample"))) {
1744
if (t->audio_stream_playback->get_sample_playback().is_valid()) {
1745
AudioServer::get_singleton()->stop_sample_playback(t->audio_stream_playback->get_sample_playback());
1746
}
1747
Ref<AudioSamplePlayback> sample_playback;
1748
sample_playback.instantiate();
1749
sample_playback->stream = stream;
1750
t->audio_stream_playback->set_sample_playback(sample_playback);
1751
AudioServer::get_singleton()->start_sample_playback(sample_playback);
1752
continue;
1753
}
1754
1755
PlayingAudioStreamInfo pasi;
1756
pasi.index = t->audio_stream_playback->play_stream(stream, start_ofs, 0, 1.0, t->playback_type, t->bus);
1757
pasi.start = time;
1758
if (len && Animation::is_greater_approx(end_ofs, 0)) { // Force an end at a time.
1759
pasi.len = len - start_ofs - end_ofs;
1760
} else {
1761
pasi.len = 0;
1762
}
1763
map[idx] = pasi;
1764
}
1765
} break;
1766
case Animation::TYPE_ANIMATION: {
1767
if (Math::is_zero_approx(blend)) {
1768
continue;
1769
}
1770
TrackCacheAnimation *t = static_cast<TrackCacheAnimation *>(track);
1771
Object *t_obj = ObjectDB::get_instance(t->object_id);
1772
if (!t_obj) {
1773
continue;
1774
}
1775
AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t_obj);
1776
if (!player2) {
1777
continue;
1778
}
1779
// TODO: Make it possible to embed section info in animation track keys.
1780
if (seeked) {
1781
// Seek.
1782
int idx = a->track_find_key(i, time, Animation::FIND_MODE_NEAREST, true);
1783
if (idx < 0) {
1784
continue;
1785
}
1786
double pos = a->track_get_key_time(i, idx);
1787
StringName anim_name = a->animation_track_get_key_animation(i, idx);
1788
if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) {
1789
continue;
1790
}
1791
Ref<Animation> anim = player2->get_animation(anim_name);
1792
double at_anim_pos = start;
1793
switch (anim->get_loop_mode()) {
1794
case Animation::LOOP_NONE: {
1795
if (!is_external_seeking && ((!backward && Animation::is_greater_or_equal_approx(time, pos + end)) || (backward && Animation::is_less_or_equal_approx(time, pos + start)))) {
1796
continue; // Do nothing if current time is outside of length when started.
1797
}
1798
at_anim_pos = MIN(end, time - pos); // Seek to end.
1799
} break;
1800
case Animation::LOOP_LINEAR: {
1801
at_anim_pos = Math::fposmod(time - pos - start, end - start) + start; // Seek to loop.
1802
} break;
1803
case Animation::LOOP_PINGPONG: {
1804
at_anim_pos = Math::pingpong(time - pos - start, end - start) + start;
1805
} break;
1806
default:
1807
break;
1808
}
1809
if (player2->is_playing() || !is_external_seeking) {
1810
player2->seek(at_anim_pos, false, p_update_only);
1811
player2->play(anim_name);
1812
t->playing = true;
1813
playing_caches.insert(t);
1814
} else {
1815
player2->set_assigned_animation(anim_name);
1816
player2->seek(at_anim_pos, true, p_update_only);
1817
}
1818
} else {
1819
// Find stuff to play.
1820
List<int> to_play;
1821
a->track_get_key_indices_in_range(i, time, delta, &to_play, looped_flag);
1822
if (to_play.size()) {
1823
int idx = to_play.back()->get();
1824
StringName anim_name = a->animation_track_get_key_animation(i, idx);
1825
if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) {
1826
if (playing_caches.has(t)) {
1827
playing_caches.erase(t);
1828
player2->stop();
1829
t->playing = false;
1830
}
1831
} else {
1832
player2->play(anim_name);
1833
t->playing = true;
1834
playing_caches.insert(t);
1835
}
1836
}
1837
}
1838
} break;
1839
}
1840
}
1841
}
1842
is_GDVIRTUAL_CALL_post_process_key_value = true;
1843
}
1844
1845
void AnimationMixer::_blend_apply() {
1846
// Finally, set the tracks.
1847
for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) {
1848
TrackCache *track = K.value;
1849
bool is_zero_amount = Math::is_zero_approx(track->total_weight);
1850
if (!deterministic && is_zero_amount) {
1851
continue;
1852
}
1853
switch (track->type) {
1854
case Animation::TYPE_POSITION_3D: {
1855
#ifndef _3D_DISABLED
1856
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
1857
1858
if (t->root_motion) {
1859
root_motion_position = root_motion_cache.loc;
1860
root_motion_rotation = root_motion_cache.rot;
1861
root_motion_scale = root_motion_cache.scale - Vector3(1, 1, 1);
1862
root_motion_position_accumulator = t->loc;
1863
root_motion_rotation_accumulator = t->rot;
1864
root_motion_scale_accumulator = t->scale;
1865
} else if (t->skeleton_id.is_valid() && t->bone_idx >= 0) {
1866
Skeleton3D *t_skeleton = ObjectDB::get_instance<Skeleton3D>(t->skeleton_id);
1867
if (!t_skeleton) {
1868
return;
1869
}
1870
if (t->loc_used) {
1871
t_skeleton->set_bone_pose_position(t->bone_idx, t->loc);
1872
}
1873
if (t->rot_used) {
1874
t_skeleton->set_bone_pose_rotation(t->bone_idx, t->rot);
1875
}
1876
if (t->scale_used) {
1877
t_skeleton->set_bone_pose_scale(t->bone_idx, t->scale);
1878
}
1879
1880
} else if (!t->skeleton_id.is_valid()) {
1881
Node3D *t_node_3d = ObjectDB::get_instance<Node3D>(t->object_id);
1882
if (!t_node_3d) {
1883
return;
1884
}
1885
if (t->loc_used) {
1886
t_node_3d->set_position(t->loc);
1887
}
1888
if (t->rot_used) {
1889
t_node_3d->set_rotation(t->rot.get_euler());
1890
}
1891
if (t->scale_used) {
1892
t_node_3d->set_scale(t->scale);
1893
}
1894
}
1895
#endif // _3D_DISABLED
1896
} break;
1897
case Animation::TYPE_BLEND_SHAPE: {
1898
#ifndef _3D_DISABLED
1899
TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track);
1900
1901
MeshInstance3D *t_mesh_3d = ObjectDB::get_instance<MeshInstance3D>(t->object_id);
1902
if (t_mesh_3d) {
1903
t_mesh_3d->set_blend_shape_value(t->shape_index, t->value);
1904
}
1905
#endif // _3D_DISABLED
1906
} break;
1907
case Animation::TYPE_VALUE: {
1908
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
1909
1910
if (callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS) {
1911
t->is_init = false; // Always update in Force Continuous.
1912
} else if (!t->use_continuous && (t->use_discrete || !deterministic)) {
1913
t->is_init = true; // If there is no continuous value and only disctere value is applied or just started, don't RESET.
1914
}
1915
1916
if ((t->is_init && (is_zero_amount || !t->use_continuous)) ||
1917
(callback_mode_discrete != ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS &&
1918
!is_zero_amount &&
1919
callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_DOMINANT &&
1920
t->use_discrete)) {
1921
break; // Don't overwrite the value set by UPDATE_DISCRETE.
1922
}
1923
1924
if (callback_mode_discrete != ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS) {
1925
t->is_init = !t->use_continuous; // If there is no Continuous in non-Force Continuous type, it means RESET.
1926
}
1927
1928
// Trim unused elements if init array/string is not blended.
1929
if (t->value.is_array()) {
1930
int actual_blended_size = (int)Math::round(Math::abs(t->element_size.operator real_t()));
1931
if (actual_blended_size < (t->value.operator Array()).size()) {
1932
real_t abs_weight = Math::abs(track->total_weight);
1933
if (abs_weight >= 1.0) {
1934
(t->value.operator Array()).resize(actual_blended_size);
1935
} else if (t->init_value.is_string()) {
1936
(t->value.operator Array()).resize(Animation::interpolate_variant((t->init_value.operator String()).length(), actual_blended_size, abs_weight));
1937
}
1938
}
1939
}
1940
1941
Object *t_obj = ObjectDB::get_instance(t->object_id);
1942
if (t_obj) {
1943
t_obj->set_indexed(t->subpath, Animation::cast_from_blendwise(t->value, t->init_value.get_type()));
1944
}
1945
1946
} break;
1947
case Animation::TYPE_AUDIO: {
1948
TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
1949
1950
// Audio ending process.
1951
LocalVector<ObjectID> erase_maps;
1952
for (KeyValue<ObjectID, PlayingAudioTrackInfo> &L : t->playing_streams) {
1953
PlayingAudioTrackInfo &track_info = L.value;
1954
float db = Math::linear_to_db(track_info.use_blend ? track_info.volume : 1.0);
1955
LocalVector<int> erase_streams;
1956
AHashMap<int, PlayingAudioStreamInfo> &map = track_info.stream_info;
1957
for (const KeyValue<int, PlayingAudioStreamInfo> &M : map) {
1958
PlayingAudioStreamInfo pasi = M.value;
1959
1960
bool stop = false;
1961
if (!t->audio_stream_playback->is_stream_playing(pasi.index)) {
1962
stop = true;
1963
}
1964
if (!track_info.loop) {
1965
if (!track_info.backward) {
1966
if (Animation::is_less_approx(track_info.time, pasi.start)) {
1967
stop = true;
1968
}
1969
} else if (track_info.backward) {
1970
if (Animation::is_greater_approx(track_info.time, pasi.start)) {
1971
stop = true;
1972
}
1973
}
1974
}
1975
if (Animation::is_greater_approx(pasi.len, 0)) {
1976
double len = 0.0;
1977
if (!track_info.backward) {
1978
len = Animation::is_greater_approx(pasi.start, track_info.time) ? (track_info.length - pasi.start) + track_info.time : track_info.time - pasi.start;
1979
} else {
1980
len = Animation::is_less_approx(pasi.start, track_info.time) ? (track_info.length - track_info.time) + pasi.start : pasi.start - track_info.time;
1981
}
1982
if (Animation::is_greater_approx(len, pasi.len)) {
1983
stop = true;
1984
}
1985
}
1986
if (stop) {
1987
// Time to stop.
1988
t->audio_stream_playback->stop_stream(pasi.index);
1989
erase_streams.push_back(M.key);
1990
} else {
1991
t->audio_stream_playback->set_stream_volume(pasi.index, db);
1992
}
1993
}
1994
for (uint32_t erase_idx = 0; erase_idx < erase_streams.size(); erase_idx++) {
1995
map.erase(erase_streams[erase_idx]);
1996
}
1997
if (map.is_empty()) {
1998
erase_maps.push_back(L.key);
1999
}
2000
}
2001
for (uint32_t erase_idx = 0; erase_idx < erase_maps.size(); erase_idx++) {
2002
t->playing_streams.erase(erase_maps[erase_idx]);
2003
}
2004
} break;
2005
default: {
2006
} // The rest don't matter.
2007
}
2008
}
2009
}
2010
2011
void AnimationMixer::_call_object(ObjectID p_object_id, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) {
2012
// Separate function to use alloca() more efficiently
2013
const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * p_params.size());
2014
const Variant *args = p_params.ptr();
2015
uint32_t argcount = p_params.size();
2016
for (uint32_t i = 0; i < argcount; i++) {
2017
argptrs[i] = &args[i];
2018
}
2019
Object *t_obj = ObjectDB::get_instance(p_object_id);
2020
if (!t_obj) {
2021
return;
2022
}
2023
if (p_deferred) {
2024
Callable(t_obj, p_method).call_deferredp(argptrs, argcount);
2025
} else {
2026
Callable::CallError ce;
2027
t_obj->callp(p_method, argptrs, argcount, ce);
2028
}
2029
}
2030
2031
void AnimationMixer::make_animation_instance(const StringName &p_name, const PlaybackInfo p_playback_info) {
2032
ERR_FAIL_COND(!has_animation(p_name));
2033
2034
AnimationData ad;
2035
ad.name = p_name;
2036
ad.animation = get_animation(p_name);
2037
ad.animation_library = find_animation_library(ad.animation);
2038
2039
AnimationInstance ai;
2040
ai.animation_data = ad;
2041
ai.playback_info = p_playback_info;
2042
2043
animation_instances.push_back(ai);
2044
}
2045
2046
void AnimationMixer::clear_animation_instances() {
2047
animation_instances.clear();
2048
}
2049
2050
void AnimationMixer::advance(double p_time) {
2051
_process_animation(p_time);
2052
}
2053
2054
void AnimationMixer::clear_caches() {
2055
_clear_caches();
2056
}
2057
2058
/* -------------------------------------------- */
2059
/* -- Root motion ----------------------------- */
2060
/* -------------------------------------------- */
2061
2062
void AnimationMixer::set_root_motion_track(const NodePath &p_track) {
2063
root_motion_track = p_track;
2064
notify_property_list_changed();
2065
}
2066
2067
NodePath AnimationMixer::get_root_motion_track() const {
2068
return root_motion_track;
2069
}
2070
2071
void AnimationMixer::set_root_motion_local(bool p_enabled) {
2072
root_motion_local = p_enabled;
2073
}
2074
2075
bool AnimationMixer::is_root_motion_local() const {
2076
return root_motion_local;
2077
}
2078
2079
Vector3 AnimationMixer::get_root_motion_position() const {
2080
return root_motion_position;
2081
}
2082
2083
Quaternion AnimationMixer::get_root_motion_rotation() const {
2084
return root_motion_rotation;
2085
}
2086
2087
Vector3 AnimationMixer::get_root_motion_scale() const {
2088
return root_motion_scale;
2089
}
2090
2091
Vector3 AnimationMixer::get_root_motion_position_accumulator() const {
2092
return root_motion_position_accumulator;
2093
}
2094
2095
Quaternion AnimationMixer::get_root_motion_rotation_accumulator() const {
2096
return root_motion_rotation_accumulator;
2097
}
2098
2099
Vector3 AnimationMixer::get_root_motion_scale_accumulator() const {
2100
return root_motion_scale_accumulator;
2101
}
2102
2103
/* -------------------------------------------- */
2104
/* -- Reset on save --------------------------- */
2105
/* -------------------------------------------- */
2106
2107
void AnimationMixer::set_reset_on_save_enabled(bool p_enabled) {
2108
reset_on_save = p_enabled;
2109
}
2110
2111
bool AnimationMixer::is_reset_on_save_enabled() const {
2112
return reset_on_save;
2113
}
2114
2115
bool AnimationMixer::can_apply_reset() const {
2116
return has_animation(SceneStringName(RESET));
2117
}
2118
2119
void AnimationMixer::_build_backup_track_cache() {
2120
for (const KeyValue<Animation::TypeHash, TrackCache *> &K : track_cache) {
2121
TrackCache *track = K.value;
2122
track->total_weight = 1.0;
2123
switch (track->type) {
2124
case Animation::TYPE_POSITION_3D: {
2125
#ifndef _3D_DISABLED
2126
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
2127
if (t->root_motion) {
2128
// Do nothing.
2129
} else if (t->skeleton_id.is_valid() && t->bone_idx >= 0) {
2130
Skeleton3D *t_skeleton = ObjectDB::get_instance<Skeleton3D>(t->skeleton_id);
2131
if (!t_skeleton) {
2132
return;
2133
}
2134
if (t->loc_used) {
2135
t->loc = t_skeleton->get_bone_pose_position(t->bone_idx);
2136
}
2137
if (t->rot_used) {
2138
t->rot = t_skeleton->get_bone_pose_rotation(t->bone_idx);
2139
}
2140
if (t->scale_used) {
2141
t->scale = t_skeleton->get_bone_pose_scale(t->bone_idx);
2142
}
2143
} else if (!t->skeleton_id.is_valid()) {
2144
Node3D *t_node_3d = ObjectDB::get_instance<Node3D>(t->object_id);
2145
if (!t_node_3d) {
2146
return;
2147
}
2148
if (t->loc_used) {
2149
t->loc = t_node_3d->get_position();
2150
}
2151
if (t->rot_used) {
2152
t->rot = t_node_3d->get_quaternion();
2153
}
2154
if (t->scale_used) {
2155
t->scale = t_node_3d->get_scale();
2156
}
2157
}
2158
#endif // _3D_DISABLED
2159
} break;
2160
case Animation::TYPE_BLEND_SHAPE: {
2161
#ifndef _3D_DISABLED
2162
TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track);
2163
MeshInstance3D *t_mesh_3d = ObjectDB::get_instance<MeshInstance3D>(t->object_id);
2164
if (t_mesh_3d) {
2165
t->value = t_mesh_3d->get_blend_shape_value(t->shape_index);
2166
}
2167
#endif // _3D_DISABLED
2168
} break;
2169
case Animation::TYPE_VALUE: {
2170
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
2171
Object *t_obj = ObjectDB::get_instance(t->object_id);
2172
if (t_obj) {
2173
t->value = Animation::cast_to_blendwise(t_obj->get_indexed(t->subpath));
2174
}
2175
t->use_continuous = true;
2176
t->use_discrete = false;
2177
if (t->init_value.is_array()) {
2178
t->element_size = MAX(t->element_size.operator int(), (t->value.operator Array()).size());
2179
} else if (t->init_value.is_string()) {
2180
t->element_size = (real_t)(t->value.operator Array()).size();
2181
}
2182
} break;
2183
case Animation::TYPE_AUDIO: {
2184
TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
2185
Object *t_obj = ObjectDB::get_instance(t->object_id);
2186
if (t_obj) {
2187
Node *asp = Object::cast_to<Node>(t_obj);
2188
if (asp) {
2189
asp->call(SNAME("set_stream"), Ref<AudioStream>());
2190
}
2191
}
2192
} break;
2193
default: {
2194
} // The rest don't matter.
2195
}
2196
}
2197
}
2198
2199
Ref<AnimatedValuesBackup> AnimationMixer::make_backup() {
2200
Ref<AnimatedValuesBackup> backup;
2201
backup.instantiate();
2202
2203
Ref<Animation> reset_anim = animation_set[SceneStringName(RESET)].animation;
2204
ERR_FAIL_COND_V(reset_anim.is_null(), Ref<AnimatedValuesBackup>());
2205
2206
_blend_init();
2207
PlaybackInfo pi;
2208
pi.time = 0;
2209
pi.delta = 0;
2210
pi.start = 0;
2211
pi.end = reset_anim->get_length();
2212
pi.seeked = true;
2213
pi.weight = 1.0;
2214
make_animation_instance(SceneStringName(RESET), pi);
2215
_build_backup_track_cache();
2216
2217
backup->set_data(track_cache);
2218
clear_animation_instances();
2219
2220
return backup;
2221
}
2222
2223
void AnimationMixer::reset() {
2224
ERR_FAIL_COND(!can_apply_reset());
2225
2226
Ref<Animation> reset_anim = animation_set[SceneStringName(RESET)].animation;
2227
ERR_FAIL_COND(reset_anim.is_null());
2228
2229
Node *root_node_object = get_node_or_null(root_node);
2230
ERR_FAIL_NULL(root_node_object);
2231
2232
AnimationPlayer *aux_player = memnew(AnimationPlayer);
2233
root_node_object->add_child(aux_player);
2234
Ref<AnimationLibrary> al;
2235
al.instantiate();
2236
al->add_animation(SceneStringName(RESET), reset_anim);
2237
aux_player->set_reset_on_save_enabled(false);
2238
aux_player->set_root_node(aux_player->get_path_to(root_node_object));
2239
aux_player->add_animation_library("", al);
2240
aux_player->set_assigned_animation(SceneStringName(RESET));
2241
aux_player->seek(0.0f, true);
2242
aux_player->queue_free();
2243
}
2244
2245
void AnimationMixer::restore(const Ref<AnimatedValuesBackup> &p_backup) {
2246
ERR_FAIL_COND(p_backup.is_null());
2247
track_cache = p_backup->get_data();
2248
_blend_apply();
2249
track_cache = AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher>();
2250
cache_valid = false;
2251
}
2252
2253
#ifdef TOOLS_ENABLED
2254
Ref<AnimatedValuesBackup> AnimationMixer::apply_reset(bool p_user_initiated) {
2255
if (!p_user_initiated && dummy) {
2256
return Ref<AnimatedValuesBackup>();
2257
}
2258
ERR_FAIL_COND_V(!can_apply_reset(), Ref<AnimatedValuesBackup>());
2259
2260
Ref<Animation> reset_anim = animation_set[SceneStringName(RESET)].animation;
2261
ERR_FAIL_COND_V(reset_anim.is_null(), Ref<AnimatedValuesBackup>());
2262
2263
Ref<AnimatedValuesBackup> backup_current = make_backup();
2264
if (p_user_initiated) {
2265
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
2266
ur->create_action(TTR("Animation Apply Reset"));
2267
ur->add_do_method(this, "_reset");
2268
ur->add_undo_method(this, "_restore", backup_current);
2269
ur->commit_action();
2270
} else {
2271
reset();
2272
}
2273
2274
return backup_current;
2275
}
2276
#endif // TOOLS_ENABLED
2277
2278
/* -------------------------------------------- */
2279
/* -- Capture feature ------------------------- */
2280
/* -------------------------------------------- */
2281
2282
void AnimationMixer::capture(const StringName &p_name, double p_duration, Tween::TransitionType p_trans_type, Tween::EaseType p_ease_type) {
2283
ERR_FAIL_COND(!active);
2284
ERR_FAIL_COND(!has_animation(p_name));
2285
ERR_FAIL_COND(p_duration <= 0);
2286
Ref<Animation> reference_animation = get_animation(p_name);
2287
2288
if (!cache_valid) {
2289
_update_caches(); // Need to retrieve object id.
2290
}
2291
2292
capture_cache.remain = 1.0;
2293
capture_cache.step = 1.0 / p_duration;
2294
capture_cache.trans_type = p_trans_type;
2295
capture_cache.ease_type = p_ease_type;
2296
if (capture_cache.animation.is_valid()) {
2297
animation_track_num_to_track_cache.erase(capture_cache.animation);
2298
}
2299
capture_cache.animation.instantiate();
2300
2301
bool is_valid = false;
2302
for (int i = 0; i < reference_animation->get_track_count(); i++) {
2303
if (!reference_animation->track_is_enabled(i)) {
2304
continue;
2305
}
2306
if (reference_animation->track_get_type(i) == Animation::TYPE_VALUE && reference_animation->value_track_get_update_mode(i) == Animation::UPDATE_CAPTURE) {
2307
TrackCacheValue *t = static_cast<TrackCacheValue *>(track_cache[reference_animation->track_get_type_hash(i)]);
2308
Object *t_obj = ObjectDB::get_instance(t->object_id);
2309
if (t_obj) {
2310
Variant value = t_obj->get_indexed(t->subpath);
2311
int inserted_idx = capture_cache.animation->add_track(Animation::TYPE_VALUE);
2312
capture_cache.animation->track_set_path(inserted_idx, reference_animation->track_get_path(i));
2313
capture_cache.animation->track_insert_key(inserted_idx, 0, value);
2314
capture_cache.animation->value_track_set_update_mode(inserted_idx, Animation::UPDATE_CONTINUOUS);
2315
capture_cache.animation->track_set_interpolation_type(inserted_idx, Animation::INTERPOLATION_LINEAR);
2316
is_valid = true;
2317
}
2318
}
2319
}
2320
if (!is_valid) {
2321
capture_cache.clear();
2322
} else {
2323
_create_track_num_to_track_cache_for_animation(capture_cache.animation);
2324
}
2325
}
2326
2327
/* -------------------------------------------- */
2328
/* -- General functions ----------------------- */
2329
/* -------------------------------------------- */
2330
2331
void AnimationMixer::_node_removed(Node *p_node) {
2332
_clear_caches();
2333
}
2334
2335
void AnimationMixer::_notification(int p_what) {
2336
switch (p_what) {
2337
case NOTIFICATION_ENTER_TREE: {
2338
if (!processing) {
2339
set_physics_process_internal(false);
2340
set_process_internal(false);
2341
}
2342
_clear_caches();
2343
} break;
2344
2345
case NOTIFICATION_INTERNAL_PROCESS: {
2346
if (active && callback_mode_process == ANIMATION_CALLBACK_MODE_PROCESS_IDLE) {
2347
_process_animation(get_process_delta_time());
2348
}
2349
} break;
2350
2351
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
2352
if (active && callback_mode_process == ANIMATION_CALLBACK_MODE_PROCESS_PHYSICS) {
2353
_process_animation(get_physics_process_delta_time());
2354
}
2355
} break;
2356
2357
case NOTIFICATION_EXIT_TREE: {
2358
_clear_caches();
2359
} break;
2360
}
2361
}
2362
2363
#ifdef TOOLS_ENABLED
2364
void AnimationMixer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
2365
const String pf = p_function;
2366
if (p_idx == 0) {
2367
if (pf == "get_animation" || pf == "has_animation") {
2368
List<StringName> al;
2369
get_animation_list(&al);
2370
for (const StringName &name : al) {
2371
r_options->push_back(String(name).quote());
2372
}
2373
} else if (pf == "get_animation_library" || pf == "has_animation_library" || pf == "remove_animation_library" || pf == "rename_animation_library") {
2374
List<StringName> al;
2375
get_animation_library_list(&al);
2376
for (const StringName &name : al) {
2377
r_options->push_back(String(name).quote());
2378
}
2379
}
2380
}
2381
Node::get_argument_options(p_function, p_idx, r_options);
2382
}
2383
#endif
2384
2385
void AnimationMixer::_bind_methods() {
2386
/* ---- Data lists ---- */
2387
ClassDB::bind_method(D_METHOD("add_animation_library", "name", "library"), &AnimationMixer::add_animation_library);
2388
ClassDB::bind_method(D_METHOD("remove_animation_library", "name"), &AnimationMixer::remove_animation_library);
2389
ClassDB::bind_method(D_METHOD("rename_animation_library", "name", "newname"), &AnimationMixer::rename_animation_library);
2390
ClassDB::bind_method(D_METHOD("has_animation_library", "name"), &AnimationMixer::has_animation_library);
2391
ClassDB::bind_method(D_METHOD("get_animation_library", "name"), &AnimationMixer::get_animation_library);
2392
ClassDB::bind_method(D_METHOD("get_animation_library_list"), &AnimationMixer::_get_animation_library_list);
2393
2394
ClassDB::bind_method(D_METHOD("has_animation", "name"), &AnimationMixer::has_animation);
2395
ClassDB::bind_method(D_METHOD("get_animation", "name"), &AnimationMixer::get_animation);
2396
ClassDB::bind_method(D_METHOD("get_animation_list"), &AnimationMixer::_get_animation_list);
2397
2398
/* ---- General settings for animation ---- */
2399
ClassDB::bind_method(D_METHOD("set_active", "active"), &AnimationMixer::set_active);
2400
ClassDB::bind_method(D_METHOD("is_active"), &AnimationMixer::is_active);
2401
2402
ClassDB::bind_method(D_METHOD("set_deterministic", "deterministic"), &AnimationMixer::set_deterministic);
2403
ClassDB::bind_method(D_METHOD("is_deterministic"), &AnimationMixer::is_deterministic);
2404
2405
ClassDB::bind_method(D_METHOD("set_root_node", "path"), &AnimationMixer::set_root_node);
2406
ClassDB::bind_method(D_METHOD("get_root_node"), &AnimationMixer::get_root_node);
2407
2408
ClassDB::bind_method(D_METHOD("set_callback_mode_process", "mode"), &AnimationMixer::set_callback_mode_process);
2409
ClassDB::bind_method(D_METHOD("get_callback_mode_process"), &AnimationMixer::get_callback_mode_process);
2410
2411
ClassDB::bind_method(D_METHOD("set_callback_mode_method", "mode"), &AnimationMixer::set_callback_mode_method);
2412
ClassDB::bind_method(D_METHOD("get_callback_mode_method"), &AnimationMixer::get_callback_mode_method);
2413
2414
ClassDB::bind_method(D_METHOD("set_callback_mode_discrete", "mode"), &AnimationMixer::set_callback_mode_discrete);
2415
ClassDB::bind_method(D_METHOD("get_callback_mode_discrete"), &AnimationMixer::get_callback_mode_discrete);
2416
2417
/* ---- Audio ---- */
2418
ClassDB::bind_method(D_METHOD("set_audio_max_polyphony", "max_polyphony"), &AnimationMixer::set_audio_max_polyphony);
2419
ClassDB::bind_method(D_METHOD("get_audio_max_polyphony"), &AnimationMixer::get_audio_max_polyphony);
2420
2421
/* ---- Root motion accumulator for Skeleton3D ---- */
2422
ClassDB::bind_method(D_METHOD("set_root_motion_track", "path"), &AnimationMixer::set_root_motion_track);
2423
ClassDB::bind_method(D_METHOD("get_root_motion_track"), &AnimationMixer::get_root_motion_track);
2424
ClassDB::bind_method(D_METHOD("set_root_motion_local", "enabled"), &AnimationMixer::set_root_motion_local);
2425
ClassDB::bind_method(D_METHOD("is_root_motion_local"), &AnimationMixer::is_root_motion_local);
2426
2427
ClassDB::bind_method(D_METHOD("get_root_motion_position"), &AnimationMixer::get_root_motion_position);
2428
ClassDB::bind_method(D_METHOD("get_root_motion_rotation"), &AnimationMixer::get_root_motion_rotation);
2429
ClassDB::bind_method(D_METHOD("get_root_motion_scale"), &AnimationMixer::get_root_motion_scale);
2430
ClassDB::bind_method(D_METHOD("get_root_motion_position_accumulator"), &AnimationMixer::get_root_motion_position_accumulator);
2431
ClassDB::bind_method(D_METHOD("get_root_motion_rotation_accumulator"), &AnimationMixer::get_root_motion_rotation_accumulator);
2432
ClassDB::bind_method(D_METHOD("get_root_motion_scale_accumulator"), &AnimationMixer::get_root_motion_scale_accumulator);
2433
2434
/* ---- Blending processor ---- */
2435
ClassDB::bind_method(D_METHOD("clear_caches"), &AnimationMixer::clear_caches);
2436
ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationMixer::advance);
2437
GDVIRTUAL_BIND(_post_process_key_value, "animation", "track", "value", "object_id", "object_sub_idx");
2438
2439
/* ---- Capture feature ---- */
2440
ClassDB::bind_method(D_METHOD("capture", "name", "duration", "trans_type", "ease_type"), &AnimationMixer::capture, DEFVAL(Tween::TRANS_LINEAR), DEFVAL(Tween::EASE_IN));
2441
2442
/* ---- Reset on save ---- */
2443
ClassDB::bind_method(D_METHOD("set_reset_on_save_enabled", "enabled"), &AnimationMixer::set_reset_on_save_enabled);
2444
ClassDB::bind_method(D_METHOD("is_reset_on_save_enabled"), &AnimationMixer::is_reset_on_save_enabled);
2445
2446
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active");
2447
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deterministic"), "set_deterministic", "is_deterministic");
2448
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reset_on_save", PROPERTY_HINT_NONE, ""), "set_reset_on_save_enabled", "is_reset_on_save_enabled");
2449
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root_node", "get_root_node");
2450
2451
ADD_GROUP("Root Motion", "root_motion_");
2452
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_motion_track"), "set_root_motion_track", "get_root_motion_track");
2453
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "root_motion_local"), "set_root_motion_local", "is_root_motion_local");
2454
2455
ADD_GROUP("Audio", "audio_");
2456
ADD_PROPERTY(PropertyInfo(Variant::INT, "audio_max_polyphony", PROPERTY_HINT_RANGE, "1,127,1"), "set_audio_max_polyphony", "get_audio_max_polyphony");
2457
2458
ADD_GROUP("Callback Mode", "callback_mode_");
2459
ADD_PROPERTY(PropertyInfo(Variant::INT, "callback_mode_process", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_callback_mode_process", "get_callback_mode_process");
2460
ADD_PROPERTY(PropertyInfo(Variant::INT, "callback_mode_method", PROPERTY_HINT_ENUM, "Deferred,Immediate"), "set_callback_mode_method", "get_callback_mode_method");
2461
ADD_PROPERTY(PropertyInfo(Variant::INT, "callback_mode_discrete", PROPERTY_HINT_ENUM, "Dominant,Recessive,Force Continuous"), "set_callback_mode_discrete", "get_callback_mode_discrete");
2462
2463
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_PROCESS_PHYSICS);
2464
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_PROCESS_IDLE);
2465
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_PROCESS_MANUAL);
2466
2467
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_METHOD_DEFERRED);
2468
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_METHOD_IMMEDIATE);
2469
2470
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_DISCRETE_DOMINANT);
2471
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_DISCRETE_RECESSIVE);
2472
BIND_ENUM_CONSTANT(ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS);
2473
2474
ADD_SIGNAL(MethodInfo(SNAME("animation_list_changed")));
2475
ADD_SIGNAL(MethodInfo(SNAME("animation_libraries_updated")));
2476
ADD_SIGNAL(MethodInfo(SNAME("animation_finished"), PropertyInfo(Variant::STRING_NAME, "anim_name")));
2477
ADD_SIGNAL(MethodInfo(SNAME("animation_started"), PropertyInfo(Variant::STRING_NAME, "anim_name")));
2478
ADD_SIGNAL(MethodInfo(SNAME("caches_cleared")));
2479
ADD_SIGNAL(MethodInfo(SNAME("mixer_applied")));
2480
ADD_SIGNAL(MethodInfo(SNAME("mixer_updated"))); // For updating dummy player.
2481
2482
ClassDB::bind_method(D_METHOD("_reset"), &AnimationMixer::reset);
2483
ClassDB::bind_method(D_METHOD("_restore", "backup"), &AnimationMixer::restore);
2484
}
2485
2486
AnimationMixer::AnimationMixer() {
2487
root_node = SceneStringName(path_pp);
2488
}
2489
2490
AnimationMixer::~AnimationMixer() {
2491
}
2492
2493
void AnimatedValuesBackup::set_data(const AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher> p_data) {
2494
clear_data();
2495
2496
for (const KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &E : p_data) {
2497
AnimationMixer::TrackCache *track = get_cache_copy(E.value);
2498
if (!track) {
2499
continue; // Some types of tracks do not get a copy and must be ignored.
2500
}
2501
2502
data.insert(E.key, track);
2503
}
2504
}
2505
2506
AHashMap<Animation::TypeHash, AnimationMixer::TrackCache *, HashHasher> AnimatedValuesBackup::get_data() const {
2507
HashMap<Animation::TypeHash, AnimationMixer::TrackCache *> ret;
2508
for (const KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &E : data) {
2509
AnimationMixer::TrackCache *track = get_cache_copy(E.value);
2510
ERR_CONTINUE(!track); // Backup shouldn't contain tracks that cannot be copied, this is a mistake.
2511
2512
ret.insert(E.key, track);
2513
}
2514
return ret;
2515
}
2516
2517
void AnimatedValuesBackup::clear_data() {
2518
for (KeyValue<Animation::TypeHash, AnimationMixer::TrackCache *> &K : data) {
2519
memdelete(K.value);
2520
}
2521
data.clear();
2522
}
2523
2524
AnimationMixer::TrackCache *AnimatedValuesBackup::get_cache_copy(AnimationMixer::TrackCache *p_cache) const {
2525
switch (p_cache->type) {
2526
case Animation::TYPE_BEZIER:
2527
case Animation::TYPE_VALUE: {
2528
AnimationMixer::TrackCacheValue *src = static_cast<AnimationMixer::TrackCacheValue *>(p_cache);
2529
AnimationMixer::TrackCacheValue *tc = memnew(AnimationMixer::TrackCacheValue(*src));
2530
return tc;
2531
}
2532
2533
case Animation::TYPE_POSITION_3D:
2534
case Animation::TYPE_ROTATION_3D:
2535
case Animation::TYPE_SCALE_3D: {
2536
AnimationMixer::TrackCacheTransform *src = static_cast<AnimationMixer::TrackCacheTransform *>(p_cache);
2537
AnimationMixer::TrackCacheTransform *tc = memnew(AnimationMixer::TrackCacheTransform(*src));
2538
return tc;
2539
}
2540
2541
case Animation::TYPE_BLEND_SHAPE: {
2542
AnimationMixer::TrackCacheBlendShape *src = static_cast<AnimationMixer::TrackCacheBlendShape *>(p_cache);
2543
AnimationMixer::TrackCacheBlendShape *tc = memnew(AnimationMixer::TrackCacheBlendShape(*src));
2544
return tc;
2545
}
2546
2547
case Animation::TYPE_AUDIO: {
2548
AnimationMixer::TrackCacheAudio *src = static_cast<AnimationMixer::TrackCacheAudio *>(p_cache);
2549
AnimationMixer::TrackCacheAudio *tc = memnew(AnimationMixer::TrackCacheAudio(*src));
2550
return tc;
2551
}
2552
2553
case Animation::TYPE_METHOD:
2554
case Animation::TYPE_ANIMATION: {
2555
// Nothing to do here.
2556
} break;
2557
}
2558
return nullptr;
2559
}
2560
2561