void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) { Node *parent = get_node(root); ERR_FAIL_COND(!parent); Animation *a = p_anim->animation.operator->(); p_anim->node_cache.resize(a->get_track_count()); for (int i = 0; i < a->get_track_count(); i++) { p_anim->node_cache[i] = NULL; RES resource; Node *child = parent->get_node_and_resource(a->track_get_path(i), resource); if (!child) { ERR_EXPLAIN("On Animation: '" + p_anim->name + "', couldn't resolve track: '" + String(a->track_get_path(i)) + "'"); } ERR_CONTINUE(!child); // couldn't find the child node uint32_t id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id(); int bone_idx = -1; if (a->track_get_path(i).get_property() && Object::cast_to<Skeleton>(child)) { bone_idx = Object::cast_to<Skeleton>(child)->find_bone(a->track_get_path(i).get_property()); if (bone_idx == -1) { continue; } } { if (!child->is_connected("tree_exited", this, "_node_removed")) child->connect("tree_exited", this, "_node_removed", make_binds(child), CONNECT_ONESHOT); } TrackNodeCacheKey key; key.id = id; key.bone_idx = bone_idx; if (node_cache_map.has(key)) { p_anim->node_cache[i] = &node_cache_map[key]; } else { node_cache_map[key] = TrackNodeCache(); p_anim->node_cache[i] = &node_cache_map[key]; p_anim->node_cache[i]->path = a->track_get_path(i); p_anim->node_cache[i]->node = child; p_anim->node_cache[i]->resource = resource; p_anim->node_cache[i]->node_2d = Object::cast_to<Node2D>(child); if (a->track_get_type(i) == Animation::TYPE_TRANSFORM) { // special cases and caches for transform tracks // cache spatial p_anim->node_cache[i]->spatial = Object::cast_to<Spatial>(child); // cache skeleton p_anim->node_cache[i]->skeleton = Object::cast_to<Skeleton>(child); if (p_anim->node_cache[i]->skeleton) { StringName bone_name = a->track_get_path(i).get_property(); if (bone_name.operator String() != "") { p_anim->node_cache[i]->bone_idx = p_anim->node_cache[i]->skeleton->find_bone(bone_name); if (p_anim->node_cache[i]->bone_idx < 0) { // broken track (nonexistent bone) p_anim->node_cache[i]->skeleton = NULL; p_anim->node_cache[i]->spatial = NULL; printf("bone is %ls\n", String(bone_name).c_str()); ERR_CONTINUE(p_anim->node_cache[i]->bone_idx < 0); } else { } } else { // no property, just use spatialnode p_anim->node_cache[i]->skeleton = NULL; } } } } if (a->track_get_type(i) == Animation::TYPE_VALUE) { StringName property = a->track_get_path(i).get_property(); if (!p_anim->node_cache[i]->property_anim.has(property)) { TrackNodeCache::PropertyAnim pa; pa.prop = property; pa.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child; pa.special = SP_NONE; pa.owner = p_anim->node_cache[i]; if (false && p_anim->node_cache[i]->node_2d) { if (pa.prop == SceneStringNames::get_singleton()->transform_pos) pa.special = SP_NODE2D_POS; else if (pa.prop == SceneStringNames::get_singleton()->transform_rot) pa.special = SP_NODE2D_ROT; else if (pa.prop == SceneStringNames::get_singleton()->transform_scale) pa.special = SP_NODE2D_SCALE; } p_anim->node_cache[i]->property_anim[property] = pa; } } } }