Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path) {

	RES res = ResourceLoader::load(p_path);
	if (!res.is_valid())
		return res;
	return generate(res);
}
bool ResourcePreloaderEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {

	Dictionary d = p_data;

	if (!d.has("type"))
		return false;

	if (d.has("from") && (Object *)(d["from"]) == tree)
		return false;

	if (String(d["type"]) == "resource" && d.has("resource")) {
		RES r = d["resource"];

		return r.is_valid();
	}

	if (String(d["type"]) == "files") {

		Vector<String> files = d["files"];

		if (files.size() == 0)
			return false;

		return true;
	}
	return false;
}
void ResourcePreloaderEditor::_paste_pressed() {

	RES r = EditorSettings::get_singleton()->get_resource_clipboard();
	if (!r.is_valid()) {
		dialog->set_text(TTR("Resource clipboard is empty!"));
		dialog->set_title(TTR("Error!"));
		dialog->get_ok()->set_text(TTR("Close"));
		dialog->popup_centered_minsize();
		return; ///beh should show an error i guess
	}

	String name = r->get_name();
	if (name == "")
		name = r->get_path().get_file();
	if (name == "")
		name = r->get_class();

	String basename = name;
	int counter = 1;
	while (preloader->has_resource(name)) {
		counter++;
		name = basename + " " + itos(counter);
	}

	undo_redo->create_action(TTR("Paste Resource"));
	undo_redo->add_do_method(preloader, "add_resource", name, r);
	undo_redo->add_undo_method(preloader, "remove_resource", name);
	undo_redo->add_do_method(this, "_update_library");
	undo_redo->add_undo_method(this, "_update_library");
	undo_redo->commit_action();
}
Example #4
0
Ref<Resource> Resource::duplicate(bool p_subresources) {

	List<PropertyInfo> plist;
	get_property_list(&plist);


	Resource *r = (Resource*)ObjectTypeDB::instance(get_type());
	ERR_FAIL_COND_V(!r,Ref<Resource>());

	for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {

		if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
			continue;
		Variant p = get(E->get().name);
		if (p.get_type()==Variant::OBJECT && p_subresources) {

			RES sr = p;
			if (sr.is_valid())
				p=sr->duplicate(true);
		}

		r->set(E->get().name,p);
	}

	return Ref<Resource>(r);
}
Example #5
0
void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource> > &remap_cache) {

	print_line("configure for local: " + get_class());
	List<PropertyInfo> plist;
	get_property_list(&plist);

	local_scene = p_for_scene;

	for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {

		if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
			continue;
		Variant p = get(E->get().name);
		if (p.get_type() == Variant::OBJECT) {

			RES sr = p;
			if (sr.is_valid()) {

				if (sr->is_local_to_scene()) {
					if (!remap_cache.has(sr)) {
						sr->configure_for_local_scene(p_for_scene, remap_cache);
						remap_cache[sr] = sr;
					}
				}
			}
		}
	}
}
Example #6
0
Object *EditorData::script_class_instance(const String &p_class) {
	if (ScriptServer::is_global_class(p_class)) {
		Object *obj = ClassDB::instance(ScriptServer::get_global_class_base(p_class));
		if (obj) {
			RES script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class));
			if (script.is_valid())
				obj->set_script(script.get_ref_ptr());

			RES icon = ResourceLoader::load(script_class_get_icon_path(p_class));
			if (icon.is_valid())
				obj->set_meta("_editor_icon", icon);

			return obj;
		}
	}
	return NULL;
}
Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String &p_path, const Size2 p_size) const {

	if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) {
		return get_script_instance()->call("generate_from_path", p_path, p_size);
	}

	RES res = ResourceLoader::load(p_path);
	if (!res.is_valid())
		return res;
	return generate(res, p_size);
}
Variant ResourcePreloaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {

	TreeItem *ti = tree->get_item_at_position(p_point);
	if (!ti)
		return Variant();

	String name = ti->get_metadata(0);

	RES res = preloader->get_resource(name);
	if (!res.is_valid())
		return Variant();

	return EditorNode::get_singleton()->drag_resource(res, p_from);
}
void ResourcePreloaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {

	if (!can_drop_data_fw(p_point, p_data, p_from))
		return;

	Dictionary d = p_data;

	if (!d.has("type"))
		return;

	if (String(d["type"]) == "resource" && d.has("resource")) {
		RES r = d["resource"];

		if (r.is_valid()) {

			String basename;
			if (r->get_name() != "") {
				basename = r->get_name();
			} else if (r->get_path().is_resource_file()) {
				basename = r->get_path().get_basename();
			} else {
				basename = "Resource";
			}

			String name = basename;
			int counter = 0;
			while (preloader->has_resource(name)) {
				counter++;
				name = basename + "_" + itos(counter);
			}

			undo_redo->create_action(TTR("Add Resource"));
			undo_redo->add_do_method(preloader, "add_resource", name, r);
			undo_redo->add_undo_method(preloader, "remove_resource", name);
			undo_redo->add_do_method(this, "_update_library");
			undo_redo->add_undo_method(this, "_update_library");
			undo_redo->commit_action();
		}
	}

	if (String(d["type"]) == "files") {

		Vector<String> files = d["files"];

		_files_load_request(files);
	}
}
Example #10
0
void Object::_clear_internal_resource_paths(const Variant &p_var) {

	switch(p_var.get_type()) {

		case Variant::OBJECT: {

			RES r = p_var;
			if (!r.is_valid())
				return;

			if (!r->get_path().begins_with("res://") || r->get_path().find("::")==-1)
				return; //not an internal resource

			Object *object=p_var;
			if (!object)
				return;

			r->set_path("");
			r->clear_internal_resource_paths();
		} break;
		case Variant::ARRAY: {

			Array a=p_var;
			for(int i=0;i<a.size();i++) {
				_clear_internal_resource_paths(a[i]);
			}

		} break;
		case Variant::DICTIONARY: {

			Dictionary d=p_var;
			List<Variant> keys;
			d.get_key_list(&keys);

			for (List<Variant>::Element *E=keys.front();E;E=E->next()) {

				_clear_internal_resource_paths(E->get());
				_clear_internal_resource_paths(d[E->get()]);
			}
		} break;
		default: {}
	}

}
Example #11
0
uint32_t Resource::hash_edited_version() const {

	uint32_t hash = hash_djb2_one_32(get_edited_version());

	List<PropertyInfo> plist;
	get_property_list(&plist);

	for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {

		if (E->get().type == Variant::OBJECT && E->get().hint == PROPERTY_HINT_RESOURCE_TYPE) {
			RES res = get(E->get().name);
			if (res.is_valid()) {
				hash = hash_djb2_one_32(res->hash_edited_version(), hash);
			}
		}
	}

	return hash;
}
Example #12
0
Array Node::_get_node_and_resource(const NodePath& p_path) {

	Node *node;
	RES res;
	node = get_node_and_resource(p_path,res);
	Array result;

	if (node)
		result.push_back(node);
	else
		result.push_back(Variant());

	if (res.is_valid())
		result.push_back(res);
	else
		result.push_back(Variant());

	return result;
}
Example #13
0
void ResourcePreloader::_set_resources(const Array& p_data) {

	resources.clear();

	ERR_FAIL_COND(p_data.size()!=2);
	DVector<String> names=p_data[0];
	Array resdata=p_data[1];

	ERR_FAIL_COND(names.size()!=resdata.size());

	for(int i=0;i<resdata.size();i++) {

		String name=names[i];
		RES resource = resdata[i];
		ERR_CONTINUE( !resource.is_valid() );
		resources[name]=resource;

		//add_resource(name,resource);
	}

}
Example #14
0
Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource> > &remap_cache) {

	List<PropertyInfo> plist;
	get_property_list(&plist);

	Resource *r = (Resource *)ClassDB::instance(get_class());
	ERR_FAIL_COND_V(!r, Ref<Resource>());

	r->local_scene = p_for_scene;

	for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {

		if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
			continue;
		Variant p = get(E->get().name);
		if (p.get_type() == Variant::OBJECT) {

			RES sr = p;
			if (sr.is_valid()) {

				if (sr->is_local_to_scene()) {
					if (remap_cache.has(sr)) {
						p = remap_cache[sr];
					} else {

						RES dupe = sr->duplicate_for_local_scene(p_for_scene, remap_cache);
						p = dupe;
						remap_cache[sr] = dupe;
					}
				}
			}
		}

		r->set(E->get().name, p);
	}

	return Ref<Resource>(r);
}
Example #15
0
RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error) {

	PathAndType pat;
	Error err = _get_path_and_type(p_path, pat);

	if (err != OK) {

		if (r_error)
			*r_error = err;

		return RES();
	}

	RES res = ResourceLoader::_load(pat.path, p_path, pat.type, false, r_error);

#ifdef TOOLS_ENABLED
	if (res.is_valid()) {
		res->set_import_last_modified_time(res->get_last_modified_time()); //pass this, if used
		res->set_import_path(pat.path);
	}
#endif

	return res;
}
Example #16
0
Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) {




#if 0
	open(p_f);
	ERR_FAIL_COND_V(error!=OK,error);

	//FileAccess

	bool old_format=false;

	FileAccess *fw = NULL;

	String base_path=local_path.get_base_dir();

	while(true) {
		bool exit;
		List<String> order;

		Tag *tag = parse_tag(&exit,true,&order);

		bool done=false;

		if (!tag) {
			if (fw) {
				memdelete(fw);
			}
			error=ERR_FILE_CORRUPT;
			ERR_FAIL_COND_V(!exit,error);
			error=ERR_FILE_EOF;

			return error;
		}

		if (tag->name=="ext_resource") {

			if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) {
				old_format=true;
				break;
			}

			if (!fw) {

				fw=FileAccess::open(p_path+".depren",FileAccess::WRITE);
				fw->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); //no escape
				fw->store_line("<resource_file type=\""+resource_type+"\" subresource_count=\""+itos(resources_total)+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\">");

			}

			String path = tag->args["path"];
			String index = tag->args["index"];
			String type = tag->args["type"];


			bool relative=false;
			if (!path.begins_with("res://")) {
				path=base_path.plus_file(path).simplify_path();
				relative=true;
			}


			if (p_map.has(path)) {
				String np=p_map[path];
				path=np;
			}

			if (relative) {
				//restore relative
				path=base_path.path_to_file(path);
			}

			tag->args["path"]=path;
			tag->args["index"]=index;
			tag->args["type"]=type;

		} else {

			done=true;
		}

		String tagt="\t<";
		if (exit)
			tagt+="/";
		tagt+=tag->name;

		for(List<String>::Element *E=order.front();E;E=E->next()) {
			tagt+=" "+E->get()+"=\""+tag->args[E->get()]+"\"";
		}
		tagt+=">";
		fw->store_line(tagt);
		if (done)
			break;
		close_tag("ext_resource");
		fw->store_line("\t</ext_resource>");

	}


	if (old_format) {
		if (fw)
			memdelete(fw);

		DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
		da->remove(p_path+".depren");
		memdelete(da);
		//f**k it, use the old approach;

		WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data());

		Error err;
		FileAccess *f2 = FileAccess::open(p_path,FileAccess::READ,&err);
		if (err!=OK) {
			ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN);
		}

		Ref<ResourceInteractiveLoaderText> ria = memnew( ResourceInteractiveLoaderText );
		ria->local_path=Globals::get_singleton()->localize_path(p_path);
		ria->res_path=ria->local_path;
		ria->remaps=p_map;
	//	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
		ria->open(f2);

		err = ria->poll();

		while(err==OK) {
			err=ria->poll();
		}

		ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT);
		RES res = ria->get_resource();
		ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT);

		return ResourceFormatSaverText::singleton->save(p_path,res);
	}

	if (!fw) {

		return OK; //nothing to rename, do nothing
	}

	uint8_t c=f->get_8();
	while(!f->eof_reached()) {
		fw->store_8(c);
		c=f->get_8();
	}

	bool all_ok = fw->get_error()==OK;

	memdelete(fw);

	if (!all_ok) {
		return ERR_CANT_CREATE;
	}

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	da->remove(p_path);
	da->rename(p_path+".depren",p_path);
	memdelete(da);
#endif
	return OK;

}
Example #17
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 #18
0
void InspectorDock::_paste_resource() const {
	RES r = EditorSettings::get_singleton()->get_resource_clipboard();
	if (r.is_valid()) {
		editor->push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String());
	}
}
Example #19
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 #20
0
bool ResourceSaverPNG::recognize(const RES& p_resource) const {

	return (p_resource.is_valid() && p_resource->is_type("ImageTexture"));
}
Example #21
0
void InspectorDock::_menu_option(int p_option) {
	switch (p_option) {
		case RESOURCE_SAVE: {
			_save_resource(false);
		} break;
		case RESOURCE_SAVE_AS: {
			_save_resource(true);
		} break;

		case OBJECT_REQUEST_HELP: {
			if (current) {
				editor->set_visible_editor(EditorNode::EDITOR_SCRIPT);
				emit_signal("request_help", current->get_class());
			}
		} break;

		case OBJECT_COPY_PARAMS: {
			editor_data->apply_changes_in_editors();
			if (current)
				editor_data->copy_object_params(current);
		} break;

		case OBJECT_PASTE_PARAMS: {
			editor_data->apply_changes_in_editors();
			if (current)
				editor_data->paste_object_params(current);
			editor_data->get_undo_redo().clear_history();
		} break;

		case OBJECT_UNIQUE_RESOURCES: {
			editor_data->apply_changes_in_editors();
			if (current) {
				List<PropertyInfo> props;
				current->get_property_list(&props);
				Map<RES, RES> duplicates;
				for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {

					if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
						continue;

					Variant v = current->get(E->get().name);
					if (v.is_ref()) {
						REF ref = v;
						if (ref.is_valid()) {

							RES res = ref;
							if (res.is_valid()) {

								if (!duplicates.has(res)) {
									duplicates[res] = res->duplicate();
								}
								res = duplicates[res];

								current->set(E->get().name, res);
							}
						}
					}
				}
			}

			editor_data->get_undo_redo().clear_history();

			editor->get_editor_plugins_over()->edit(NULL);
			editor->get_editor_plugins_over()->edit(current);

		} break;

		default: {
			if (p_option >= OBJECT_METHOD_BASE) {
				ERR_FAIL_COND(!current);

				int idx = p_option - OBJECT_METHOD_BASE;

				List<MethodInfo> methods;
				current->get_method_list(&methods);

				ERR_FAIL_INDEX(idx, methods.size());
				String name = methods[idx].name;

				if (current)
					current->call(name);
			}
		}
	}
}