From 83740ab793079ff5094de372d499560589f68b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Sun, 26 Jun 2016 11:10:22 +0200 Subject: Revert "make default extension .tscn" This reverts commit 29177e1e9b2644cfa2d5efe6fcfe2605b84ed68c. --- tools/editor/editor_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 58da0e8478..84321af337 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -2155,7 +2155,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { String existing; if (extensions.size()) { String root_name(get_edited_scene()->get_name()); - existing=root_name+".tscn";//+extensions.front()->get().to_lower(); + existing=root_name+"."+extensions.front()->get().to_lower(); } file->set_current_path(existing); -- cgit v1.2.3 From a5e27503fd52589703d637d1245a023233a14a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Sun, 26 Jun 2016 11:57:10 +0200 Subject: Homogeinize resource formats loaders/savers --- core/io/resource_format_text.cpp | 1474 +++++++++++++++++++++++++++++++++ core/io/resource_format_text.h | 170 ++++ core/register_core_types.cpp | 14 + scene/register_scene_types.cpp | 18 - scene/resources/scene_format_text.cpp | 1474 --------------------------------- scene/resources/scene_format_text.h | 170 ---- 6 files changed, 1658 insertions(+), 1662 deletions(-) create mode 100644 core/io/resource_format_text.cpp create mode 100644 core/io/resource_format_text.h delete mode 100644 scene/resources/scene_format_text.cpp delete mode 100644 scene/resources/scene_format_text.h diff --git a/core/io/resource_format_text.cpp b/core/io/resource_format_text.cpp new file mode 100644 index 0000000000..ed4fbdfb73 --- /dev/null +++ b/core/io/resource_format_text.cpp @@ -0,0 +1,1474 @@ +/*************************************************************************/ +/* scene_format_text.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "resource_format_text.h" + +#include "globals.h" +#include "version.h" +#include "os/dir_access.h" + +#define FORMAT_VERSION 1 + +#include "version.h" +#include "os/dir_access.h" + +#define _printerr() ERR_PRINT(String(res_path+":"+itos(lines)+" - Parse Error: "+error_text).utf8().get_data()); + + + + +/// + +void ResourceInteractiveLoaderText::set_local_path(const String& p_local_path) { + + res_path=p_local_path; +} + +Ref ResourceInteractiveLoaderText::get_resource() { + + return resource; +} + +Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str) { + + VariantParser::Token token; + VariantParser::get_token(p_stream,token,line,r_err_str); + if (token.type!=VariantParser::TK_NUMBER) { + r_err_str="Expected number (sub-resource index)"; + return ERR_PARSE_ERROR; + } + + int index = token.value; + + String path = local_path+"::"+itos(index); + + if (!ignore_resource_parsing) { + + if (!ResourceCache::has(path)) { + r_err_str="Can't load cached sub-resource: "+path; + return ERR_PARSE_ERROR; + } + + r_res=RES(ResourceCache::get(path)); + } else { + r_res=RES(); + } + + VariantParser::get_token(p_stream,token,line,r_err_str); + if (token.type!=VariantParser::TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + + return OK; +} + +Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str){ + + VariantParser::Token token; + VariantParser::get_token(p_stream,token,line,r_err_str); + if (token.type!=VariantParser::TK_NUMBER) { + r_err_str="Expected number (sub-resource index)"; + return ERR_PARSE_ERROR; + } + + int id = token.value; + + if (!ignore_resource_parsing) { + + if (!ext_resources.has(id)) { + r_err_str="Can't load cached ext-resource #"+itos(id); + return ERR_PARSE_ERROR; + } + + String path = ext_resources[id].path; + String type = ext_resources[id].type; + + if (path.find("://")==-1 && path.is_rel_path()) { + // path is relative to file being loaded, so convert to a resource path + path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); + + } + + r_res=ResourceLoader::load(path,type); + + if (r_res.is_null()) { + WARN_PRINT(String("Couldn't load external resource: "+path).utf8().get_data()); + } + } else { + r_res=RES(); + } + + VariantParser::get_token(p_stream,token,line,r_err_str); + if (token.type!=VariantParser::TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + + return OK; +} + + +Error ResourceInteractiveLoaderText::poll() { + + if (error!=OK) + return error; + + if (next_tag.name=="ext_resource") { + + + if (!next_tag.fields.has("path")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'path' in external resource tag"; + _printerr(); + return error; + } + + if (!next_tag.fields.has("type")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'type' in external resource tag"; + _printerr(); + return error; + } + + if (!next_tag.fields.has("id")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'id' in external resource tag"; + _printerr(); + return error; + } + + String path=next_tag.fields["path"]; + String type=next_tag.fields["type"]; + int index=next_tag.fields["id"]; + + + if (path.find("://")==-1 && path.is_rel_path()) { + // path is relative to file being loaded, so convert to a resource path + path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); + } + + if (remaps.has(path)) { + path=remaps[path]; + } + + RES res = ResourceLoader::load(path,type); + + if (res.is_null()) { + + if (ResourceLoader::get_abort_on_missing_resources()) { + error=ERR_FILE_CORRUPT; + error_text="[ext_resource] referenced nonexistent resource at: "+path; + _printerr(); + return error; + } else { + ResourceLoader::notify_dependency_error(local_path,path,type); + } + } else { + + resource_cache.push_back(res); + } + + ExtResource er; + er.path=path; + er.type=type; + ext_resources[index]=er; + + error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); + + if (error) { + _printerr(); + } + + resource_current++; + return error; + + + } else if (next_tag.name=="sub_resource") { + + + if (!next_tag.fields.has("type")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'type' in external resource tag"; + _printerr(); + return error; + } + + if (!next_tag.fields.has("id")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'index' in external resource tag"; + _printerr(); + return error; + } + + String type=next_tag.fields["type"]; + int id=next_tag.fields["id"]; + + String path = local_path+"::"+itos(id); + + + //bool exists=ResourceCache::has(path); + + Ref res; + + if ( !ResourceCache::has(path)) { //only if it doesn't exist + + Object *obj = ObjectTypeDB::instance(type); + if (!obj) { + + error_text+="Can't create sub resource of type: "+type; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + + Resource *r = obj->cast_to(); + if (!r) { + + error_text+="Can't create sub resource of type, because not a resource: "+type; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + res=Ref(r); + resource_cache.push_back(res); + res->set_path(path); + + } + + resource_current++; + + while(true) { + + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp); + + if (error) { + _printerr(); + return error; + } + + if (assign!=String()) { + if (res.is_valid()) { + res->set(assign,value); + } + //it's assignment + } else if (next_tag.name!=String()) { + + error=OK; + break; + } else { + error=ERR_FILE_CORRUPT; + error_text="Premature end of file while parsing [sub_resource]"; + _printerr(); + return error; + } + + + } + + return OK; + + } else if (next_tag.name=="resource") { + + if (is_scene) { + + error_text+="found the 'resource' tag on a scene file!"; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + Object *obj = ObjectTypeDB::instance(res_type); + if (!obj) { + + error_text+="Can't create sub resource of type: "+res_type; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + + Resource *r = obj->cast_to(); + if (!r) { + + error_text+="Can't create sub resource of type, because not a resource: "+res_type; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + resource=Ref(r); + + resource_current++; + + while(true) { + + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp); + + if (error) { + if (error!=ERR_FILE_EOF) { + _printerr(); + } else { + if (!ResourceCache::has(res_path)) { + resource->set_path(res_path); + } + } + return error; + } + + if (assign!=String()) { + resource->set(assign,value); + //it's assignment + } else if (next_tag.name!=String()) { + + error=ERR_FILE_CORRUPT; + error_text="Extra tag found when parsing main resource file"; + _printerr(); + return error; + } else { + error=ERR_FILE_EOF; + return error; + } + + } + + return OK; + + } else if (next_tag.name=="node") { + + if (!is_scene) { + + error_text+="found the 'node' tag on a resource file!"; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + /* + int add_name(const StringName& p_name); + int add_value(const Variant& p_value); + int add_node_path(const NodePath& p_path); + int add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance); + void add_node_property(int p_node,int p_name,int p_value); + void add_node_group(int p_node,int p_group); + void set_base_scene(int p_idx); + void add_connection(int p_from,int p_to, int p_signal, int p_method, int p_flags,const Vector& p_binds); + void add_editable_instance(const NodePath& p_path); + + */ + + int parent=-1; + int owner=-1; + int type=-1; + int name=-1; + int instance=-1; +// int base_scene=-1; + + if (next_tag.fields.has("name")) { + name=packed_scene->get_state()->add_name(next_tag.fields["name"]); + } + + if (next_tag.fields.has("parent")) { + parent=packed_scene->get_state()->add_node_path(next_tag.fields["parent"]); + } + + + + if (next_tag.fields.has("type")) { + type=packed_scene->get_state()->add_name(next_tag.fields["type"]); + } else { + type=SceneState::TYPE_INSTANCED; //no type? assume this was instanced + } + + + if (next_tag.fields.has("instance")) { + + instance=packed_scene->get_state()->add_value(next_tag.fields["instance"]); + + if (packed_scene->get_state()->get_node_count()==0 && parent==-1) { + packed_scene->get_state()->set_base_scene(instance); + instance=-1; + } + } + + if (next_tag.fields.has("instance_placeholder")) { + + String path=next_tag.fields["instance_placeholder"]; + + int path_v = packed_scene->get_state()->add_value(path); + + if (packed_scene->get_state()->get_node_count()==0) { + error=ERR_FILE_CORRUPT; + error_text="Instance Placeholder can't be used for inheritance."; + _printerr(); + return error; + } + + instance=path_v|SceneState::FLAG_INSTANCE_IS_PLACEHOLDER; + } + + if (next_tag.fields.has("owner")) { + owner=packed_scene->get_state()->add_node_path(next_tag.fields["owner"]); + } else { + if (parent!=-1 && !(type==SceneState::TYPE_INSTANCED && instance==-1)) + owner=0; //if no owner, owner is root + } + + int node_id = packed_scene->get_state()->add_node(parent,owner,type,name,instance); + + if (next_tag.fields.has("groups")) { + + Array groups = next_tag.fields["groups"]; + for (int i=0;iget_state()->add_node_group(node_id,packed_scene->get_state()->add_name(groups[i])); + } + } + + while(true) { + + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp); + + if (error) { + if (error!=ERR_FILE_EOF) { + _printerr(); + } else { + resource=packed_scene; + if (!ResourceCache::has(res_path)) { + packed_scene->set_path(res_path); + } + } + return error; + } + + if (assign!=String()) { + int nameidx = packed_scene->get_state()->add_name(assign); + int valueidx = packed_scene->get_state()->add_value(value); + packed_scene->get_state()->add_node_property(node_id,nameidx,valueidx); + //it's assignment + } else if (next_tag.name!=String()) { + + error=OK; + return error; + } else { + + resource=packed_scene; + error=ERR_FILE_EOF; + return error; + } + + } + + return OK; + + } else if (next_tag.name=="connection") { + + if (!is_scene) { + + error_text+="found the 'connection' tag on a resource file!"; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + if (!next_tag.fields.has("from")) { + error=ERR_FILE_CORRUPT; + error_text="missing 'from' field fron connection tag"; + return error; + } + + if (!next_tag.fields.has("to")) { + error=ERR_FILE_CORRUPT; + error_text="missing 'to' field fron connection tag"; + return error; + } + + if (!next_tag.fields.has("signal")) { + error=ERR_FILE_CORRUPT; + error_text="missing 'signal' field fron connection tag"; + return error; + } + + if (!next_tag.fields.has("method")) { + error=ERR_FILE_CORRUPT; + error_text="missing 'method' field fron connection tag"; + return error; + } + + NodePath from = next_tag.fields["from"]; + NodePath to = next_tag.fields["to"]; + StringName method = next_tag.fields["method"]; + StringName signal = next_tag.fields["signal"]; + int flags=CONNECT_PERSIST; + Array binds; + + if (next_tag.fields.has("flags")) { + flags=next_tag.fields["flags"]; + } + + if (next_tag.fields.has("binds")) { + binds=next_tag.fields["binds"]; + } + + Vector bind_ints; + for(int i=0;iget_state()->add_value( binds[i] ) ); + } + + packed_scene->get_state()->add_connection( + packed_scene->get_state()->add_node_path(from.simplified()), + packed_scene->get_state()->add_node_path(to.simplified()), + packed_scene->get_state()->add_name(signal), + packed_scene->get_state()->add_name(method), + flags, + bind_ints + ); + + error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); + + if (error) { + if (error!=ERR_FILE_EOF) { + _printerr(); + } else { + resource=packed_scene; + } + } + + return error; + } else if (next_tag.name=="editable") { + + if (!is_scene) { + + error_text+="found the 'editable' tag on a resource file!"; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + if (!next_tag.fields.has("path")) { + error=ERR_FILE_CORRUPT; + error_text="missing 'path' field fron connection tag"; + _printerr(); + return error; + } + + NodePath path = next_tag.fields["path"]; + + packed_scene->get_state()->add_editable_instance(path.simplified()); + + error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); + + if (error) { + if (error!=ERR_FILE_EOF) { + _printerr(); + } else { + resource=packed_scene; + } + } + + return error; + + } else { + + error_text+="Unknown tag in file: "+next_tag.name; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + + return OK; +} + +int ResourceInteractiveLoaderText::get_stage() const { + + return resource_current; +} +int ResourceInteractiveLoaderText::get_stage_count() const { + + return resources_total;//+ext_resources; +} + +ResourceInteractiveLoaderText::~ResourceInteractiveLoaderText() { + + memdelete(f); +} + +void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f,List *p_dependencies,bool p_add_types) { + + + open(f); + ignore_resource_parsing=true; + ERR_FAIL_COND(error!=OK); + + while(next_tag.name=="ext_resource") { + + if (!next_tag.fields.has("type")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'type' in external resource tag"; + _printerr(); + return; + } + + if (!next_tag.fields.has("id")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'index' in external resource tag"; + _printerr(); + return; + } + + String path=next_tag.fields["path"]; + String type=next_tag.fields["type"]; + + + if (path.find("://")==-1 && path.is_rel_path()) { + // path is relative to file being loaded, so convert to a resource path + path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); + } + + + if (p_add_types) { + path+="::"+type; + } + + p_dependencies->push_back(path); + + Error err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); + + if (err) { + print_line(error_text+" - "+itos(lines)); + error_text="Unexpected end of file"; + _printerr(); + error=ERR_FILE_CORRUPT; + } + + + } +} + +Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map& p_map) { + + + open(p_f,true); + ERR_FAIL_COND_V(error!=OK,error); + ignore_resource_parsing=true; + //FileAccess + + FileAccess *fw = NULL; + + String base_path=local_path.get_base_dir(); + + + uint64_t tag_end = f->get_pos(); + + + while(true) { + + + + Error err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); + + if (err!=OK) { + if (fw) { + memdelete(fw); + } + error=ERR_FILE_CORRUPT; + ERR_FAIL_V(error); + } + + if (next_tag.name!="ext_resource") { + + //nothing was done + if (!fw) + return OK; + + break; + + + } else { + + if (!fw) { + + fw=FileAccess::open(p_path+".depren",FileAccess::WRITE); + if (is_scene) { + fw->store_line("[gd_scene load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n"); + } else { + fw->store_line("[gd_resource type=\""+res_type+"\" load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n"); + } + } + + if (!next_tag.fields.has("path") || !next_tag.fields.has("id") || !next_tag.fields.has("type")) { + memdelete(fw); + error=ERR_FILE_CORRUPT; + ERR_FAIL_V(error); + } + + String path = next_tag.fields["path"]; + int index = next_tag.fields["id"]; + String type = next_tag.fields["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); + } + + fw->store_line("[ext_resource path=\""+path+"\" type=\""+type+"\" id="+itos(index)+"]"); + + tag_end = f->get_pos(); + + } + + } + + f->seek(tag_end); + + uint8_t c=f->get_8(); + while(!f->eof_reached()) { + fw->store_8(c); + c=f->get_8(); + } + f->close(); + + 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); + + return OK; + +} + + +void ResourceInteractiveLoaderText::open(FileAccess *p_f,bool p_skip_first_tag) { + + error=OK; + + lines=1; + f=p_f; + + + stream.f=f; + is_scene=false; + ignore_resource_parsing=false; + resource_current=0; + + + VariantParser::Tag tag; + Error err = VariantParser::parse_tag(&stream,lines,error_text,tag); + + if (err) { + + error=err; + _printerr(); + return; + } + + if (tag.fields.has("format")) { + int fmt = tag.fields["format"]; + if (fmt>FORMAT_VERSION) { + error_text="Saved with newer format version"; + _printerr(); + error=ERR_PARSE_ERROR; + return; + } + } + + + if (tag.name=="gd_scene") { + is_scene=true; + packed_scene.instance(); + + } else if (tag.name=="gd_resource") { + if (!tag.fields.has("type")) { + error_text="Missing 'type' field in 'gd_resource' tag"; + _printerr(); + error=ERR_PARSE_ERROR; + return; + } + + res_type=tag.fields["type"]; + + } else { + error_text="Unrecognized file type: "+tag.name; + _printerr(); + error=ERR_PARSE_ERROR; + return; + + } + + + + if (tag.fields.has("load_steps")) { + resources_total=tag.fields["load_steps"]; + } else { + resources_total=0; + } + + if (!p_skip_first_tag) { + + err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); + + if (err) { + error_text="Unexpected end of file"; + _printerr(); + error=ERR_FILE_CORRUPT; + } + } + + rp.ext_func=_parse_ext_resources; + rp.sub_func=_parse_sub_resources; + rp.func=NULL; + rp.userdata=this; + +} + + + + +String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { + + error=OK; + + lines=1; + f=p_f; + + stream.f=f; + + ignore_resource_parsing=true; + + + VariantParser::Tag tag; + Error err = VariantParser::parse_tag(&stream,lines,error_text,tag); + + if (err) { + _printerr(); + return ""; + } + + if (tag.fields.has("format")) { + int fmt = tag.fields["format"]; + if (fmt>FORMAT_VERSION) { + error_text="Saved with newer format version"; + _printerr(); + return ""; + } + } + + if (tag.name=="gd_scene") + return "PackedScene"; + + if (tag.name!="gd_resource") + return ""; + + + + if (!tag.fields.has("type")) { + error_text="Missing 'type' field in 'gd_resource' tag"; + _printerr(); + return ""; + } + + return tag.fields["type"]; + + +} + +///////////////////// + +Ref ResourceFormatLoaderText::load_interactive(const String &p_path, Error *r_error) { + + if (r_error) + *r_error=ERR_CANT_OPEN; + + Error err; + FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); + + + if (err!=OK) { + + ERR_FAIL_COND_V(err!=OK,Ref()); + } + + Ref ria = memnew( ResourceInteractiveLoaderText ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; +// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); + ria->open(f); + + return ria; +} + +void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const { + + if (p_type=="") { + get_recognized_extensions(p_extensions); + return; + } + + if (p_type=="PackedScene") + p_extensions->push_back("tscn"); + else + p_extensions->push_back("tres"); + +} + +void ResourceFormatLoaderText::get_recognized_extensions(List *p_extensions) const{ + + p_extensions->push_back("tscn"); + p_extensions->push_back("tres"); +} + +bool ResourceFormatLoaderText::handles_type(const String& p_type) const{ + + return true; +} +String ResourceFormatLoaderText::get_resource_type(const String &p_path) const{ + + + + String ext=p_path.extension().to_lower(); + if (ext=="tscn") + return "PackedScene"; + else if (ext!="tres") + return String(); + + //for anyhting else must test.. + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + if (!f) { + + return ""; //could not rwead + } + + Ref ria = memnew( ResourceInteractiveLoaderText ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; +// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); + String r = ria->recognize(f); + return r; +} + + +void ResourceFormatLoaderText::get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types) { + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + if (!f) { + + ERR_FAIL(); + } + + Ref ria = memnew( ResourceInteractiveLoaderText ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; +// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); + ria->get_dependencies(f,p_dependencies,p_add_types); + + +} + +Error ResourceFormatLoaderText::rename_dependencies(const String &p_path,const Map& p_map) { + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + if (!f) { + + ERR_FAIL_V(ERR_CANT_OPEN); + } + + Ref ria = memnew( ResourceInteractiveLoaderText ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; +// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); + return ria->rename_dependencies(f,p_path,p_map); +} + + +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ +/*****************************************************************************************************/ + + +String ResourceFormatSaverTextInstance::_write_resources(void *ud,const RES& p_resource) { + + ResourceFormatSaverTextInstance *rsi=(ResourceFormatSaverTextInstance*)ud; + return rsi->_write_resource(p_resource); + +} + +String ResourceFormatSaverTextInstance::_write_resource(const RES& res) { + + if (external_resources.has(res)) { + + return "ExtResource( "+itos(external_resources[res]+1)+" )"; + } else { + + if (internal_resources.has(res)) { + return "SubResource( "+itos(internal_resources[res])+" )"; + } else if (res->get_path().length() && res->get_path().find("::")==-1) { + + //external resource + String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path(); + return "Resource( \""+path+"\" )"; + } else { + ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?"); + ERR_FAIL_V("null"); + //internal resource + } + } + + return "null"; +} + +void ResourceFormatSaverTextInstance::_find_resources(const Variant& p_variant,bool p_main) { + + + switch(p_variant.get_type()) { + case Variant::OBJECT: { + + + RES res = p_variant.operator RefPtr(); + + if (res.is_null() || external_resources.has(res)) + return; + + if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) { + int index = external_resources.size(); + external_resources[res]=index; + return; + } + + if (resource_set.has(res)) + return; + + List property_list; + + res->get_property_list( &property_list ); + property_list.sort(); + + List::Element *I=property_list.front(); + + while(I) { + + PropertyInfo pi=I->get(); + + if (pi.usage&PROPERTY_USAGE_STORAGE || (bundle_resources && pi.usage&PROPERTY_USAGE_BUNDLE)) { + + Variant v=res->get(I->get().name); + _find_resources(v); + } + + I=I->next(); + } + + resource_set.insert( res ); //saved after, so the childs it needs are available when loaded + saved_resources.push_back(res); + + } break; + case Variant::ARRAY: { + + Array varray=p_variant; + int len=varray.size(); + for(int i=0;i keys; + d.get_key_list(&keys); + for(List::Element *E=keys.front();E;E=E->next()) { + + Variant v = d[E->get()]; + _find_resources(v); + } + } break; + default: {} + } + +} + +static String _valprop(const String& p_name) { + + if (p_name.find("\"")!=-1 || p_name.find("=")!=-1 || p_name.find(" ")!=-1) + return "\""+p_name.c_escape()+"\""; + return p_name; +} + +Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_resource,uint32_t p_flags) { + + if (p_path.ends_with(".tscn")) { + packed_scene=p_resource; + } + + Error err; + f = FileAccess::open(p_path, FileAccess::WRITE,&err); + ERR_FAIL_COND_V( err, ERR_CANT_OPEN ); + FileAccessRef _fref(f); + + local_path = Globals::get_singleton()->localize_path(p_path); + + relative_paths=p_flags&ResourceSaver::FLAG_RELATIVE_PATHS; + skip_editor=p_flags&ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES; + bundle_resources=p_flags&ResourceSaver::FLAG_BUNDLE_RESOURCES; + takeover_paths=p_flags&ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS; + if (!p_path.begins_with("res://")) { + takeover_paths=false; + } + + // save resources + _find_resources(p_resource,true); + + if (packed_scene.is_valid()) { + //add instances to external resources if saving a packed scene + for(int i=0;iget_state()->get_node_count();i++) { + if (packed_scene->get_state()->is_node_instance_placeholder(i)) + continue; + + Ref instance=packed_scene->get_state()->get_node_instance(i); + if (instance.is_valid() && !external_resources.has(instance)) { + int index = external_resources.size(); + external_resources[instance]=index; + } + } + } + + + ERR_FAIL_COND_V(err!=OK,err); + + { + String title=packed_scene.is_valid()?"[gd_scene ":"[gd_resource "; + if (packed_scene.is_null()) + title+="type=\""+p_resource->get_type()+"\" "; + int load_steps=saved_resources.size()+external_resources.size(); + //if (packed_scene.is_valid()) { + // load_steps+=packed_scene->get_node_count(); + //} + //no, better to not use load steps from nodes, no point to that + + if (load_steps>1) { + title+="load_steps="+itos(load_steps)+" "; + } + title+="format="+itos(FORMAT_VERSION)+""; + //title+="engine_version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\""; + + f->store_string(title); + f->store_line("]\n"); //one empty line + } + + + Vector sorted_er; + sorted_er.resize(external_resources.size()); + + for(Map::Element *E=external_resources.front();E;E=E->next()) { + + sorted_er[E->get()]=E->key(); + } + + for(int i=0;iget_path(); + + f->store_string("[ext_resource path=\""+p+"\" type=\""+sorted_er[i]->get_save_type()+"\" id="+itos(i+1)+"]\n"); //bundled + } + + if (external_resources.size()) + f->store_line(String()); //separate + + Set used_indices; + + for(List::Element *E=saved_resources.front();E;E=E->next()) { + + RES res = E->get(); + if (E->next() && (res->get_path()=="" || res->get_path().find("::") != -1 )) { + + if (res->get_subindex()!=0) { + if (used_indices.has(res->get_subindex())) { + res->set_subindex(0); //repeated + } else { + used_indices.insert(res->get_subindex()); + } + } + } + } + + for(List::Element *E=saved_resources.front();E;E=E->next()) { + + RES res = E->get(); + ERR_CONTINUE(!resource_set.has(res)); + bool main = (E->next()==NULL); + + if (main && packed_scene.is_valid()) + break; //save as a scene + + if (main) { + f->store_line("[resource]\n"); + } else { + String line="[sub_resource "; + if (res->get_subindex()==0) { + int new_subindex=1; + if (used_indices.size()) { + new_subindex=used_indices.back()->get()+1; + } + + res->set_subindex(new_subindex); + used_indices.insert(new_subindex); + } + + int idx = res->get_subindex(); + line+="type=\""+res->get_type()+"\" id="+itos(idx); + f->store_line(line+"]\n"); + if (takeover_paths) { + res->set_path(p_path+"::"+itos(idx),true); + } + + internal_resources[res]=idx; + + } + + + List property_list; + res->get_property_list(&property_list); +// property_list.sort(); + for(List::Element *PE = property_list.front();PE;PE=PE->next()) { + + + if (skip_editor && PE->get().name.begins_with("__editor")) + continue; + + if (PE->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && PE->get().usage&PROPERTY_USAGE_BUNDLE)) { + + String name = PE->get().name; + Variant value = res->get(name); + + + if ((PE->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())||(PE->get().usage&PROPERTY_USAGE_STORE_IF_NONONE && value.is_one()) ) + continue; + + if (PE->get().type==Variant::OBJECT && value.is_zero() && !(PE->get().usage&PROPERTY_USAGE_STORE_IF_NULL)) + continue; + + String vars; + VariantWriter::write_to_string(value,vars,_write_resources,this); + f->store_string(_valprop(name)+" = "+vars+"\n"); + } + + + } + + f->store_string("\n"); + + } + + if (packed_scene.is_valid()) { + //if this is a scene, save nodes and connections! + Ref state = packed_scene->get_state(); + for(int i=0;iget_node_count();i++) { + + StringName type = state->get_node_type(i); + StringName name = state->get_node_name(i); + NodePath path = state->get_node_path(i,true); + NodePath owner = state->get_node_owner_path(i); + Ref instance = state->get_node_instance(i); + String instance_placeholder = state->get_node_instance_placeholder(i); + Vector groups = state->get_node_groups(i); + + + + String header="[node"; + header+=" name=\""+String(name)+"\""; + if (type!=StringName()) { + header+=" type=\""+String(type)+"\""; + } + if (path!=NodePath()) { + header+=" parent=\""+String(path.simplified())+"\""; + } + if (owner!=NodePath() && owner!=NodePath(".")) { + header+=" owner=\""+String(owner.simplified())+"\""; + } + + if (groups.size()) { + String sgroups=" groups=[ "; + for(int j=0;j0) + sgroups+=", "; + sgroups+="\""+groups[j].operator String().c_escape()+"\""; + } + sgroups+=" ]"; + header+=sgroups; + } + + f->store_string(header); + + if (instance_placeholder!=String()) { + + String vars; + f->store_string(" instance_placeholder="); + VariantWriter::write_to_string(instance_placeholder,vars,_write_resources,this); + f->store_string(vars); + } + + if (instance.is_valid()) { + + String vars; + f->store_string(" instance="); + VariantWriter::write_to_string(instance,vars,_write_resources,this); + f->store_string(vars); + + } + + f->store_line("]\n"); + + for(int j=0;jget_node_property_count(i);j++) { + + String vars; + VariantWriter::write_to_string(state->get_node_property_value(i,j),vars,_write_resources,this); + + f->store_string(_valprop(String(state->get_node_property_name(i,j)))+" = "+vars+"\n"); + } + + if (state->get_node_property_count(i)) { + //add space + f->store_line(String()); + } + + } + + for(int i=0;iget_connection_count();i++) { + + String connstr="[connection"; + connstr+=" signal=\""+String(state->get_connection_signal(i))+"\""; + connstr+=" from=\""+String(state->get_connection_source(i).simplified())+"\""; + connstr+=" to=\""+String(state->get_connection_target(i).simplified())+"\""; + connstr+=" method=\""+String(state->get_connection_method(i))+"\""; + int flags = state->get_connection_flags(i); + if (flags!=Object::CONNECT_PERSIST) { + connstr+=" flags="+itos(flags); + } + + Array binds=state->get_connection_binds(i); + f->store_string(connstr); + if (binds.size()) { + String vars; + VariantWriter::write_to_string(binds,vars,_write_resources,this); + f->store_string(" binds= "+vars); + + } + + f->store_line("]\n"); + } + + f->store_line(String()); + + Vector editable_instances = state->get_editable_instances(); + for(int i=0;istore_line("[editable path=\""+editable_instances[i].operator String()+"\"]"); + } + } + + if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) { + f->close(); + return ERR_CANT_CREATE; + } + + f->close(); + //memdelete(f); + + return OK; +} + + + +Error ResourceFormatSaverText::save(const String &p_path,const RES& p_resource,uint32_t p_flags) { + + if (p_path.ends_with(".sct") && p_resource->get_type()!="PackedScene") { + return ERR_FILE_UNRECOGNIZED; + } + + ResourceFormatSaverTextInstance saver; + return saver.save(p_path,p_resource,p_flags); + +} + +bool ResourceFormatSaverText::recognize(const RES& p_resource) const { + + + return true; // all recognized! +} +void ResourceFormatSaverText::get_recognized_extensions(const RES& p_resource,List *p_extensions) const { + + if (p_resource->get_type()=="PackedScene") + p_extensions->push_back("tscn"); //text scene + else + p_extensions->push_back("tres"); //text resource + +} + +ResourceFormatSaverText* ResourceFormatSaverText::singleton=NULL; +ResourceFormatSaverText::ResourceFormatSaverText() { + singleton=this; +} diff --git a/core/io/resource_format_text.h b/core/io/resource_format_text.h new file mode 100644 index 0000000000..6122a1f9d8 --- /dev/null +++ b/core/io/resource_format_text.h @@ -0,0 +1,170 @@ +/*************************************************************************/ +/* scene_format_text.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SCENE_FORMAT_TEXT_H +#define SCENE_FORMAT_TEXT_H + +#include "io/resource_loader.h" +#include "io/resource_saver.h" +#include "os/file_access.h" +#include "scene/resources/packed_scene.h" +#include "variant_parser.h" + + + +class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { + + String local_path; + String res_path; + String error_text; + + FileAccess *f; + + VariantParser::StreamFile stream; + + struct ExtResource { + String path; + String type; + }; + + + bool is_scene; + String res_type; + + bool ignore_resource_parsing; + +// Map remaps; + + Map ext_resources; + + int resources_total; + int resource_current; + String resource_type; + + VariantParser::Tag next_tag; + + mutable int lines; + + Map remaps; + //void _printerr(); + + static Error _parse_sub_resources(void* p_self, VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str) { return reinterpret_cast(p_self)->_parse_sub_resource(p_stream,r_res,line,r_err_str); } + static Error _parse_ext_resources(void* p_self, VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str) { return reinterpret_cast(p_self)->_parse_ext_resource(p_stream,r_res,line,r_err_str); } + + Error _parse_sub_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str); + Error _parse_ext_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str); + + VariantParser::ResourceParser rp; + + + Ref packed_scene; + + +friend class ResourceFormatLoaderText; + + List resource_cache; + Error error; + + RES resource; + +public: + + virtual void set_local_path(const String& p_local_path); + virtual Ref get_resource(); + virtual Error poll(); + virtual int get_stage() const; + virtual int get_stage_count() const; + + void open(FileAccess *p_f, bool p_skip_first_tag=false); + String recognize(FileAccess *p_f); + void get_dependencies(FileAccess *p_f, List *p_dependencies, bool p_add_types); + Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map& p_map); + + + ~ResourceInteractiveLoaderText(); + +}; + + + +class ResourceFormatLoaderText : public ResourceFormatLoader { +public: + + virtual Ref load_interactive(const String &p_path,Error *r_error=NULL); + virtual void get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const; + virtual void get_recognized_extensions(List *p_extensions) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + virtual void get_dependencies(const String& p_path, List *p_dependencies, bool p_add_types=false); + virtual Error rename_dependencies(const String &p_path,const Map& p_map); + + +}; + + +class ResourceFormatSaverTextInstance { + + String local_path; + + Ref packed_scene; + + bool takeover_paths; + bool relative_paths; + bool bundle_resources; + bool skip_editor; + FileAccess *f; + Set resource_set; + List saved_resources; + Map external_resources; + Map internal_resources; + + void _find_resources(const Variant& p_variant,bool p_main=false); + + static String _write_resources(void *ud,const RES& p_resource); + String _write_resource(const RES& res); + + +public: + + Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); + + +}; + +class ResourceFormatSaverText : public ResourceFormatSaver { +public: + static ResourceFormatSaverText* singleton; + virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); + virtual bool recognize(const RES& p_resource) const; + virtual void get_recognized_extensions(const RES& p_resource,List *p_extensions) const; + + ResourceFormatSaverText(); +}; + + +#endif // SCENE_FORMAT_TEXT_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 97bd5f2a32..0e73639e97 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -42,6 +42,7 @@ #include "translation.h" #include "compressed_translation.h" #include "io/translation_loader_po.h" +#include "io/resource_format_text.h" #include "io/resource_format_xml.h" #include "io/resource_format_binary.h" #include "io/stream_peer_ssl.h" @@ -53,6 +54,9 @@ #include "input_map.h" #include "undo_redo.h" + +static ResourceFormatSaverText *resource_saver_text=NULL; +static ResourceFormatLoaderText *resource_loader_text=NULL; #ifdef XML_ENABLED static ResourceFormatSaverXML *resource_saver_xml=NULL; static ResourceFormatLoaderXML *resource_loader_xml=NULL; @@ -102,6 +106,11 @@ void register_core_types() { resource_loader_binary = memnew( ResourceFormatLoaderBinary ); ResourceLoader::add_resource_format_loader(resource_loader_binary); + resource_saver_text = memnew( ResourceFormatSaverText ); + ResourceSaver::add_resource_format_saver(resource_saver_text); + resource_loader_text = memnew( ResourceFormatLoaderText ); + ResourceLoader::add_resource_format_loader(resource_loader_text); + #ifdef XML_ENABLED resource_saver_xml = memnew( ResourceFormatSaverXML ); ResourceSaver::add_resource_format_saver(resource_saver_xml); @@ -202,6 +211,11 @@ void unregister_core_types() { if (resource_loader_binary) memdelete(resource_loader_binary); + if (resource_saver_text) + memdelete(resource_saver_text); + if (resource_loader_text) + memdelete(resource_loader_text); + memdelete( resource_format_po ); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index c83ab88c73..d848b9e5a5 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -222,8 +222,6 @@ #include "scene/3d/collision_polygon.h" #endif -#include "scene/resources/scene_format_text.h" - static ResourceFormatLoaderImage *resource_loader_image=NULL; static ResourceFormatLoaderWAV *resource_loader_wav=NULL; @@ -235,9 +233,6 @@ static ResourceFormatLoaderWAV *resource_loader_wav=NULL; static ResourceFormatLoaderTheme *resource_loader_theme=NULL; static ResourceFormatLoaderShader *resource_loader_shader=NULL; -static ResourceFormatSaverText *resource_saver_text=NULL; -static ResourceFormatLoaderText *resource_loader_text=NULL; - static ResourceFormatLoaderDynamicFont *resource_loader_dynamic_font=NULL; //static SceneStringNames *string_names; @@ -635,13 +630,6 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - - resource_saver_text = memnew( ResourceFormatSaverText ); - ResourceSaver::add_resource_format_saver(resource_saver_text); - - resource_loader_text = memnew( ResourceFormatLoaderText ); - ResourceLoader::add_resource_format_loader(resource_loader_text); - } void unregister_scene_types() { @@ -661,11 +649,5 @@ void unregister_scene_types() { memdelete( resource_loader_theme ); memdelete( resource_loader_shader ); - if (resource_saver_text) { - memdelete(resource_saver_text); - } - if (resource_loader_text) { - memdelete(resource_loader_text); - } SceneStringNames::free(); } diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp deleted file mode 100644 index 95645107d4..0000000000 --- a/scene/resources/scene_format_text.cpp +++ /dev/null @@ -1,1474 +0,0 @@ -/*************************************************************************/ -/* scene_format_text.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "scene_format_text.h" - -#include "globals.h" -#include "version.h" -#include "os/dir_access.h" - -#define FORMAT_VERSION 1 - -#include "version.h" -#include "os/dir_access.h" - -#define _printerr() ERR_PRINT(String(res_path+":"+itos(lines)+" - Parse Error: "+error_text).utf8().get_data()); - - - - -/// - -void ResourceInteractiveLoaderText::set_local_path(const String& p_local_path) { - - res_path=p_local_path; -} - -Ref ResourceInteractiveLoaderText::get_resource() { - - return resource; -} - -Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str) { - - VariantParser::Token token; - VariantParser::get_token(p_stream,token,line,r_err_str); - if (token.type!=VariantParser::TK_NUMBER) { - r_err_str="Expected number (sub-resource index)"; - return ERR_PARSE_ERROR; - } - - int index = token.value; - - String path = local_path+"::"+itos(index); - - if (!ignore_resource_parsing) { - - if (!ResourceCache::has(path)) { - r_err_str="Can't load cached sub-resource: "+path; - return ERR_PARSE_ERROR; - } - - r_res=RES(ResourceCache::get(path)); - } else { - r_res=RES(); - } - - VariantParser::get_token(p_stream,token,line,r_err_str); - if (token.type!=VariantParser::TK_PARENTHESIS_CLOSE) { - r_err_str="Expected ')'"; - return ERR_PARSE_ERROR; - } - - - return OK; -} - -Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str){ - - VariantParser::Token token; - VariantParser::get_token(p_stream,token,line,r_err_str); - if (token.type!=VariantParser::TK_NUMBER) { - r_err_str="Expected number (sub-resource index)"; - return ERR_PARSE_ERROR; - } - - int id = token.value; - - if (!ignore_resource_parsing) { - - if (!ext_resources.has(id)) { - r_err_str="Can't load cached ext-resource #"+itos(id); - return ERR_PARSE_ERROR; - } - - String path = ext_resources[id].path; - String type = ext_resources[id].type; - - if (path.find("://")==-1 && path.is_rel_path()) { - // path is relative to file being loaded, so convert to a resource path - path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); - - } - - r_res=ResourceLoader::load(path,type); - - if (r_res.is_null()) { - WARN_PRINT(String("Couldn't load external resource: "+path).utf8().get_data()); - } - } else { - r_res=RES(); - } - - VariantParser::get_token(p_stream,token,line,r_err_str); - if (token.type!=VariantParser::TK_PARENTHESIS_CLOSE) { - r_err_str="Expected ')'"; - return ERR_PARSE_ERROR; - } - - - return OK; -} - - -Error ResourceInteractiveLoaderText::poll() { - - if (error!=OK) - return error; - - if (next_tag.name=="ext_resource") { - - - if (!next_tag.fields.has("path")) { - error=ERR_FILE_CORRUPT; - error_text="Missing 'path' in external resource tag"; - _printerr(); - return error; - } - - if (!next_tag.fields.has("type")) { - error=ERR_FILE_CORRUPT; - error_text="Missing 'type' in external resource tag"; - _printerr(); - return error; - } - - if (!next_tag.fields.has("id")) { - error=ERR_FILE_CORRUPT; - error_text="Missing 'id' in external resource tag"; - _printerr(); - return error; - } - - String path=next_tag.fields["path"]; - String type=next_tag.fields["type"]; - int index=next_tag.fields["id"]; - - - if (path.find("://")==-1 && path.is_rel_path()) { - // path is relative to file being loaded, so convert to a resource path - path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); - } - - if (remaps.has(path)) { - path=remaps[path]; - } - - RES res = ResourceLoader::load(path,type); - - if (res.is_null()) { - - if (ResourceLoader::get_abort_on_missing_resources()) { - error=ERR_FILE_CORRUPT; - error_text="[ext_resource] referenced nonexistent resource at: "+path; - _printerr(); - return error; - } else { - ResourceLoader::notify_dependency_error(local_path,path,type); - } - } else { - - resource_cache.push_back(res); - } - - ExtResource er; - er.path=path; - er.type=type; - ext_resources[index]=er; - - error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); - - if (error) { - _printerr(); - } - - resource_current++; - return error; - - - } else if (next_tag.name=="sub_resource") { - - - if (!next_tag.fields.has("type")) { - error=ERR_FILE_CORRUPT; - error_text="Missing 'type' in external resource tag"; - _printerr(); - return error; - } - - if (!next_tag.fields.has("id")) { - error=ERR_FILE_CORRUPT; - error_text="Missing 'index' in external resource tag"; - _printerr(); - return error; - } - - String type=next_tag.fields["type"]; - int id=next_tag.fields["id"]; - - String path = local_path+"::"+itos(id); - - - //bool exists=ResourceCache::has(path); - - Ref res; - - if ( !ResourceCache::has(path)) { //only if it doesn't exist - - Object *obj = ObjectTypeDB::instance(type); - if (!obj) { - - error_text+="Can't create sub resource of type: "+type; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - - Resource *r = obj->cast_to(); - if (!r) { - - error_text+="Can't create sub resource of type, because not a resource: "+type; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - res=Ref(r); - resource_cache.push_back(res); - res->set_path(path); - - } - - resource_current++; - - while(true) { - - String assign; - Variant value; - - error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp); - - if (error) { - _printerr(); - return error; - } - - if (assign!=String()) { - if (res.is_valid()) { - res->set(assign,value); - } - //it's assignment - } else if (next_tag.name!=String()) { - - error=OK; - break; - } else { - error=ERR_FILE_CORRUPT; - error_text="Premature end of file while parsing [sub_resource]"; - _printerr(); - return error; - } - - - } - - return OK; - - } else if (next_tag.name=="resource") { - - if (is_scene) { - - error_text+="found the 'resource' tag on a scene file!"; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - Object *obj = ObjectTypeDB::instance(res_type); - if (!obj) { - - error_text+="Can't create sub resource of type: "+res_type; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - - Resource *r = obj->cast_to(); - if (!r) { - - error_text+="Can't create sub resource of type, because not a resource: "+res_type; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - resource=Ref(r); - - resource_current++; - - while(true) { - - String assign; - Variant value; - - error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp); - - if (error) { - if (error!=ERR_FILE_EOF) { - _printerr(); - } else { - if (!ResourceCache::has(res_path)) { - resource->set_path(res_path); - } - } - return error; - } - - if (assign!=String()) { - resource->set(assign,value); - //it's assignment - } else if (next_tag.name!=String()) { - - error=ERR_FILE_CORRUPT; - error_text="Extra tag found when parsing main resource file"; - _printerr(); - return error; - } else { - error=ERR_FILE_EOF; - return error; - } - - } - - return OK; - - } else if (next_tag.name=="node") { - - if (!is_scene) { - - error_text+="found the 'node' tag on a resource file!"; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - /* - int add_name(const StringName& p_name); - int add_value(const Variant& p_value); - int add_node_path(const NodePath& p_path); - int add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance); - void add_node_property(int p_node,int p_name,int p_value); - void add_node_group(int p_node,int p_group); - void set_base_scene(int p_idx); - void add_connection(int p_from,int p_to, int p_signal, int p_method, int p_flags,const Vector& p_binds); - void add_editable_instance(const NodePath& p_path); - - */ - - int parent=-1; - int owner=-1; - int type=-1; - int name=-1; - int instance=-1; -// int base_scene=-1; - - if (next_tag.fields.has("name")) { - name=packed_scene->get_state()->add_name(next_tag.fields["name"]); - } - - if (next_tag.fields.has("parent")) { - parent=packed_scene->get_state()->add_node_path(next_tag.fields["parent"]); - } - - - - if (next_tag.fields.has("type")) { - type=packed_scene->get_state()->add_name(next_tag.fields["type"]); - } else { - type=SceneState::TYPE_INSTANCED; //no type? assume this was instanced - } - - - if (next_tag.fields.has("instance")) { - - instance=packed_scene->get_state()->add_value(next_tag.fields["instance"]); - - if (packed_scene->get_state()->get_node_count()==0 && parent==-1) { - packed_scene->get_state()->set_base_scene(instance); - instance=-1; - } - } - - if (next_tag.fields.has("instance_placeholder")) { - - String path=next_tag.fields["instance_placeholder"]; - - int path_v = packed_scene->get_state()->add_value(path); - - if (packed_scene->get_state()->get_node_count()==0) { - error=ERR_FILE_CORRUPT; - error_text="Instance Placeholder can't be used for inheritance."; - _printerr(); - return error; - } - - instance=path_v|SceneState::FLAG_INSTANCE_IS_PLACEHOLDER; - } - - if (next_tag.fields.has("owner")) { - owner=packed_scene->get_state()->add_node_path(next_tag.fields["owner"]); - } else { - if (parent!=-1 && !(type==SceneState::TYPE_INSTANCED && instance==-1)) - owner=0; //if no owner, owner is root - } - - int node_id = packed_scene->get_state()->add_node(parent,owner,type,name,instance); - - if (next_tag.fields.has("groups")) { - - Array groups = next_tag.fields["groups"]; - for (int i=0;iget_state()->add_node_group(node_id,packed_scene->get_state()->add_name(groups[i])); - } - } - - while(true) { - - String assign; - Variant value; - - error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp); - - if (error) { - if (error!=ERR_FILE_EOF) { - _printerr(); - } else { - resource=packed_scene; - if (!ResourceCache::has(res_path)) { - packed_scene->set_path(res_path); - } - } - return error; - } - - if (assign!=String()) { - int nameidx = packed_scene->get_state()->add_name(assign); - int valueidx = packed_scene->get_state()->add_value(value); - packed_scene->get_state()->add_node_property(node_id,nameidx,valueidx); - //it's assignment - } else if (next_tag.name!=String()) { - - error=OK; - return error; - } else { - - resource=packed_scene; - error=ERR_FILE_EOF; - return error; - } - - } - - return OK; - - } else if (next_tag.name=="connection") { - - if (!is_scene) { - - error_text+="found the 'connection' tag on a resource file!"; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - if (!next_tag.fields.has("from")) { - error=ERR_FILE_CORRUPT; - error_text="missing 'from' field fron connection tag"; - return error; - } - - if (!next_tag.fields.has("to")) { - error=ERR_FILE_CORRUPT; - error_text="missing 'to' field fron connection tag"; - return error; - } - - if (!next_tag.fields.has("signal")) { - error=ERR_FILE_CORRUPT; - error_text="missing 'signal' field fron connection tag"; - return error; - } - - if (!next_tag.fields.has("method")) { - error=ERR_FILE_CORRUPT; - error_text="missing 'method' field fron connection tag"; - return error; - } - - NodePath from = next_tag.fields["from"]; - NodePath to = next_tag.fields["to"]; - StringName method = next_tag.fields["method"]; - StringName signal = next_tag.fields["signal"]; - int flags=CONNECT_PERSIST; - Array binds; - - if (next_tag.fields.has("flags")) { - flags=next_tag.fields["flags"]; - } - - if (next_tag.fields.has("binds")) { - binds=next_tag.fields["binds"]; - } - - Vector bind_ints; - for(int i=0;iget_state()->add_value( binds[i] ) ); - } - - packed_scene->get_state()->add_connection( - packed_scene->get_state()->add_node_path(from.simplified()), - packed_scene->get_state()->add_node_path(to.simplified()), - packed_scene->get_state()->add_name(signal), - packed_scene->get_state()->add_name(method), - flags, - bind_ints - ); - - error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); - - if (error) { - if (error!=ERR_FILE_EOF) { - _printerr(); - } else { - resource=packed_scene; - } - } - - return error; - } else if (next_tag.name=="editable") { - - if (!is_scene) { - - error_text+="found the 'editable' tag on a resource file!"; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - if (!next_tag.fields.has("path")) { - error=ERR_FILE_CORRUPT; - error_text="missing 'path' field fron connection tag"; - _printerr(); - return error; - } - - NodePath path = next_tag.fields["path"]; - - packed_scene->get_state()->add_editable_instance(path.simplified()); - - error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); - - if (error) { - if (error!=ERR_FILE_EOF) { - _printerr(); - } else { - resource=packed_scene; - } - } - - return error; - - } else { - - error_text+="Unknown tag in file: "+next_tag.name; - _printerr(); - error=ERR_FILE_CORRUPT; - return error; - } - - return OK; -} - -int ResourceInteractiveLoaderText::get_stage() const { - - return resource_current; -} -int ResourceInteractiveLoaderText::get_stage_count() const { - - return resources_total;//+ext_resources; -} - -ResourceInteractiveLoaderText::~ResourceInteractiveLoaderText() { - - memdelete(f); -} - -void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f,List *p_dependencies,bool p_add_types) { - - - open(f); - ignore_resource_parsing=true; - ERR_FAIL_COND(error!=OK); - - while(next_tag.name=="ext_resource") { - - if (!next_tag.fields.has("type")) { - error=ERR_FILE_CORRUPT; - error_text="Missing 'type' in external resource tag"; - _printerr(); - return; - } - - if (!next_tag.fields.has("id")) { - error=ERR_FILE_CORRUPT; - error_text="Missing 'index' in external resource tag"; - _printerr(); - return; - } - - String path=next_tag.fields["path"]; - String type=next_tag.fields["type"]; - - - if (path.find("://")==-1 && path.is_rel_path()) { - // path is relative to file being loaded, so convert to a resource path - path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path)); - } - - - if (p_add_types) { - path+="::"+type; - } - - p_dependencies->push_back(path); - - Error err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); - - if (err) { - print_line(error_text+" - "+itos(lines)); - error_text="Unexpected end of file"; - _printerr(); - error=ERR_FILE_CORRUPT; - } - - - } -} - -Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map& p_map) { - - - open(p_f,true); - ERR_FAIL_COND_V(error!=OK,error); - ignore_resource_parsing=true; - //FileAccess - - FileAccess *fw = NULL; - - String base_path=local_path.get_base_dir(); - - - uint64_t tag_end = f->get_pos(); - - - while(true) { - - - - Error err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); - - if (err!=OK) { - if (fw) { - memdelete(fw); - } - error=ERR_FILE_CORRUPT; - ERR_FAIL_V(error); - } - - if (next_tag.name!="ext_resource") { - - //nothing was done - if (!fw) - return OK; - - break; - - - } else { - - if (!fw) { - - fw=FileAccess::open(p_path+".depren",FileAccess::WRITE); - if (is_scene) { - fw->store_line("[gd_scene load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n"); - } else { - fw->store_line("[gd_resource type=\""+res_type+"\" load_steps="+itos(resources_total)+" format="+itos(FORMAT_VERSION)+"]\n"); - } - } - - if (!next_tag.fields.has("path") || !next_tag.fields.has("id") || !next_tag.fields.has("type")) { - memdelete(fw); - error=ERR_FILE_CORRUPT; - ERR_FAIL_V(error); - } - - String path = next_tag.fields["path"]; - int index = next_tag.fields["id"]; - String type = next_tag.fields["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); - } - - fw->store_line("[ext_resource path=\""+path+"\" type=\""+type+"\" id="+itos(index)+"]"); - - tag_end = f->get_pos(); - - } - - } - - f->seek(tag_end); - - uint8_t c=f->get_8(); - while(!f->eof_reached()) { - fw->store_8(c); - c=f->get_8(); - } - f->close(); - - 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); - - return OK; - -} - - -void ResourceInteractiveLoaderText::open(FileAccess *p_f,bool p_skip_first_tag) { - - error=OK; - - lines=1; - f=p_f; - - - stream.f=f; - is_scene=false; - ignore_resource_parsing=false; - resource_current=0; - - - VariantParser::Tag tag; - Error err = VariantParser::parse_tag(&stream,lines,error_text,tag); - - if (err) { - - error=err; - _printerr(); - return; - } - - if (tag.fields.has("format")) { - int fmt = tag.fields["format"]; - if (fmt>FORMAT_VERSION) { - error_text="Saved with newer format version"; - _printerr(); - error=ERR_PARSE_ERROR; - return; - } - } - - - if (tag.name=="gd_scene") { - is_scene=true; - packed_scene.instance(); - - } else if (tag.name=="gd_resource") { - if (!tag.fields.has("type")) { - error_text="Missing 'type' field in 'gd_resource' tag"; - _printerr(); - error=ERR_PARSE_ERROR; - return; - } - - res_type=tag.fields["type"]; - - } else { - error_text="Unrecognized file type: "+tag.name; - _printerr(); - error=ERR_PARSE_ERROR; - return; - - } - - - - if (tag.fields.has("load_steps")) { - resources_total=tag.fields["load_steps"]; - } else { - resources_total=0; - } - - if (!p_skip_first_tag) { - - err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); - - if (err) { - error_text="Unexpected end of file"; - _printerr(); - error=ERR_FILE_CORRUPT; - } - } - - rp.ext_func=_parse_ext_resources; - rp.sub_func=_parse_sub_resources; - rp.func=NULL; - rp.userdata=this; - -} - - - - -String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { - - error=OK; - - lines=1; - f=p_f; - - stream.f=f; - - ignore_resource_parsing=true; - - - VariantParser::Tag tag; - Error err = VariantParser::parse_tag(&stream,lines,error_text,tag); - - if (err) { - _printerr(); - return ""; - } - - if (tag.fields.has("format")) { - int fmt = tag.fields["format"]; - if (fmt>FORMAT_VERSION) { - error_text="Saved with newer format version"; - _printerr(); - return ""; - } - } - - if (tag.name=="gd_scene") - return "PackedScene"; - - if (tag.name!="gd_resource") - return ""; - - - - if (!tag.fields.has("type")) { - error_text="Missing 'type' field in 'gd_resource' tag"; - _printerr(); - return ""; - } - - return tag.fields["type"]; - - -} - -///////////////////// - -Ref ResourceFormatLoaderText::load_interactive(const String &p_path, Error *r_error) { - - if (r_error) - *r_error=ERR_CANT_OPEN; - - Error err; - FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); - - - if (err!=OK) { - - ERR_FAIL_COND_V(err!=OK,Ref()); - } - - Ref ria = memnew( ResourceInteractiveLoaderText ); - ria->local_path=Globals::get_singleton()->localize_path(p_path); - ria->res_path=ria->local_path; -// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); - ria->open(f); - - return ria; -} - -void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const { - - if (p_type=="") { - get_recognized_extensions(p_extensions); - return; - } - - if (p_type=="PackedScene") - p_extensions->push_back("tscn"); - else - p_extensions->push_back("tres"); - -} - -void ResourceFormatLoaderText::get_recognized_extensions(List *p_extensions) const{ - - p_extensions->push_back("tscn"); - p_extensions->push_back("tres"); -} - -bool ResourceFormatLoaderText::handles_type(const String& p_type) const{ - - return true; -} -String ResourceFormatLoaderText::get_resource_type(const String &p_path) const{ - - - - String ext=p_path.extension().to_lower(); - if (ext=="tscn") - return "PackedScene"; - else if (ext!="tres") - return String(); - - //for anyhting else must test.. - - FileAccess *f = FileAccess::open(p_path,FileAccess::READ); - if (!f) { - - return ""; //could not rwead - } - - Ref ria = memnew( ResourceInteractiveLoaderText ); - ria->local_path=Globals::get_singleton()->localize_path(p_path); - ria->res_path=ria->local_path; -// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); - String r = ria->recognize(f); - return r; -} - - -void ResourceFormatLoaderText::get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types) { - - FileAccess *f = FileAccess::open(p_path,FileAccess::READ); - if (!f) { - - ERR_FAIL(); - } - - Ref ria = memnew( ResourceInteractiveLoaderText ); - ria->local_path=Globals::get_singleton()->localize_path(p_path); - ria->res_path=ria->local_path; -// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); - ria->get_dependencies(f,p_dependencies,p_add_types); - - -} - -Error ResourceFormatLoaderText::rename_dependencies(const String &p_path,const Map& p_map) { - - FileAccess *f = FileAccess::open(p_path,FileAccess::READ); - if (!f) { - - ERR_FAIL_V(ERR_CANT_OPEN); - } - - Ref ria = memnew( ResourceInteractiveLoaderText ); - ria->local_path=Globals::get_singleton()->localize_path(p_path); - ria->res_path=ria->local_path; -// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); - return ria->rename_dependencies(f,p_path,p_map); -} - - -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ -/*****************************************************************************************************/ - - -String ResourceFormatSaverTextInstance::_write_resources(void *ud,const RES& p_resource) { - - ResourceFormatSaverTextInstance *rsi=(ResourceFormatSaverTextInstance*)ud; - return rsi->_write_resource(p_resource); - -} - -String ResourceFormatSaverTextInstance::_write_resource(const RES& res) { - - if (external_resources.has(res)) { - - return "ExtResource( "+itos(external_resources[res]+1)+" )"; - } else { - - if (internal_resources.has(res)) { - return "SubResource( "+itos(internal_resources[res])+" )"; - } else if (res->get_path().length() && res->get_path().find("::")==-1) { - - //external resource - String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path(); - return "Resource( \""+path+"\" )"; - } else { - ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?"); - ERR_FAIL_V("null"); - //internal resource - } - } - - return "null"; -} - -void ResourceFormatSaverTextInstance::_find_resources(const Variant& p_variant,bool p_main) { - - - switch(p_variant.get_type()) { - case Variant::OBJECT: { - - - RES res = p_variant.operator RefPtr(); - - if (res.is_null() || external_resources.has(res)) - return; - - if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) { - int index = external_resources.size(); - external_resources[res]=index; - return; - } - - if (resource_set.has(res)) - return; - - List property_list; - - res->get_property_list( &property_list ); - property_list.sort(); - - List::Element *I=property_list.front(); - - while(I) { - - PropertyInfo pi=I->get(); - - if (pi.usage&PROPERTY_USAGE_STORAGE || (bundle_resources && pi.usage&PROPERTY_USAGE_BUNDLE)) { - - Variant v=res->get(I->get().name); - _find_resources(v); - } - - I=I->next(); - } - - resource_set.insert( res ); //saved after, so the childs it needs are available when loaded - saved_resources.push_back(res); - - } break; - case Variant::ARRAY: { - - Array varray=p_variant; - int len=varray.size(); - for(int i=0;i keys; - d.get_key_list(&keys); - for(List::Element *E=keys.front();E;E=E->next()) { - - Variant v = d[E->get()]; - _find_resources(v); - } - } break; - default: {} - } - -} - -static String _valprop(const String& p_name) { - - if (p_name.find("\"")!=-1 || p_name.find("=")!=-1 || p_name.find(" ")!=-1) - return "\""+p_name.c_escape()+"\""; - return p_name; -} - -Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_resource,uint32_t p_flags) { - - if (p_path.ends_with(".tscn")) { - packed_scene=p_resource; - } - - Error err; - f = FileAccess::open(p_path, FileAccess::WRITE,&err); - ERR_FAIL_COND_V( err, ERR_CANT_OPEN ); - FileAccessRef _fref(f); - - local_path = Globals::get_singleton()->localize_path(p_path); - - relative_paths=p_flags&ResourceSaver::FLAG_RELATIVE_PATHS; - skip_editor=p_flags&ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES; - bundle_resources=p_flags&ResourceSaver::FLAG_BUNDLE_RESOURCES; - takeover_paths=p_flags&ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS; - if (!p_path.begins_with("res://")) { - takeover_paths=false; - } - - // save resources - _find_resources(p_resource,true); - - if (packed_scene.is_valid()) { - //add instances to external resources if saving a packed scene - for(int i=0;iget_state()->get_node_count();i++) { - if (packed_scene->get_state()->is_node_instance_placeholder(i)) - continue; - - Ref instance=packed_scene->get_state()->get_node_instance(i); - if (instance.is_valid() && !external_resources.has(instance)) { - int index = external_resources.size(); - external_resources[instance]=index; - } - } - } - - - ERR_FAIL_COND_V(err!=OK,err); - - { - String title=packed_scene.is_valid()?"[gd_scene ":"[gd_resource "; - if (packed_scene.is_null()) - title+="type=\""+p_resource->get_type()+"\" "; - int load_steps=saved_resources.size()+external_resources.size(); - //if (packed_scene.is_valid()) { - // load_steps+=packed_scene->get_node_count(); - //} - //no, better to not use load steps from nodes, no point to that - - if (load_steps>1) { - title+="load_steps="+itos(load_steps)+" "; - } - title+="format="+itos(FORMAT_VERSION)+""; - //title+="engine_version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\""; - - f->store_string(title); - f->store_line("]\n"); //one empty line - } - - - Vector sorted_er; - sorted_er.resize(external_resources.size()); - - for(Map::Element *E=external_resources.front();E;E=E->next()) { - - sorted_er[E->get()]=E->key(); - } - - for(int i=0;iget_path(); - - f->store_string("[ext_resource path=\""+p+"\" type=\""+sorted_er[i]->get_save_type()+"\" id="+itos(i+1)+"]\n"); //bundled - } - - if (external_resources.size()) - f->store_line(String()); //separate - - Set used_indices; - - for(List::Element *E=saved_resources.front();E;E=E->next()) { - - RES res = E->get(); - if (E->next() && (res->get_path()=="" || res->get_path().find("::") != -1 )) { - - if (res->get_subindex()!=0) { - if (used_indices.has(res->get_subindex())) { - res->set_subindex(0); //repeated - } else { - used_indices.insert(res->get_subindex()); - } - } - } - } - - for(List::Element *E=saved_resources.front();E;E=E->next()) { - - RES res = E->get(); - ERR_CONTINUE(!resource_set.has(res)); - bool main = (E->next()==NULL); - - if (main && packed_scene.is_valid()) - break; //save as a scene - - if (main) { - f->store_line("[resource]\n"); - } else { - String line="[sub_resource "; - if (res->get_subindex()==0) { - int new_subindex=1; - if (used_indices.size()) { - new_subindex=used_indices.back()->get()+1; - } - - res->set_subindex(new_subindex); - used_indices.insert(new_subindex); - } - - int idx = res->get_subindex(); - line+="type=\""+res->get_type()+"\" id="+itos(idx); - f->store_line(line+"]\n"); - if (takeover_paths) { - res->set_path(p_path+"::"+itos(idx),true); - } - - internal_resources[res]=idx; - - } - - - List property_list; - res->get_property_list(&property_list); -// property_list.sort(); - for(List::Element *PE = property_list.front();PE;PE=PE->next()) { - - - if (skip_editor && PE->get().name.begins_with("__editor")) - continue; - - if (PE->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && PE->get().usage&PROPERTY_USAGE_BUNDLE)) { - - String name = PE->get().name; - Variant value = res->get(name); - - - if ((PE->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())||(PE->get().usage&PROPERTY_USAGE_STORE_IF_NONONE && value.is_one()) ) - continue; - - if (PE->get().type==Variant::OBJECT && value.is_zero() && !(PE->get().usage&PROPERTY_USAGE_STORE_IF_NULL)) - continue; - - String vars; - VariantWriter::write_to_string(value,vars,_write_resources,this); - f->store_string(_valprop(name)+" = "+vars+"\n"); - } - - - } - - f->store_string("\n"); - - } - - if (packed_scene.is_valid()) { - //if this is a scene, save nodes and connections! - Ref state = packed_scene->get_state(); - for(int i=0;iget_node_count();i++) { - - StringName type = state->get_node_type(i); - StringName name = state->get_node_name(i); - NodePath path = state->get_node_path(i,true); - NodePath owner = state->get_node_owner_path(i); - Ref instance = state->get_node_instance(i); - String instance_placeholder = state->get_node_instance_placeholder(i); - Vector groups = state->get_node_groups(i); - - - - String header="[node"; - header+=" name=\""+String(name)+"\""; - if (type!=StringName()) { - header+=" type=\""+String(type)+"\""; - } - if (path!=NodePath()) { - header+=" parent=\""+String(path.simplified())+"\""; - } - if (owner!=NodePath() && owner!=NodePath(".")) { - header+=" owner=\""+String(owner.simplified())+"\""; - } - - if (groups.size()) { - String sgroups=" groups=[ "; - for(int j=0;j0) - sgroups+=", "; - sgroups+="\""+groups[j].operator String().c_escape()+"\""; - } - sgroups+=" ]"; - header+=sgroups; - } - - f->store_string(header); - - if (instance_placeholder!=String()) { - - String vars; - f->store_string(" instance_placeholder="); - VariantWriter::write_to_string(instance_placeholder,vars,_write_resources,this); - f->store_string(vars); - } - - if (instance.is_valid()) { - - String vars; - f->store_string(" instance="); - VariantWriter::write_to_string(instance,vars,_write_resources,this); - f->store_string(vars); - - } - - f->store_line("]\n"); - - for(int j=0;jget_node_property_count(i);j++) { - - String vars; - VariantWriter::write_to_string(state->get_node_property_value(i,j),vars,_write_resources,this); - - f->store_string(_valprop(String(state->get_node_property_name(i,j)))+" = "+vars+"\n"); - } - - if (state->get_node_property_count(i)) { - //add space - f->store_line(String()); - } - - } - - for(int i=0;iget_connection_count();i++) { - - String connstr="[connection"; - connstr+=" signal=\""+String(state->get_connection_signal(i))+"\""; - connstr+=" from=\""+String(state->get_connection_source(i).simplified())+"\""; - connstr+=" to=\""+String(state->get_connection_target(i).simplified())+"\""; - connstr+=" method=\""+String(state->get_connection_method(i))+"\""; - int flags = state->get_connection_flags(i); - if (flags!=Object::CONNECT_PERSIST) { - connstr+=" flags="+itos(flags); - } - - Array binds=state->get_connection_binds(i); - f->store_string(connstr); - if (binds.size()) { - String vars; - VariantWriter::write_to_string(binds,vars,_write_resources,this); - f->store_string(" binds= "+vars); - - } - - f->store_line("]\n"); - } - - f->store_line(String()); - - Vector editable_instances = state->get_editable_instances(); - for(int i=0;istore_line("[editable path=\""+editable_instances[i].operator String()+"\"]"); - } - } - - if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) { - f->close(); - return ERR_CANT_CREATE; - } - - f->close(); - //memdelete(f); - - return OK; -} - - - -Error ResourceFormatSaverText::save(const String &p_path,const RES& p_resource,uint32_t p_flags) { - - if (p_path.ends_with(".sct") && p_resource->get_type()!="PackedScene") { - return ERR_FILE_UNRECOGNIZED; - } - - ResourceFormatSaverTextInstance saver; - return saver.save(p_path,p_resource,p_flags); - -} - -bool ResourceFormatSaverText::recognize(const RES& p_resource) const { - - - return true; // all recognized! -} -void ResourceFormatSaverText::get_recognized_extensions(const RES& p_resource,List *p_extensions) const { - - if (p_resource->get_type()=="PackedScene") - p_extensions->push_back("tscn"); //text scene - else - p_extensions->push_back("tres"); //text resource - -} - -ResourceFormatSaverText* ResourceFormatSaverText::singleton=NULL; -ResourceFormatSaverText::ResourceFormatSaverText() { - singleton=this; -} diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h deleted file mode 100644 index 6122a1f9d8..0000000000 --- a/scene/resources/scene_format_text.h +++ /dev/null @@ -1,170 +0,0 @@ -/*************************************************************************/ -/* scene_format_text.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SCENE_FORMAT_TEXT_H -#define SCENE_FORMAT_TEXT_H - -#include "io/resource_loader.h" -#include "io/resource_saver.h" -#include "os/file_access.h" -#include "scene/resources/packed_scene.h" -#include "variant_parser.h" - - - -class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { - - String local_path; - String res_path; - String error_text; - - FileAccess *f; - - VariantParser::StreamFile stream; - - struct ExtResource { - String path; - String type; - }; - - - bool is_scene; - String res_type; - - bool ignore_resource_parsing; - -// Map remaps; - - Map ext_resources; - - int resources_total; - int resource_current; - String resource_type; - - VariantParser::Tag next_tag; - - mutable int lines; - - Map remaps; - //void _printerr(); - - static Error _parse_sub_resources(void* p_self, VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str) { return reinterpret_cast(p_self)->_parse_sub_resource(p_stream,r_res,line,r_err_str); } - static Error _parse_ext_resources(void* p_self, VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str) { return reinterpret_cast(p_self)->_parse_ext_resource(p_stream,r_res,line,r_err_str); } - - Error _parse_sub_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str); - Error _parse_ext_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str); - - VariantParser::ResourceParser rp; - - - Ref packed_scene; - - -friend class ResourceFormatLoaderText; - - List resource_cache; - Error error; - - RES resource; - -public: - - virtual void set_local_path(const String& p_local_path); - virtual Ref get_resource(); - virtual Error poll(); - virtual int get_stage() const; - virtual int get_stage_count() const; - - void open(FileAccess *p_f, bool p_skip_first_tag=false); - String recognize(FileAccess *p_f); - void get_dependencies(FileAccess *p_f, List *p_dependencies, bool p_add_types); - Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map& p_map); - - - ~ResourceInteractiveLoaderText(); - -}; - - - -class ResourceFormatLoaderText : public ResourceFormatLoader { -public: - - virtual Ref load_interactive(const String &p_path,Error *r_error=NULL); - virtual void get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const; - virtual void get_recognized_extensions(List *p_extensions) const; - virtual bool handles_type(const String& p_type) const; - virtual String get_resource_type(const String &p_path) const; - virtual void get_dependencies(const String& p_path, List *p_dependencies, bool p_add_types=false); - virtual Error rename_dependencies(const String &p_path,const Map& p_map); - - -}; - - -class ResourceFormatSaverTextInstance { - - String local_path; - - Ref packed_scene; - - bool takeover_paths; - bool relative_paths; - bool bundle_resources; - bool skip_editor; - FileAccess *f; - Set resource_set; - List saved_resources; - Map external_resources; - Map internal_resources; - - void _find_resources(const Variant& p_variant,bool p_main=false); - - static String _write_resources(void *ud,const RES& p_resource); - String _write_resource(const RES& res); - - -public: - - Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); - - -}; - -class ResourceFormatSaverText : public ResourceFormatSaver { -public: - static ResourceFormatSaverText* singleton; - virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); - virtual bool recognize(const RES& p_resource) const; - virtual void get_recognized_extensions(const RES& p_resource,List *p_extensions) const; - - ResourceFormatSaverText(); -}; - - -#endif // SCENE_FORMAT_TEXT_H -- cgit v1.2.3 From 92f10a358289df3d81bc796a9d37dbd90afb39a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Tue, 28 Jun 2016 18:58:40 +0200 Subject: Tidy up population of extensions list --- core/io/resource_format_binary.cpp | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 58f3a4df2b..343a54e0d7 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1105,14 +1105,9 @@ void ResourceFormatLoaderBinary::get_recognized_extensions_for_type(const String for(List::Element *E=extensions.front();E;E=E->next()) { String ext = E->get().to_lower(); - if (ext=="res") - continue; -// p_extensions->push_back("x"+ext); p_extensions->push_back(ext); } - p_extensions->push_back("res"); - } void ResourceFormatLoaderBinary::get_recognized_extensions(List *p_extensions) const{ @@ -1122,12 +1117,9 @@ void ResourceFormatLoaderBinary::get_recognized_extensions(List *p_exten for(List::Element *E=extensions.front();E;E=E->next()) { String ext = E->get().to_lower(); - if (ext=="res") - continue; p_extensions->push_back(ext); } - p_extensions->push_back("res"); } bool ResourceFormatLoaderBinary::handles_type(const String& p_type) const{ @@ -2270,16 +2262,8 @@ bool ResourceFormatSaverBinary::recognize(const RES& p_resource) const { void ResourceFormatSaverBinary::get_recognized_extensions(const RES& p_resource,List *p_extensions) const { - - //here comes the sun, lalalala String base = p_resource->get_base_extension().to_lower(); - if (base!="res") { - - p_extensions->push_back(base); - } - - p_extensions->push_back("res"); - + p_extensions->push_back(base); } -- cgit v1.2.3 From 1492fd846073a4fa643365a8a5d4e021868c0e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Tue, 28 Jun 2016 19:08:41 +0200 Subject: Make text formats preferent over binary ones --- core/register_core_types.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 0e73639e97..65427b1ea7 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -100,17 +100,17 @@ void register_core_types() { resource_format_po = memnew( TranslationLoaderPO ); ResourceLoader::add_resource_format_loader( resource_format_po ); + // Register text formats before to give them precedence on saving + resource_saver_text = memnew( ResourceFormatSaverText ); + ResourceSaver::add_resource_format_saver(resource_saver_text); + resource_loader_text = memnew( ResourceFormatLoaderText ); + ResourceLoader::add_resource_format_loader(resource_loader_text); resource_saver_binary = memnew( ResourceFormatSaverBinary ); ResourceSaver::add_resource_format_saver(resource_saver_binary); resource_loader_binary = memnew( ResourceFormatLoaderBinary ); ResourceLoader::add_resource_format_loader(resource_loader_binary); - resource_saver_text = memnew( ResourceFormatSaverText ); - ResourceSaver::add_resource_format_saver(resource_saver_text); - resource_loader_text = memnew( ResourceFormatLoaderText ); - ResourceLoader::add_resource_format_loader(resource_loader_text); - #ifdef XML_ENABLED resource_saver_xml = memnew( ResourceFormatSaverXML ); ResourceSaver::add_resource_format_saver(resource_saver_xml); -- cgit v1.2.3