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