Example #1
0
Error ResourceSaver::save(const String &p_path,const RES& p_resource,uint32_t p_flags) {
		
	String extension=p_path.extension();
	Error err=ERR_FILE_UNRECOGNIZED;

	for (int i=0;i<saver_count;i++) {
		
		if (!saver[i]->recognize(p_resource))
			continue;
			
		List<String> extensions;
		bool recognized=false;
		saver[i]->get_recognized_extensions(p_resource,&extensions);
				
		for (List<String>::Element *E=extensions.front();E;E=E->next()) {
		
			if (E->get().nocasecmp_to(extension.extension())==0)
				recognized=true;
		}

		if (!recognized)
			continue;
		
		String old_path=p_resource->get_path();
		

		String local_path=Globals::get_singleton()->localize_path(p_path);

		RES rwcopy = p_resource;
		if (p_flags&FLAG_CHANGE_PATH)
			rwcopy->set_path(local_path);

		err = saver[i]->save(p_path,p_resource,p_flags);

		if (err == OK ) {

#ifdef TOOLS_ENABLED

			((Resource*)p_resource.ptr())->set_edited(false);
			if (timestamp_on_save) {
				uint64_t mt = FileAccess::get_modified_time(p_path);

				((Resource*)p_resource.ptr())->set_last_modified_time(mt);
			}
#endif

			if (p_flags&FLAG_CHANGE_PATH)
				rwcopy->set_path(old_path);

			if (save_callback && p_path.begins_with("res://"))
				save_callback(p_path);

			return OK;
		} else {
		
		}
	}
	
	return err;
}
Example #2
0
bool AnimationTree::_update_caches(AnimationPlayer *player) {

	setup_pass++;

	if (!player->has_node(player->get_root())) {
		ERR_PRINT("AnimationTree: AnimationPlayer root is invalid.");
		set_active(false);
		return false;
	}
	Node *parent = player->get_node(player->get_root());

	List<StringName> sname;
	player->get_animation_list(&sname);

	for (List<StringName>::Element *E = sname.front(); E; E = E->next()) {
		Ref<Animation> anim = player->get_animation(E->get());
		for (int i = 0; i < anim->get_track_count(); i++) {
			NodePath path = anim->track_get_path(i);
			Animation::TrackType track_type = anim->track_get_type(i);

			TrackCache *track = NULL;
			if (track_cache.has(path)) {
				track = track_cache.get(path);
			}

			//if not valid, delete track
			if (track && (track->type != track_type || ObjectDB::get_instance(track->object_id) == NULL)) {
				playing_caches.erase(track);
				memdelete(track);
				track_cache.erase(path);
				track = NULL;
			}

			if (!track) {

				RES resource;
				Vector<StringName> leftover_path;
				Node *child = parent->get_node_and_resource(path, resource, leftover_path);

				if (!child) {
					ERR_PRINTS("AnimationTree: '" + String(E->get()) + "', couldn't resolve track:  '" + String(path) + "'");
					continue;
				}

				if (!child->is_connected("tree_exited", this, "_node_removed")) {
					child->connect("tree_exited", this, "_node_removed", varray(child));
				}

				switch (track_type) {
					case Animation::TYPE_VALUE: {

						TrackCacheValue *track_value = memnew(TrackCacheValue);

						if (resource.is_valid()) {
							track_value->object = resource.ptr();
						} else {
							track_value->object = child;
						}

						track_value->subpath = leftover_path;
						track_value->object_id = track_value->object->get_instance_id();

						track = track_value;

					} break;
					case Animation::TYPE_TRANSFORM: {

						Spatial *spatial = Object::cast_to<Spatial>(child);

						if (!spatial) {
							ERR_PRINTS("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial:  '" + String(path) + "'");
							continue;
						}

						TrackCacheTransform *track_xform = memnew(TrackCacheTransform);

						track_xform->spatial = spatial;
						track_xform->skeleton = NULL;
						track_xform->bone_idx = -1;

						if (path.get_subname_count() == 1 && Object::cast_to<Skeleton>(spatial)) {

							Skeleton *sk = Object::cast_to<Skeleton>(spatial);
							int bone_idx = sk->find_bone(path.get_subname(0));
							if (bone_idx != -1 && !sk->is_bone_ignore_animation(bone_idx)) {

								track_xform->skeleton = sk;
								track_xform->bone_idx = bone_idx;
							}
						}

						track_xform->object = spatial;
						track_xform->object_id = track_xform->object->get_instance_id();

						track = track_xform;

					} break;
					case Animation::TYPE_METHOD: {

						TrackCacheMethod *track_method = memnew(TrackCacheMethod);

						if (resource.is_valid()) {
							track_method->object = resource.ptr();
						} else {
							track_method->object = child;
						}

						track_method->object_id = track_method->object->get_instance_id();

						track = track_method;

					} break;
					case Animation::TYPE_BEZIER: {

						TrackCacheBezier *track_bezier = memnew(TrackCacheBezier);

						if (resource.is_valid()) {
							track_bezier->object = resource.ptr();
						} else {
							track_bezier->object = child;
						}

						track_bezier->subpath = leftover_path;
						track_bezier->object_id = track_bezier->object->get_instance_id();

						track = track_bezier;
					} break;
					case Animation::TYPE_AUDIO: {

						TrackCacheAudio *track_audio = memnew(TrackCacheAudio);

						track_audio->object = child;
						track_audio->object_id = track_audio->object->get_instance_id();

						track = track_audio;

					} break;
					case Animation::TYPE_ANIMATION: {

						TrackCacheAnimation *track_animation = memnew(TrackCacheAnimation);

						track_animation->object = child;
						track_animation->object_id = track_animation->object->get_instance_id();

						track = track_animation;

					} break;
					default: {
						ERR_PRINT("Animation corrupted (invalid track type)");
						continue;
					}
				}

				track_cache[path] = track;
			}

			track->setup_pass = setup_pass;
		}
	}

	List<NodePath> to_delete;

	const NodePath *K = NULL;
	while ((K = track_cache.next(K))) {
		TrackCache *tc = track_cache[*K];
		if (tc->setup_pass != setup_pass) {
			to_delete.push_back(*K);
		}
	}

	while (to_delete.front()) {
		NodePath np = to_delete.front()->get();
		memdelete(track_cache[np]);
		track_cache.erase(np);
		to_delete.pop_front();
	}

	state.track_map.clear();

	K = NULL;
	int idx = 0;
	while ((K = track_cache.next(K))) {
		state.track_map[*K] = idx;
		idx++;
	}

	state.track_count = idx;

	cache_valid = true;

	return true;
}
Example #3
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;
			}
		}
	}
}
Example #4
0
void AnimationCache::_update_cache() {

	cache_valid=false;

	ERR_FAIL_COND(!root);
	ERR_FAIL_COND(!root->is_inside_tree());
	ERR_FAIL_COND(animation.is_null());

	for(int i=0;i<animation->get_track_count();i++) {



		NodePath np = animation->track_get_path(i);

		Node *node = root->get_node(np);
		if (!node) {

			path_cache.push_back(Path());
			ERR_EXPLAIN("Invalid Track Path in Animation: "+np);
			ERR_CONTINUE(!node);
		}


		Path path;

		Ref<Resource> res;

		if (np.get_subname_count()) {


			if (animation->track_get_type(i)==Animation::TYPE_TRANSFORM) {

				path_cache.push_back(Path());
				ERR_EXPLAIN("Transform tracks can't have a subpath: "+np);
				ERR_CONTINUE(animation->track_get_type(i)==Animation::TYPE_TRANSFORM);

			}

			RES res;

			for(int j=0;j<np.get_subname_count();j++) {
				res = j==0 ? node->get(np.get_subname(j)) : res->get(np.get_subname(j));
				if (res.is_null())
					break;

			}

			if (res.is_null()) {

				path_cache.push_back(Path());
				ERR_EXPLAIN("Invalid Track SubPath in Animation: "+np);
				ERR_CONTINUE(res.is_null());
			}

			path.resource=res;
			path.object=res.ptr();

		} else {


			if (animation->track_get_type(i)==Animation::TYPE_TRANSFORM) {
				StringName property = np.get_property();
				String ps = property;


				Spatial *sp = node->cast_to<Spatial>();

				if (!sp) {

					path_cache.push_back(Path());
					ERR_EXPLAIN("Transform track not of type Spatial: "+np);
					ERR_CONTINUE(!sp);
				}

				if (ps!="") {

					Skeleton *sk = node->cast_to<Skeleton>();
					if (!sk) {

						path_cache.push_back(Path());
						ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton!: "+np);
						ERR_CONTINUE(!sk);
					}

					int idx = sk->find_bone(ps);
					if (idx==-1) {

						path_cache.push_back(Path());
						ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton Bone!: "+np);
						ERR_CONTINUE(idx==-1);

					}

					path.bone_idx=idx;
					path.skeleton=sk;

				}

				path.spatial=sp;

			}

			path.node=node;
			path.object=node;

		}

		if (animation->track_get_type(i)==Animation::TYPE_VALUE) {

			if (np.get_property().operator String()=="") {

				path_cache.push_back(Path());
				ERR_EXPLAIN("Value Track lacks property: "+np);
				ERR_CONTINUE(np.get_property().operator String()=="");

			}

			path.property=np.get_property();

		} else if (animation->track_get_type(i)==Animation::TYPE_METHOD) {

			if (np.get_property().operator String()!="") {

				path_cache.push_back(Path());
				ERR_EXPLAIN("Method Track has property: "+np);
				ERR_CONTINUE(np.get_property().operator String()!="");

			}

		}


		path.valid=true;

		path_cache.push_back(path);

		if (!connected_nodes.has(path.node)) {
			connected_nodes.insert(path.node);
			path.node->connect("exit_tree",this,"_node_exit_tree",Node::make_binds(path.node),CONNECT_ONESHOT);
		}



	}



	cache_dirty=false;
	cache_valid=true;
}