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