1 /*************************************************************************/
2 /* animation_tree.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
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_tree.h"
32
33 #include "animation_blend_tree.h"
34 #include "core/engine.h"
35 #include "core/method_bind_ext.gen.inc"
36 #include "scene/scene_string_names.h"
37 #include "servers/audio/audio_stream.h"
38
get_parameter_list(List<PropertyInfo> * r_list) const39 void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
40 if (get_script_instance()) {
41 Array parameters = get_script_instance()->call("get_parameter_list");
42 for (int i = 0; i < parameters.size(); i++) {
43 Dictionary d = parameters[i];
44 ERR_CONTINUE(d.empty());
45 r_list->push_back(PropertyInfo::from_dict(d));
46 }
47 }
48 }
49
get_parameter_default_value(const StringName & p_parameter) const50 Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const {
51 if (get_script_instance()) {
52 return get_script_instance()->call("get_parameter_default_value", p_parameter);
53 }
54 return Variant();
55 }
56
set_parameter(const StringName & p_name,const Variant & p_value)57 void AnimationNode::set_parameter(const StringName &p_name, const Variant &p_value) {
58 ERR_FAIL_COND(!state);
59 ERR_FAIL_COND(!state->tree->property_parent_map.has(base_path));
60 ERR_FAIL_COND(!state->tree->property_parent_map[base_path].has(p_name));
61 StringName path = state->tree->property_parent_map[base_path][p_name];
62
63 state->tree->property_map[path] = p_value;
64 }
65
get_parameter(const StringName & p_name) const66 Variant AnimationNode::get_parameter(const StringName &p_name) const {
67 ERR_FAIL_COND_V(!state, Variant());
68 ERR_FAIL_COND_V(!state->tree->property_parent_map.has(base_path), Variant());
69 ERR_FAIL_COND_V(!state->tree->property_parent_map[base_path].has(p_name), Variant());
70
71 StringName path = state->tree->property_parent_map[base_path][p_name];
72 return state->tree->property_map[path];
73 }
74
get_child_nodes(List<ChildNode> * r_child_nodes)75 void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
76
77 if (get_script_instance()) {
78 Dictionary cn = get_script_instance()->call("get_child_nodes");
79 List<Variant> keys;
80 cn.get_key_list(&keys);
81 for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
82 ChildNode child;
83 child.name = E->get();
84 child.node = cn[E->get()];
85 r_child_nodes->push_back(child);
86 }
87 }
88 }
89
blend_animation(const StringName & p_animation,float p_time,float p_delta,bool p_seeked,float p_blend)90 void AnimationNode::blend_animation(const StringName &p_animation, float p_time, float p_delta, bool p_seeked, float p_blend) {
91
92 ERR_FAIL_COND(!state);
93 ERR_FAIL_COND(!state->player->has_animation(p_animation));
94
95 Ref<Animation> animation = state->player->get_animation(p_animation);
96
97 if (animation.is_null()) {
98
99 AnimationNodeBlendTree *btree = Object::cast_to<AnimationNodeBlendTree>(parent);
100 if (btree) {
101 String name = btree->get_node_name(Ref<AnimationNodeAnimation>(this));
102 make_invalid(vformat(RTR("In node '%s', invalid animation: '%s'."), name, p_animation));
103 } else {
104 make_invalid(vformat(RTR("Invalid animation: '%s'."), p_animation));
105 }
106 return;
107 }
108
109 ERR_FAIL_COND(!animation.is_valid());
110
111 AnimationState anim_state;
112 anim_state.blend = p_blend;
113 anim_state.track_blends = &blends;
114 anim_state.delta = p_delta;
115 anim_state.time = p_time;
116 anim_state.animation = animation;
117 anim_state.seeked = p_seeked;
118
119 state->animation_states.push_back(anim_state);
120 }
121
_pre_process(const StringName & p_base_path,AnimationNode * p_parent,State * p_state,float p_time,bool p_seek,const Vector<StringName> & p_connections)122 float AnimationNode::_pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, float p_time, bool p_seek, const Vector<StringName> &p_connections) {
123
124 base_path = p_base_path;
125 parent = p_parent;
126 connections = p_connections;
127 state = p_state;
128
129 float t = process(p_time, p_seek);
130
131 state = NULL;
132 parent = NULL;
133 base_path = StringName();
134 connections.clear();
135
136 return t;
137 }
138
make_invalid(const String & p_reason)139 void AnimationNode::make_invalid(const String &p_reason) {
140 ERR_FAIL_COND(!state);
141 state->valid = false;
142 if (state->invalid_reasons != String()) {
143 state->invalid_reasons += "\n";
144 }
145 state->invalid_reasons += "- " + p_reason;
146 }
147
blend_input(int p_input,float p_time,bool p_seek,float p_blend,FilterAction p_filter,bool p_optimize)148 float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
149 ERR_FAIL_INDEX_V(p_input, inputs.size(), 0);
150 ERR_FAIL_COND_V(!state, 0);
151
152 AnimationNodeBlendTree *blend_tree = Object::cast_to<AnimationNodeBlendTree>(parent);
153 ERR_FAIL_COND_V(!blend_tree, 0);
154
155 StringName node_name = connections[p_input];
156
157 if (!blend_tree->has_node(node_name)) {
158 String name = blend_tree->get_node_name(Ref<AnimationNode>(this));
159 make_invalid(vformat(RTR("Nothing connected to input '%s' of node '%s'."), get_input_name(p_input), name));
160 return 0;
161 }
162
163 Ref<AnimationNode> node = blend_tree->get_node(node_name);
164
165 //inputs.write[p_input].last_pass = state->last_pass;
166 float activity = 0;
167 float ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), NULL, node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity);
168
169 Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path);
170
171 if (activity_ptr && p_input < activity_ptr->size()) {
172 activity_ptr->write[p_input].last_pass = state->last_pass;
173 activity_ptr->write[p_input].activity = activity;
174 }
175 return ret;
176 }
177
blend_node(const StringName & p_sub_path,Ref<AnimationNode> p_node,float p_time,bool p_seek,float p_blend,FilterAction p_filter,bool p_optimize)178 float AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
179
180 return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_blend, p_filter, p_optimize);
181 }
182
_blend_node(const StringName & p_subpath,const Vector<StringName> & p_connections,AnimationNode * p_new_parent,Ref<AnimationNode> p_node,float p_time,bool p_seek,float p_blend,FilterAction p_filter,bool p_optimize,float * r_max)183 float AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize, float *r_max) {
184
185 ERR_FAIL_COND_V(!p_node.is_valid(), 0);
186 ERR_FAIL_COND_V(!state, 0);
187
188 int blend_count = blends.size();
189
190 if (p_node->blends.size() != blend_count) {
191 p_node->blends.resize(blend_count);
192 }
193
194 float *blendw = p_node->blends.ptrw();
195 const float *blendr = blends.ptr();
196
197 bool any_valid = false;
198
199 if (has_filter() && is_filter_enabled() && p_filter != FILTER_IGNORE) {
200
201 for (int i = 0; i < blend_count; i++) {
202 blendw[i] = 0.0; //all to zero by default
203 }
204
205 const NodePath *K = NULL;
206 while ((K = filter.next(K))) {
207 if (!state->track_map.has(*K)) {
208 continue;
209 }
210 int idx = state->track_map[*K];
211 blendw[idx] = 1.0; //filtered goes to one
212 }
213
214 switch (p_filter) {
215 case FILTER_IGNORE:
216 break; //will not happen anyway
217 case FILTER_PASS: {
218 //values filtered pass, the rest don't
219 for (int i = 0; i < blend_count; i++) {
220 if (blendw[i] == 0) //not filtered, does not pass
221 continue;
222
223 blendw[i] = blendr[i] * p_blend;
224 if (blendw[i] > CMP_EPSILON) {
225 any_valid = true;
226 }
227 }
228
229 } break;
230 case FILTER_STOP: {
231
232 //values filtered don't pass, the rest are blended
233
234 for (int i = 0; i < blend_count; i++) {
235 if (blendw[i] > 0) //filtered, does not pass
236 continue;
237
238 blendw[i] = blendr[i] * p_blend;
239 if (blendw[i] > CMP_EPSILON) {
240 any_valid = true;
241 }
242 }
243
244 } break;
245 case FILTER_BLEND: {
246
247 //filtered values are blended, the rest are passed without blending
248
249 for (int i = 0; i < blend_count; i++) {
250 if (blendw[i] == 1.0) {
251 blendw[i] = blendr[i] * p_blend; //filtered, blend
252 } else {
253 blendw[i] = blendr[i]; //not filtered, do not blend
254 }
255
256 if (blendw[i] > CMP_EPSILON) {
257 any_valid = true;
258 }
259 }
260
261 } break;
262 }
263 } else {
264 for (int i = 0; i < blend_count; i++) {
265
266 //regular blend
267 blendw[i] = blendr[i] * p_blend;
268 if (blendw[i] > CMP_EPSILON) {
269 any_valid = true;
270 }
271 }
272 }
273
274 if (r_max) {
275 *r_max = 0;
276 for (int i = 0; i < blend_count; i++) {
277 *r_max = MAX(*r_max, blendw[i]);
278 }
279 }
280
281 if (!p_seek && p_optimize && !any_valid) //pointless to go on, all are zero
282 return 0;
283
284 String new_path;
285 AnimationNode *new_parent;
286
287 //this is the slowest part of processing, but as strings process in powers of 2, and the paths always exist, it will not result in that many allocations
288 if (p_new_parent) {
289 new_parent = p_new_parent;
290 new_path = String(base_path) + String(p_subpath) + "/";
291 } else {
292 ERR_FAIL_COND_V(!parent, 0);
293 new_parent = parent;
294 new_path = String(parent->base_path) + String(p_subpath) + "/";
295 }
296 return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_connections);
297 }
298
get_input_count() const299 int AnimationNode::get_input_count() const {
300
301 return inputs.size();
302 }
get_input_name(int p_input)303 String AnimationNode::get_input_name(int p_input) {
304 ERR_FAIL_INDEX_V(p_input, inputs.size(), String());
305 return inputs[p_input].name;
306 }
307
get_caption() const308 String AnimationNode::get_caption() const {
309
310 if (get_script_instance()) {
311 return get_script_instance()->call("get_caption");
312 }
313
314 return "Node";
315 }
316
add_input(const String & p_name)317 void AnimationNode::add_input(const String &p_name) {
318 //root nodes can't add inputs
319 ERR_FAIL_COND(Object::cast_to<AnimationRootNode>(this) != NULL);
320 Input input;
321 ERR_FAIL_COND(p_name.find(".") != -1 || p_name.find("/") != -1);
322 input.name = p_name;
323 inputs.push_back(input);
324 emit_changed();
325 }
326
set_input_name(int p_input,const String & p_name)327 void AnimationNode::set_input_name(int p_input, const String &p_name) {
328 ERR_FAIL_INDEX(p_input, inputs.size());
329 ERR_FAIL_COND(p_name.find(".") != -1 || p_name.find("/") != -1);
330 inputs.write[p_input].name = p_name;
331 emit_changed();
332 }
333
remove_input(int p_index)334 void AnimationNode::remove_input(int p_index) {
335 ERR_FAIL_INDEX(p_index, inputs.size());
336 inputs.remove(p_index);
337 emit_changed();
338 }
339
process(float p_time,bool p_seek)340 float AnimationNode::process(float p_time, bool p_seek) {
341
342 if (get_script_instance()) {
343 return get_script_instance()->call("process", p_time, p_seek);
344 }
345
346 return 0;
347 }
348
set_filter_path(const NodePath & p_path,bool p_enable)349 void AnimationNode::set_filter_path(const NodePath &p_path, bool p_enable) {
350 if (p_enable) {
351 filter[p_path] = true;
352 } else {
353 filter.erase(p_path);
354 }
355 }
356
set_filter_enabled(bool p_enable)357 void AnimationNode::set_filter_enabled(bool p_enable) {
358 filter_enabled = p_enable;
359 }
360
is_filter_enabled() const361 bool AnimationNode::is_filter_enabled() const {
362 return filter_enabled;
363 }
364
is_path_filtered(const NodePath & p_path) const365 bool AnimationNode::is_path_filtered(const NodePath &p_path) const {
366 return filter.has(p_path);
367 }
368
has_filter() const369 bool AnimationNode::has_filter() const {
370 return false;
371 }
372
_get_filters() const373 Array AnimationNode::_get_filters() const {
374
375 Array paths;
376
377 const NodePath *K = NULL;
378 while ((K = filter.next(K))) {
379 paths.push_back(String(*K)); //use strings, so sorting is possible
380 }
381 paths.sort(); //done so every time the scene is saved, it does not change
382
383 return paths;
384 }
_set_filters(const Array & p_filters)385 void AnimationNode::_set_filters(const Array &p_filters) {
386 filter.clear();
387 for (int i = 0; i < p_filters.size(); i++) {
388 set_filter_path(p_filters[i], true);
389 }
390 }
391
_validate_property(PropertyInfo & property) const392 void AnimationNode::_validate_property(PropertyInfo &property) const {
393 if (!has_filter() && (property.name == "filter_enabled" || property.name == "filters")) {
394 property.usage = 0;
395 }
396 }
397
get_child_by_name(const StringName & p_name)398 Ref<AnimationNode> AnimationNode::get_child_by_name(const StringName &p_name) {
399 if (get_script_instance()) {
400 return get_script_instance()->call("get_child_by_name", p_name);
401 }
402 return Ref<AnimationNode>();
403 }
404
_bind_methods()405 void AnimationNode::_bind_methods() {
406
407 ClassDB::bind_method(D_METHOD("get_input_count"), &AnimationNode::get_input_count);
408 ClassDB::bind_method(D_METHOD("get_input_name", "input"), &AnimationNode::get_input_name);
409
410 ClassDB::bind_method(D_METHOD("add_input", "name"), &AnimationNode::add_input);
411 ClassDB::bind_method(D_METHOD("remove_input", "index"), &AnimationNode::remove_input);
412
413 ClassDB::bind_method(D_METHOD("set_filter_path", "path", "enable"), &AnimationNode::set_filter_path);
414 ClassDB::bind_method(D_METHOD("is_path_filtered", "path"), &AnimationNode::is_path_filtered);
415
416 ClassDB::bind_method(D_METHOD("set_filter_enabled", "enable"), &AnimationNode::set_filter_enabled);
417 ClassDB::bind_method(D_METHOD("is_filter_enabled"), &AnimationNode::is_filter_enabled);
418
419 ClassDB::bind_method(D_METHOD("_set_filters", "filters"), &AnimationNode::_set_filters);
420 ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters);
421
422 ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "blend"), &AnimationNode::blend_animation);
423 ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
424 ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true));
425
426 ClassDB::bind_method(D_METHOD("set_parameter", "name", "value"), &AnimationNode::set_parameter);
427 ClassDB::bind_method(D_METHOD("get_parameter", "name"), &AnimationNode::get_parameter);
428
429 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_filter_enabled", "is_filter_enabled");
430 ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "filters", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_filters", "_get_filters");
431
432 BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "get_child_nodes"));
433 BIND_VMETHOD(MethodInfo(Variant::ARRAY, "get_parameter_list"));
434 BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_child_by_name", PropertyInfo(Variant::STRING, "name")));
435 {
436 MethodInfo mi = MethodInfo(Variant::NIL, "get_parameter_default_value", PropertyInfo(Variant::STRING, "name"));
437 mi.return_val.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
438 BIND_VMETHOD(mi);
439 }
440 BIND_VMETHOD(MethodInfo("process", PropertyInfo(Variant::REAL, "time"), PropertyInfo(Variant::BOOL, "seek")));
441 BIND_VMETHOD(MethodInfo(Variant::STRING, "get_caption"));
442 BIND_VMETHOD(MethodInfo(Variant::STRING, "has_filter"));
443
444 ADD_SIGNAL(MethodInfo("removed_from_graph"));
445
446 ADD_SIGNAL(MethodInfo("tree_changed"));
447
448 BIND_ENUM_CONSTANT(FILTER_IGNORE);
449 BIND_ENUM_CONSTANT(FILTER_PASS);
450 BIND_ENUM_CONSTANT(FILTER_STOP);
451 BIND_ENUM_CONSTANT(FILTER_BLEND);
452 }
453
AnimationNode()454 AnimationNode::AnimationNode() {
455
456 state = NULL;
457 parent = NULL;
458 filter_enabled = false;
459 }
460
461 ////////////////////
462
set_tree_root(const Ref<AnimationNode> & p_root)463 void AnimationTree::set_tree_root(const Ref<AnimationNode> &p_root) {
464
465 if (root.is_valid()) {
466 root->disconnect("tree_changed", this, "_tree_changed");
467 }
468
469 root = p_root;
470
471 if (root.is_valid()) {
472 root->connect("tree_changed", this, "_tree_changed");
473 }
474
475 properties_dirty = true;
476
477 update_configuration_warning();
478 }
479
get_tree_root() const480 Ref<AnimationNode> AnimationTree::get_tree_root() const {
481 return root;
482 }
483
set_active(bool p_active)484 void AnimationTree::set_active(bool p_active) {
485
486 if (active == p_active)
487 return;
488
489 active = p_active;
490 started = active;
491
492 if (process_mode == ANIMATION_PROCESS_IDLE) {
493 set_process_internal(active);
494 } else {
495
496 set_physics_process_internal(active);
497 }
498
499 if (!active && is_inside_tree()) {
500 for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
501
502 if (ObjectDB::get_instance(E->get()->object_id)) {
503 E->get()->object->call("stop");
504 }
505 }
506
507 playing_caches.clear();
508 }
509 }
510
is_active() const511 bool AnimationTree::is_active() const {
512
513 return active;
514 }
515
set_process_mode(AnimationProcessMode p_mode)516 void AnimationTree::set_process_mode(AnimationProcessMode p_mode) {
517
518 if (process_mode == p_mode)
519 return;
520
521 bool was_active = is_active();
522 if (was_active) {
523 set_active(false);
524 }
525
526 process_mode = p_mode;
527
528 if (was_active) {
529 set_active(true);
530 }
531 }
532
get_process_mode() const533 AnimationTree::AnimationProcessMode AnimationTree::get_process_mode() const {
534 return process_mode;
535 }
536
_node_removed(Node * p_node)537 void AnimationTree::_node_removed(Node *p_node) {
538 cache_valid = false;
539 }
540
_update_caches(AnimationPlayer * player)541 bool AnimationTree::_update_caches(AnimationPlayer *player) {
542
543 setup_pass++;
544
545 if (!player->has_node(player->get_root())) {
546 ERR_PRINT("AnimationTree: AnimationPlayer root is invalid.");
547 set_active(false);
548 return false;
549 }
550 Node *parent = player->get_node(player->get_root());
551
552 List<StringName> sname;
553 player->get_animation_list(&sname);
554
555 for (List<StringName>::Element *E = sname.front(); E; E = E->next()) {
556 Ref<Animation> anim = player->get_animation(E->get());
557 for (int i = 0; i < anim->get_track_count(); i++) {
558 NodePath path = anim->track_get_path(i);
559 Animation::TrackType track_type = anim->track_get_type(i);
560
561 TrackCache *track = NULL;
562 if (track_cache.has(path)) {
563 track = track_cache.get(path);
564 }
565
566 //if not valid, delete track
567 if (track && (track->type != track_type || ObjectDB::get_instance(track->object_id) == NULL)) {
568 playing_caches.erase(track);
569 memdelete(track);
570 track_cache.erase(path);
571 track = NULL;
572 }
573
574 if (!track) {
575
576 RES resource;
577 Vector<StringName> leftover_path;
578 Node *child = parent->get_node_and_resource(path, resource, leftover_path);
579
580 if (!child) {
581 ERR_PRINTS("AnimationTree: '" + String(E->get()) + "', couldn't resolve track: '" + String(path) + "'");
582 continue;
583 }
584
585 if (!child->is_connected("tree_exited", this, "_node_removed")) {
586 child->connect("tree_exited", this, "_node_removed", varray(child));
587 }
588
589 switch (track_type) {
590 case Animation::TYPE_VALUE: {
591
592 TrackCacheValue *track_value = memnew(TrackCacheValue);
593
594 if (resource.is_valid()) {
595 track_value->object = resource.ptr();
596 } else {
597 track_value->object = child;
598 }
599
600 track_value->subpath = leftover_path;
601 track_value->object_id = track_value->object->get_instance_id();
602
603 track = track_value;
604
605 } break;
606 case Animation::TYPE_TRANSFORM: {
607
608 Spatial *spatial = Object::cast_to<Spatial>(child);
609
610 if (!spatial) {
611 ERR_PRINTS("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial: '" + String(path) + "'");
612 continue;
613 }
614
615 TrackCacheTransform *track_xform = memnew(TrackCacheTransform);
616
617 track_xform->spatial = spatial;
618 track_xform->skeleton = NULL;
619 track_xform->bone_idx = -1;
620
621 if (path.get_subname_count() == 1 && Object::cast_to<Skeleton>(spatial)) {
622
623 Skeleton *sk = Object::cast_to<Skeleton>(spatial);
624 int bone_idx = sk->find_bone(path.get_subname(0));
625 if (bone_idx != -1) {
626
627 track_xform->skeleton = sk;
628 track_xform->bone_idx = bone_idx;
629 }
630 }
631
632 track_xform->object = spatial;
633 track_xform->object_id = track_xform->object->get_instance_id();
634
635 track = track_xform;
636
637 } break;
638 case Animation::TYPE_METHOD: {
639
640 TrackCacheMethod *track_method = memnew(TrackCacheMethod);
641
642 if (resource.is_valid()) {
643 track_method->object = resource.ptr();
644 } else {
645 track_method->object = child;
646 }
647
648 track_method->object_id = track_method->object->get_instance_id();
649
650 track = track_method;
651
652 } break;
653 case Animation::TYPE_BEZIER: {
654
655 TrackCacheBezier *track_bezier = memnew(TrackCacheBezier);
656
657 if (resource.is_valid()) {
658 track_bezier->object = resource.ptr();
659 } else {
660 track_bezier->object = child;
661 }
662
663 track_bezier->subpath = leftover_path;
664 track_bezier->object_id = track_bezier->object->get_instance_id();
665
666 track = track_bezier;
667 } break;
668 case Animation::TYPE_AUDIO: {
669
670 TrackCacheAudio *track_audio = memnew(TrackCacheAudio);
671
672 track_audio->object = child;
673 track_audio->object_id = track_audio->object->get_instance_id();
674
675 track = track_audio;
676
677 } break;
678 case Animation::TYPE_ANIMATION: {
679
680 TrackCacheAnimation *track_animation = memnew(TrackCacheAnimation);
681
682 track_animation->object = child;
683 track_animation->object_id = track_animation->object->get_instance_id();
684
685 track = track_animation;
686
687 } break;
688 default: {
689 ERR_PRINT("Animation corrupted (invalid track type)");
690 continue;
691 }
692 }
693
694 track_cache[path] = track;
695 }
696
697 track->setup_pass = setup_pass;
698 }
699 }
700
701 List<NodePath> to_delete;
702
703 const NodePath *K = NULL;
704 while ((K = track_cache.next(K))) {
705 TrackCache *tc = track_cache[*K];
706 if (tc->setup_pass != setup_pass) {
707 to_delete.push_back(*K);
708 }
709 }
710
711 while (to_delete.front()) {
712 NodePath np = to_delete.front()->get();
713 memdelete(track_cache[np]);
714 track_cache.erase(np);
715 to_delete.pop_front();
716 }
717
718 state.track_map.clear();
719
720 K = NULL;
721 int idx = 0;
722 while ((K = track_cache.next(K))) {
723 state.track_map[*K] = idx;
724 idx++;
725 }
726
727 state.track_count = idx;
728
729 cache_valid = true;
730
731 return true;
732 }
733
_clear_caches()734 void AnimationTree::_clear_caches() {
735
736 const NodePath *K = NULL;
737 while ((K = track_cache.next(K))) {
738 memdelete(track_cache[*K]);
739 }
740 playing_caches.clear();
741
742 track_cache.clear();
743 cache_valid = false;
744 }
745
_process_graph(float p_delta)746 void AnimationTree::_process_graph(float p_delta) {
747
748 _update_properties(); //if properties need updating, update them
749
750 //check all tracks, see if they need modification
751
752 root_motion_transform = Transform();
753
754 if (!root.is_valid()) {
755 ERR_PRINT("AnimationTree: root AnimationNode is not set, disabling playback.");
756 set_active(false);
757 cache_valid = false;
758 return;
759 }
760
761 if (!has_node(animation_player)) {
762 ERR_PRINT("AnimationTree: no valid AnimationPlayer path set, disabling playback");
763 set_active(false);
764 cache_valid = false;
765 return;
766 }
767
768 AnimationPlayer *player = Object::cast_to<AnimationPlayer>(get_node(animation_player));
769
770 ObjectID current_animation_player = 0;
771
772 if (player) {
773 current_animation_player = player->get_instance_id();
774 }
775
776 if (last_animation_player != current_animation_player) {
777
778 if (last_animation_player) {
779 Object *old_player = ObjectDB::get_instance(last_animation_player);
780 if (old_player) {
781 old_player->disconnect("caches_cleared", this, "_clear_caches");
782 }
783 }
784
785 if (player) {
786 player->connect("caches_cleared", this, "_clear_caches");
787 }
788
789 last_animation_player = current_animation_player;
790 }
791
792 if (!player) {
793 ERR_PRINT("AnimationTree: path points to a node not an AnimationPlayer, disabling playback");
794 set_active(false);
795 cache_valid = false;
796 return;
797 }
798
799 if (!cache_valid) {
800 if (!_update_caches(player)) {
801 return;
802 }
803 }
804
805 { //setup
806
807 process_pass++;
808
809 state.valid = true;
810 state.invalid_reasons = "";
811 state.animation_states.clear(); //will need to be re-created
812 state.valid = true;
813 state.player = player;
814 state.last_pass = process_pass;
815 state.tree = this;
816
817 // root source blends
818
819 root->blends.resize(state.track_count);
820 float *src_blendsw = root->blends.ptrw();
821 for (int i = 0; i < state.track_count; i++) {
822 src_blendsw[i] = 1.0; //by default all go to 1 for the root input
823 }
824 }
825
826 //process
827
828 {
829
830 if (started) {
831 //if started, seek
832 root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, NULL, &state, 0, true, Vector<StringName>());
833 started = false;
834 }
835
836 root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, NULL, &state, p_delta, false, Vector<StringName>());
837 }
838
839 if (!state.valid) {
840 return; //state is not valid. do nothing.
841 }
842 //apply value/transform/bezier blends to track caches and execute method/audio/animation tracks
843
844 {
845
846 bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint();
847
848 for (List<AnimationNode::AnimationState>::Element *E = state.animation_states.front(); E; E = E->next()) {
849
850 const AnimationNode::AnimationState &as = E->get();
851
852 Ref<Animation> a = as.animation;
853 float time = as.time;
854 float delta = as.delta;
855 bool seeked = as.seeked;
856
857 for (int i = 0; i < a->get_track_count(); i++) {
858
859 NodePath path = a->track_get_path(i);
860
861 ERR_CONTINUE(!track_cache.has(path));
862
863 TrackCache *track = track_cache[path];
864 if (track->type != a->track_get_type(i)) {
865 continue; //may happen should not
866 }
867
868 track->root_motion = root_motion_track == path;
869
870 ERR_CONTINUE(!state.track_map.has(path));
871 int blend_idx = state.track_map[path];
872
873 ERR_CONTINUE(blend_idx < 0 || blend_idx >= state.track_count);
874
875 float blend = (*as.track_blends)[blend_idx];
876
877 if (blend < CMP_EPSILON)
878 continue; //nothing to blend
879
880 switch (track->type) {
881
882 case Animation::TYPE_TRANSFORM: {
883
884 TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
885
886 if (track->root_motion) {
887
888 if (t->process_pass != process_pass) {
889
890 t->process_pass = process_pass;
891 t->loc = Vector3();
892 t->rot = Quat();
893 t->rot_blend_accum = 0;
894 t->scale = Vector3(1, 1, 1);
895 }
896
897 float prev_time = time - delta;
898 if (prev_time < 0) {
899 if (!a->has_loop()) {
900 prev_time = 0;
901 } else {
902 prev_time = a->get_length() + prev_time;
903 }
904 }
905
906 Vector3 loc[2];
907 Quat rot[2];
908 Vector3 scale[2];
909
910 if (prev_time > time) {
911
912 Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
913 if (err != OK) {
914 continue;
915 }
916
917 a->transform_track_interpolate(i, a->get_length(), &loc[1], &rot[1], &scale[1]);
918
919 t->loc += (loc[1] - loc[0]) * blend;
920 t->scale += (scale[1] - scale[0]) * blend;
921 Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
922 t->rot = (t->rot * q).normalized();
923
924 prev_time = 0;
925 }
926
927 Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
928 if (err != OK) {
929 continue;
930 }
931
932 a->transform_track_interpolate(i, time, &loc[1], &rot[1], &scale[1]);
933
934 t->loc += (loc[1] - loc[0]) * blend;
935 t->scale += (scale[1] - scale[0]) * blend;
936 Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
937 t->rot = (t->rot * q).normalized();
938
939 prev_time = 0;
940
941 } else {
942 Vector3 loc;
943 Quat rot;
944 Vector3 scale;
945
946 Error err = a->transform_track_interpolate(i, time, &loc, &rot, &scale);
947 //ERR_CONTINUE(err!=OK); //used for testing, should be removed
948
949 if (t->process_pass != process_pass) {
950
951 t->process_pass = process_pass;
952 t->loc = loc;
953 t->rot = rot;
954 t->rot_blend_accum = 0;
955 t->scale = scale;
956 }
957
958 if (err != OK)
959 continue;
960
961 t->loc = t->loc.linear_interpolate(loc, blend);
962 if (t->rot_blend_accum == 0) {
963 t->rot = rot;
964 t->rot_blend_accum = blend;
965 } else {
966 float rot_total = t->rot_blend_accum + blend;
967 t->rot = rot.slerp(t->rot, t->rot_blend_accum / rot_total).normalized();
968 t->rot_blend_accum = rot_total;
969 }
970 t->scale = t->scale.linear_interpolate(scale, blend);
971 }
972
973 } break;
974 case Animation::TYPE_VALUE: {
975
976 TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
977
978 Animation::UpdateMode update_mode = a->value_track_get_update_mode(i);
979
980 if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { //delta == 0 means seek
981
982 Variant value = a->value_track_interpolate(i, time);
983
984 if (value == Variant())
985 continue;
986
987 if (t->process_pass != process_pass) {
988 t->value = value;
989 t->process_pass = process_pass;
990 }
991
992 Variant::interpolate(t->value, value, blend, t->value);
993
994 } else if (delta != 0) {
995
996 List<int> indices;
997 a->value_track_get_key_indices(i, time, delta, &indices);
998
999 for (List<int>::Element *F = indices.front(); F; F = F->next()) {
1000
1001 Variant value = a->track_get_key_value(i, F->get());
1002 t->object->set_indexed(t->subpath, value);
1003 }
1004 }
1005
1006 } break;
1007 case Animation::TYPE_METHOD: {
1008
1009 if (delta == 0) {
1010 continue;
1011 }
1012 TrackCacheMethod *t = static_cast<TrackCacheMethod *>(track);
1013
1014 List<int> indices;
1015
1016 a->method_track_get_key_indices(i, time, delta, &indices);
1017
1018 for (List<int>::Element *F = indices.front(); F; F = F->next()) {
1019
1020 StringName method = a->method_track_get_name(i, F->get());
1021 Vector<Variant> params = a->method_track_get_params(i, F->get());
1022
1023 int s = params.size();
1024
1025 ERR_CONTINUE(s > VARIANT_ARG_MAX);
1026 if (can_call) {
1027 t->object->call_deferred(
1028 method,
1029 s >= 1 ? params[0] : Variant(),
1030 s >= 2 ? params[1] : Variant(),
1031 s >= 3 ? params[2] : Variant(),
1032 s >= 4 ? params[3] : Variant(),
1033 s >= 5 ? params[4] : Variant());
1034 }
1035 }
1036
1037 } break;
1038 case Animation::TYPE_BEZIER: {
1039
1040 TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);
1041
1042 float bezier = a->bezier_track_interpolate(i, time);
1043
1044 if (t->process_pass != process_pass) {
1045 t->value = bezier;
1046 t->process_pass = process_pass;
1047 }
1048
1049 t->value = Math::lerp(t->value, bezier, blend);
1050
1051 } break;
1052 case Animation::TYPE_AUDIO: {
1053
1054 TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
1055
1056 if (seeked) {
1057 //find whathever should be playing
1058 int idx = a->track_find_key(i, time);
1059 if (idx < 0)
1060 continue;
1061
1062 Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
1063 if (!stream.is_valid()) {
1064 t->object->call("stop");
1065 t->playing = false;
1066 playing_caches.erase(t);
1067 } else {
1068 float start_ofs = a->audio_track_get_key_start_offset(i, idx);
1069 start_ofs += time - a->track_get_key_time(i, idx);
1070 float end_ofs = a->audio_track_get_key_end_offset(i, idx);
1071 float len = stream->get_length();
1072
1073 if (start_ofs > len - end_ofs) {
1074 t->object->call("stop");
1075 t->playing = false;
1076 playing_caches.erase(t);
1077 continue;
1078 }
1079
1080 t->object->call("set_stream", stream);
1081 t->object->call("play", start_ofs);
1082
1083 t->playing = true;
1084 playing_caches.insert(t);
1085 if (len && end_ofs > 0) { //force a end at a time
1086 t->len = len - start_ofs - end_ofs;
1087 } else {
1088 t->len = 0;
1089 }
1090
1091 t->start = time;
1092 }
1093
1094 } else {
1095 //find stuff to play
1096 List<int> to_play;
1097 a->track_get_key_indices_in_range(i, time, delta, &to_play);
1098 if (to_play.size()) {
1099 int idx = to_play.back()->get();
1100
1101 Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
1102 if (!stream.is_valid()) {
1103 t->object->call("stop");
1104 t->playing = false;
1105 playing_caches.erase(t);
1106 } else {
1107 float start_ofs = a->audio_track_get_key_start_offset(i, idx);
1108 float end_ofs = a->audio_track_get_key_end_offset(i, idx);
1109 float len = stream->get_length();
1110
1111 t->object->call("set_stream", stream);
1112 t->object->call("play", start_ofs);
1113
1114 t->playing = true;
1115 playing_caches.insert(t);
1116 if (len && end_ofs > 0) { //force a end at a time
1117 t->len = len - start_ofs - end_ofs;
1118 } else {
1119 t->len = 0;
1120 }
1121
1122 t->start = time;
1123 }
1124 } else if (t->playing) {
1125
1126 bool loop = a->has_loop();
1127
1128 bool stop = false;
1129
1130 if (!loop && time < t->start) {
1131 stop = true;
1132 } else if (t->len > 0) {
1133 float len = t->start > time ? (a->get_length() - t->start) + time : time - t->start;
1134
1135 if (len > t->len) {
1136 stop = true;
1137 }
1138 }
1139
1140 if (stop) {
1141 //time to stop
1142 t->object->call("stop");
1143 t->playing = false;
1144 playing_caches.erase(t);
1145 }
1146 }
1147 }
1148
1149 float db = Math::linear2db(MAX(blend, 0.00001));
1150 if (t->object->has_method("set_unit_db")) {
1151 t->object->call("set_unit_db", db);
1152 } else {
1153 t->object->call("set_volume_db", db);
1154 }
1155 } break;
1156 case Animation::TYPE_ANIMATION: {
1157
1158 TrackCacheAnimation *t = static_cast<TrackCacheAnimation *>(track);
1159
1160 AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t->object);
1161
1162 if (!player2)
1163 continue;
1164
1165 if (delta == 0 || seeked) {
1166 //seek
1167 int idx = a->track_find_key(i, time);
1168 if (idx < 0)
1169 continue;
1170
1171 float pos = a->track_get_key_time(i, idx);
1172
1173 StringName anim_name = a->animation_track_get_key_animation(i, idx);
1174 if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name))
1175 continue;
1176
1177 Ref<Animation> anim = player2->get_animation(anim_name);
1178
1179 float at_anim_pos;
1180
1181 if (anim->has_loop()) {
1182 at_anim_pos = Math::fposmod(time - pos, anim->get_length()); //seek to loop
1183 } else {
1184 at_anim_pos = MAX(anim->get_length(), time - pos); //seek to end
1185 }
1186
1187 if (player2->is_playing() || seeked) {
1188 player2->play(anim_name);
1189 player2->seek(at_anim_pos);
1190 t->playing = true;
1191 playing_caches.insert(t);
1192 } else {
1193 player2->set_assigned_animation(anim_name);
1194 player2->seek(at_anim_pos, true);
1195 }
1196 } else {
1197 //find stuff to play
1198 List<int> to_play;
1199 a->track_get_key_indices_in_range(i, time, delta, &to_play);
1200 if (to_play.size()) {
1201 int idx = to_play.back()->get();
1202
1203 StringName anim_name = a->animation_track_get_key_animation(i, idx);
1204 if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) {
1205
1206 if (playing_caches.has(t)) {
1207 playing_caches.erase(t);
1208 player2->stop();
1209 t->playing = false;
1210 }
1211 } else {
1212 player2->play(anim_name);
1213 t->playing = true;
1214 playing_caches.insert(t);
1215 }
1216 }
1217 }
1218
1219 } break;
1220 }
1221 }
1222 }
1223 }
1224
1225 {
1226 // finally, set the tracks
1227 const NodePath *K = NULL;
1228 while ((K = track_cache.next(K))) {
1229 TrackCache *track = track_cache[*K];
1230 if (track->process_pass != process_pass)
1231 continue; //not processed, ignore
1232
1233 switch (track->type) {
1234
1235 case Animation::TYPE_TRANSFORM: {
1236
1237 TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
1238
1239 Transform xform;
1240 xform.origin = t->loc;
1241
1242 xform.basis.set_quat_scale(t->rot, t->scale);
1243
1244 if (t->root_motion) {
1245
1246 root_motion_transform = xform;
1247
1248 if (t->skeleton && t->bone_idx >= 0) {
1249 root_motion_transform = (t->skeleton->get_bone_rest(t->bone_idx) * root_motion_transform) * t->skeleton->get_bone_rest(t->bone_idx).affine_inverse();
1250 }
1251 } else if (t->skeleton && t->bone_idx >= 0) {
1252
1253 t->skeleton->set_bone_pose(t->bone_idx, xform);
1254
1255 } else {
1256
1257 t->spatial->set_transform(xform);
1258 }
1259
1260 } break;
1261 case Animation::TYPE_VALUE: {
1262
1263 TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
1264
1265 t->object->set_indexed(t->subpath, t->value);
1266
1267 } break;
1268 case Animation::TYPE_BEZIER: {
1269
1270 TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);
1271
1272 t->object->set_indexed(t->subpath, t->value);
1273
1274 } break;
1275 default: {
1276 } //the rest don't matter
1277 }
1278 }
1279 }
1280 }
1281
advance(float p_time)1282 void AnimationTree::advance(float p_time) {
1283
1284 _process_graph(p_time);
1285 }
1286
_notification(int p_what)1287 void AnimationTree::_notification(int p_what) {
1288
1289 if (active && p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS && process_mode == ANIMATION_PROCESS_PHYSICS) {
1290 _process_graph(get_physics_process_delta_time());
1291 }
1292
1293 if (active && p_what == NOTIFICATION_INTERNAL_PROCESS && process_mode == ANIMATION_PROCESS_IDLE) {
1294 _process_graph(get_process_delta_time());
1295 }
1296
1297 if (p_what == NOTIFICATION_EXIT_TREE) {
1298 _clear_caches();
1299 if (last_animation_player) {
1300
1301 Object *player = ObjectDB::get_instance(last_animation_player);
1302 if (player) {
1303 player->disconnect("caches_cleared", this, "_clear_caches");
1304 }
1305 }
1306 } else if (p_what == NOTIFICATION_ENTER_TREE) {
1307 if (last_animation_player) {
1308
1309 Object *player = ObjectDB::get_instance(last_animation_player);
1310 if (player) {
1311 player->connect("caches_cleared", this, "_clear_caches");
1312 }
1313 }
1314 }
1315 }
1316
set_animation_player(const NodePath & p_player)1317 void AnimationTree::set_animation_player(const NodePath &p_player) {
1318 animation_player = p_player;
1319 update_configuration_warning();
1320 }
1321
get_animation_player() const1322 NodePath AnimationTree::get_animation_player() const {
1323 return animation_player;
1324 }
1325
is_state_invalid() const1326 bool AnimationTree::is_state_invalid() const {
1327
1328 return !state.valid;
1329 }
get_invalid_state_reason() const1330 String AnimationTree::get_invalid_state_reason() const {
1331
1332 return state.invalid_reasons;
1333 }
1334
get_last_process_pass() const1335 uint64_t AnimationTree::get_last_process_pass() const {
1336 return process_pass;
1337 }
1338
get_configuration_warning() const1339 String AnimationTree::get_configuration_warning() const {
1340
1341 String warning = Node::get_configuration_warning();
1342
1343 if (!root.is_valid()) {
1344 if (warning != String()) {
1345 warning += "\n\n";
1346 }
1347 warning += TTR("No root AnimationNode for the graph is set.");
1348 }
1349
1350 if (!has_node(animation_player)) {
1351
1352 if (warning != String()) {
1353 warning += "\n\n";
1354 }
1355
1356 warning += TTR("Path to an AnimationPlayer node containing animations is not set.");
1357 return warning;
1358 }
1359
1360 AnimationPlayer *player = Object::cast_to<AnimationPlayer>(get_node(animation_player));
1361
1362 if (!player) {
1363 if (warning != String()) {
1364 warning += "\n\n";
1365 }
1366
1367 warning += TTR("Path set for AnimationPlayer does not lead to an AnimationPlayer node.");
1368 return warning;
1369 }
1370
1371 if (!player->has_node(player->get_root())) {
1372 if (warning != String()) {
1373 warning += "\n\n";
1374 }
1375
1376 warning += TTR("The AnimationPlayer root node is not a valid node.");
1377 return warning;
1378 }
1379
1380 return warning;
1381 }
1382
set_root_motion_track(const NodePath & p_track)1383 void AnimationTree::set_root_motion_track(const NodePath &p_track) {
1384 root_motion_track = p_track;
1385 }
1386
get_root_motion_track() const1387 NodePath AnimationTree::get_root_motion_track() const {
1388 return root_motion_track;
1389 }
1390
get_root_motion_transform() const1391 Transform AnimationTree::get_root_motion_transform() const {
1392 return root_motion_transform;
1393 }
1394
_tree_changed()1395 void AnimationTree::_tree_changed() {
1396 if (properties_dirty) {
1397 return;
1398 }
1399
1400 call_deferred("_update_properties");
1401 properties_dirty = true;
1402 }
1403
_update_properties_for_node(const String & p_base_path,Ref<AnimationNode> node)1404 void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<AnimationNode> node) {
1405
1406 if (!property_parent_map.has(p_base_path)) {
1407 property_parent_map[p_base_path] = HashMap<StringName, StringName>();
1408 }
1409
1410 if (node->get_input_count() && !input_activity_map.has(p_base_path)) {
1411
1412 Vector<Activity> activity;
1413 for (int i = 0; i < node->get_input_count(); i++) {
1414 Activity a;
1415 a.activity = 0;
1416 a.last_pass = 0;
1417 activity.push_back(a);
1418 }
1419 input_activity_map[p_base_path] = activity;
1420 input_activity_map_get[String(p_base_path).substr(0, String(p_base_path).length() - 1)] = &input_activity_map[p_base_path];
1421 }
1422
1423 List<PropertyInfo> plist;
1424 node->get_parameter_list(&plist);
1425 for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
1426 PropertyInfo pinfo = E->get();
1427
1428 StringName key = pinfo.name;
1429
1430 if (!property_map.has(p_base_path + key)) {
1431 property_map[p_base_path + key] = node->get_parameter_default_value(key);
1432 }
1433
1434 property_parent_map[p_base_path][key] = p_base_path + key;
1435
1436 pinfo.name = p_base_path + key;
1437 properties.push_back(pinfo);
1438 }
1439
1440 List<AnimationNode::ChildNode> children;
1441 node->get_child_nodes(&children);
1442
1443 for (List<AnimationNode::ChildNode>::Element *E = children.front(); E; E = E->next()) {
1444 _update_properties_for_node(p_base_path + E->get().name + "/", E->get().node);
1445 }
1446 }
1447
_update_properties()1448 void AnimationTree::_update_properties() {
1449 if (!properties_dirty) {
1450 return;
1451 }
1452
1453 properties.clear();
1454 property_parent_map.clear();
1455 input_activity_map.clear();
1456 input_activity_map_get.clear();
1457
1458 if (root.is_valid()) {
1459 _update_properties_for_node(SceneStringNames::get_singleton()->parameters_base_path, root);
1460 }
1461
1462 properties_dirty = false;
1463
1464 _change_notify();
1465 }
1466
_set(const StringName & p_name,const Variant & p_value)1467 bool AnimationTree::_set(const StringName &p_name, const Variant &p_value) {
1468 if (properties_dirty) {
1469 _update_properties();
1470 }
1471
1472 if (property_map.has(p_name)) {
1473 property_map[p_name] = p_value;
1474 #ifdef TOOLS_ENABLED
1475 _change_notify(p_name.operator String().utf8().get_data());
1476 #endif
1477 return true;
1478 }
1479
1480 return false;
1481 }
1482
_get(const StringName & p_name,Variant & r_ret) const1483 bool AnimationTree::_get(const StringName &p_name, Variant &r_ret) const {
1484 if (properties_dirty) {
1485 const_cast<AnimationTree *>(this)->_update_properties();
1486 }
1487
1488 if (property_map.has(p_name)) {
1489 r_ret = property_map[p_name];
1490 return true;
1491 }
1492
1493 return false;
1494 }
_get_property_list(List<PropertyInfo> * p_list) const1495 void AnimationTree::_get_property_list(List<PropertyInfo> *p_list) const {
1496 if (properties_dirty) {
1497 const_cast<AnimationTree *>(this)->_update_properties();
1498 }
1499
1500 for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
1501 p_list->push_back(E->get());
1502 }
1503 }
1504
rename_parameter(const String & p_base,const String & p_new_base)1505 void AnimationTree::rename_parameter(const String &p_base, const String &p_new_base) {
1506
1507 //rename values first
1508 for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
1509 if (E->get().name.begins_with(p_base)) {
1510 String new_name = E->get().name.replace_first(p_base, p_new_base);
1511 property_map[new_name] = property_map[E->get().name];
1512 }
1513 }
1514
1515 //update tree second
1516 properties_dirty = true;
1517 _update_properties();
1518 }
1519
get_connection_activity(const StringName & p_path,int p_connection) const1520 float AnimationTree::get_connection_activity(const StringName &p_path, int p_connection) const {
1521
1522 if (!input_activity_map_get.has(p_path)) {
1523 return 0;
1524 }
1525 const Vector<Activity> *activity = input_activity_map_get[p_path];
1526
1527 if (!activity || p_connection < 0 || p_connection >= activity->size()) {
1528 return 0;
1529 }
1530
1531 if ((*activity)[p_connection].last_pass != process_pass) {
1532 return 0;
1533 }
1534
1535 return (*activity)[p_connection].activity;
1536 }
1537
_bind_methods()1538 void AnimationTree::_bind_methods() {
1539 ClassDB::bind_method(D_METHOD("set_active", "active"), &AnimationTree::set_active);
1540 ClassDB::bind_method(D_METHOD("is_active"), &AnimationTree::is_active);
1541
1542 ClassDB::bind_method(D_METHOD("set_tree_root", "root"), &AnimationTree::set_tree_root);
1543 ClassDB::bind_method(D_METHOD("get_tree_root"), &AnimationTree::get_tree_root);
1544
1545 ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &AnimationTree::set_process_mode);
1546 ClassDB::bind_method(D_METHOD("get_process_mode"), &AnimationTree::get_process_mode);
1547
1548 ClassDB::bind_method(D_METHOD("set_animation_player", "root"), &AnimationTree::set_animation_player);
1549 ClassDB::bind_method(D_METHOD("get_animation_player"), &AnimationTree::get_animation_player);
1550
1551 ClassDB::bind_method(D_METHOD("set_root_motion_track", "path"), &AnimationTree::set_root_motion_track);
1552 ClassDB::bind_method(D_METHOD("get_root_motion_track"), &AnimationTree::get_root_motion_track);
1553
1554 ClassDB::bind_method(D_METHOD("get_root_motion_transform"), &AnimationTree::get_root_motion_transform);
1555
1556 ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationTree::_tree_changed);
1557 ClassDB::bind_method(D_METHOD("_update_properties"), &AnimationTree::_update_properties);
1558
1559 ClassDB::bind_method(D_METHOD("rename_parameter", "old_name", "new_name"), &AnimationTree::rename_parameter);
1560
1561 ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationTree::advance);
1562
1563 ClassDB::bind_method(D_METHOD("_node_removed"), &AnimationTree::_node_removed);
1564 ClassDB::bind_method(D_METHOD("_clear_caches"), &AnimationTree::_clear_caches);
1565
1566 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tree_root", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode"), "set_tree_root", "get_tree_root");
1567 ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "anim_player", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationPlayer"), "set_animation_player", "get_animation_player");
1568 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active");
1569 ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_mode", "get_process_mode");
1570 ADD_GROUP("Root Motion", "root_motion_");
1571 ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_motion_track"), "set_root_motion_track", "get_root_motion_track");
1572
1573 BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS);
1574 BIND_ENUM_CONSTANT(ANIMATION_PROCESS_IDLE);
1575 BIND_ENUM_CONSTANT(ANIMATION_PROCESS_MANUAL);
1576 }
1577
AnimationTree()1578 AnimationTree::AnimationTree() {
1579
1580 process_mode = ANIMATION_PROCESS_IDLE;
1581 active = false;
1582 cache_valid = false;
1583 setup_pass = 1;
1584 process_pass = 1;
1585 started = true;
1586 properties_dirty = true;
1587 last_animation_player = 0;
1588 }
1589
~AnimationTree()1590 AnimationTree::~AnimationTree() {
1591 }
1592