Пример #1
0
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;
			}
		}
	}
}