diff options
| author | Juan Linietsky | 2017-02-12 22:52:02 -0300 |
|---|---|---|
| committer | Juan Linietsky | 2017-02-12 23:13:14 -0300 |
| commit | ebb7d2cdb7c5cd755f0b4b69db934df9cc15b1d6 (patch) | |
| tree | 54834d4b17f9ec1c164ea213e5343104d37308b6 | |
| parent | 6abe141579742a0a84234bc71257d7b037511f36 (diff) | |
| download | godot-ebb7d2cdb7c5cd755f0b4b69db934df9cc15b1d6.tar.gz godot-ebb7d2cdb7c5cd755f0b4b69db934df9cc15b1d6.tar.zst godot-ebb7d2cdb7c5cd755f0b4b69db934df9cc15b1d6.zip | |
-WIP Exporter to Godot 3.0, only text scenes (no .scn) and still kind of buggy
Diffstat (limited to '')
| -rw-r--r-- | core/io/export_data.cpp | 2 | ||||
| -rw-r--r-- | core/io/export_data.h | 86 | ||||
| -rw-r--r-- | core/io/resource_format_binary.cpp | 177 | ||||
| -rw-r--r-- | core/io/resource_format_binary.h | 7 | ||||
| -rw-r--r-- | core/io/resource_format_xml.cpp | 184 | ||||
| -rw-r--r-- | core/io/resource_format_xml.h | 6 | ||||
| -rw-r--r-- | core/io/resource_loader.cpp | 28 | ||||
| -rw-r--r-- | core/io/resource_loader.h | 5 | ||||
| -rw-r--r-- | core/os/dir_access.cpp | 2 | ||||
| -rw-r--r-- | core/variant_parser.cpp | 13 | ||||
| -rw-r--r-- | core/variant_parser.h | 2 | ||||
| -rw-r--r-- | scene/resources/scene_format_text.cpp | 477 | ||||
| -rw-r--r-- | scene/resources/scene_format_text.h | 21 | ||||
| -rw-r--r-- | tools/editor/editor_export_godot3.cpp | 1358 | ||||
| -rw-r--r-- | tools/editor/editor_export_godot3.h | 66 | ||||
| -rw-r--r-- | tools/editor/editor_node.cpp | 20 | ||||
| -rw-r--r-- | tools/editor/editor_node.h | 7 |
17 files changed, 2395 insertions, 66 deletions
diff --git a/core/io/export_data.cpp b/core/io/export_data.cpp new file mode 100644 index 000000000..2495288a7 --- /dev/null +++ b/core/io/export_data.cpp @@ -0,0 +1,2 @@ +#include "export_data.h" + diff --git a/core/io/export_data.h b/core/io/export_data.h new file mode 100644 index 000000000..17ee60f33 --- /dev/null +++ b/core/io/export_data.h @@ -0,0 +1,86 @@ +#ifndef EXPORT_DATA_H +#define EXPORT_DATA_H + +#include "variant.h" +#include "vector.h" +#include "map.h" +struct ExportData { + + struct Dependency { + String path; + String type; + }; + + Map<int,Dependency> dependencies; + + struct PropertyData { + String name; + Variant value; + }; + + struct ResourceData { + + String type; + int index; + List<PropertyData> properties; + + }; + + Vector<ResourceData> resources; + + + struct NodeData { + + bool text_data; + String name; + String type; + String instance; + //int info + int owner_int; //depending type + int parent_int; + bool instance_is_placeholder; + + + //text info + NodePath parent; + NodePath owner; + String instance_placeholder; + + + + Vector<String> groups; + List<PropertyData> properties; + + + NodeData() { parent_int=0; owner_int=0; text_data=true; } + }; + + Vector<NodeData> nodes; + + struct Connection { + + bool text_data; + + int from_int; + int to_int; + + NodePath from; + NodePath to; + String signal; + String method; + Array binds; + int flags; + + Connection() { text_data=true; } + }; + + Vector<Connection> connections; + Vector<NodePath> editables; + + Array node_paths; //for integer packed data + Variant base_scene; + + +}; + +#endif // EXPORT_DATA_H diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index a49b1f79c..2b6cfe051 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -118,7 +118,7 @@ void ResourceInteractiveLoaderBinary::_advance_padding(uint32_t p_len) { } -Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { +Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v,bool p_for_export_data) { uint32_t type = f->get_32(); @@ -378,62 +378,79 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { } break; case OBJECT_INTERNAL_RESOURCE: { uint32_t index=f->get_32(); - String path = res_path+"::"+itos(index); - RES res = ResourceLoader::load(path); - if (res.is_null()) { - WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); + + if (p_for_export_data) { + + r_v="@RESLOCAL:"+itos(index); + } else { + String path = res_path+"::"+itos(index); + RES res = ResourceLoader::load(path); + if (res.is_null()) { + WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); + } + r_v=res; } - r_v=res; } break; case OBJECT_EXTERNAL_RESOURCE: { //old file format, still around for compatibility + String type = get_unicode_string(); String path = get_unicode_string(); - 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)); + if (p_for_export_data) { - } + r_v="@RESPATH:"+type+":"+path; + } else { - if (remaps.find(path)) { - path=remaps[path]; - } + 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)); - RES res=ResourceLoader::load(path,type); + } + + if (remaps.find(path)) { + path=remaps[path]; + } - if (res.is_null()) { - WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); + RES res=ResourceLoader::load(path,type); + + if (res.is_null()) { + WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); + } + r_v=res; } - r_v=res; } break; case OBJECT_EXTERNAL_RESOURCE_INDEX: { //new file format, just refers to an index in the external list uint32_t erindex = f->get_32(); - if (erindex>=external_resources.size()) { - WARN_PRINT("Broken external resource! (index out of size"); - r_v=Variant(); + if (p_for_export_data) { + r_v="@RESEXTERNAL:"+itos(erindex); } else { + if (erindex>=external_resources.size()) { + WARN_PRINT("Broken external resource! (index out of size"); + r_v=Variant(); + } else { - String type = external_resources[erindex].type; - String path = external_resources[erindex].path; + String type = external_resources[erindex].type; + String path = external_resources[erindex].path; - 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)); + 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)); - } + } - RES res=ResourceLoader::load(path,type); + RES res=ResourceLoader::load(path,type); - if (res.is_null()) { - WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); + if (res.is_null()) { + WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data()); + } + r_v=res; } - r_v=res; } @@ -455,10 +472,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { len&=0x7FFFFFFF; for(uint32_t i=0;i<len;i++) { Variant key; - Error err = parse_variant(key); + Error err = parse_variant(key,p_for_export_data); ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT); Variant value; - err = parse_variant(value); + err = parse_variant(value,p_for_export_data); ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT); d[key]=value; } @@ -472,7 +489,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { a.resize(len); for(uint32_t i=0;i<len;i++) { Variant val; - Error err = parse_variant(val); + Error err = parse_variant(val,p_for_export_data); ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT); a[i]=val; } @@ -862,6 +879,77 @@ String ResourceInteractiveLoaderBinary::get_unicode_string() { return s; } +Error ResourceInteractiveLoaderBinary::get_export_data(ExportData& r_export_data) { + + for(int i=0;i<external_resources.size();i++) { + ExportData::Dependency dep; + dep.path=external_resources[i].path; + dep.type=external_resources[i].type; + r_export_data.dependencies[i]=dep; + } + + for(int i=0;i<internal_resources.size();i++) { + + bool main = i==(internal_resources.size()-1); + + //maybe it is loaded already + + + r_export_data.resources.resize( r_export_data.resources.size()+1 ); + ExportData::ResourceData &res_data=r_export_data.resources[ r_export_data.resources.size()-1 ]; + + res_data.index=-1; + + if (!main) { + + String path=internal_resources[i].path; + if (path.begins_with("local://")) { + path=path.replace_first("local://",""); + res_data.index = path.to_int(); + } + } else { + + } + + uint64_t offset = internal_resources[i].offset; + + f->seek(offset); + + String t = get_unicode_string(); + + res_data.type=t; + + int pc = f->get_32(); + + //set properties + + for(int i=0;i<pc;i++) { + + uint32_t name_idx = f->get_32(); + if (name_idx>=(uint32_t)string_map.size()) { + error=ERR_FILE_CORRUPT; + ERR_FAIL_V(ERR_FILE_CORRUPT); + } + + Variant value; + + error = parse_variant(value,true); + if (error) + return error; + + ExportData::PropertyData pdata; + pdata.name=string_map[name_idx]; + pdata.value=value; + + res_data.properties.push_back(pdata); + } + + } + + return OK; +} + + void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List<String> *p_dependencies,bool p_add_types) { @@ -1175,6 +1263,7 @@ Error ResourceFormatLoaderBinary::load_import_metadata(const String &p_path, Ref } +ResourceFormatLoaderBinary *ResourceFormatLoaderBinary::singleton=NULL; void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types) { @@ -1188,6 +1277,28 @@ void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<Stri ria->get_dependencies(f,p_dependencies,p_add_types); } + +Error ResourceFormatLoaderBinary::get_export_data(const String& p_path,ExportData& r_export_data) { + + Error err; + FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); + + if (err!=OK) { + + ERR_FAIL_COND_V(err!=OK,ERR_CANT_OPEN); + } + + Ref<ResourceInteractiveLoaderBinary> ria = memnew( ResourceInteractiveLoaderBinary ); + 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->get_export_data(r_export_data); + +} + Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path,const Map<String,String>& p_map) { diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 611029e79..566767b83 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -79,7 +79,7 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader { friend class ResourceFormatLoaderBinary; - Error parse_variant(Variant& r_v); + Error parse_variant(Variant& r_v, bool p_for_export_data=false); public: @@ -94,6 +94,7 @@ public: String recognize(FileAccess *p_f); void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types); + Error get_export_data(ExportData& r_export_data); ResourceInteractiveLoaderBinary(); ~ResourceInteractiveLoaderBinary(); @@ -111,9 +112,11 @@ public: virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false); virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const; virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map); + virtual Error get_export_data(const String& p_path,ExportData& r_export_data); + static ResourceFormatLoaderBinary *singleton; - + ResourceFormatLoaderBinary() { singleton=this; } }; diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index cc0a3b488..8be6a32f6 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -339,7 +339,7 @@ Error ResourceInteractiveLoaderXML::_parse_array_element(Vector<char> &buff,bool return OK; } -Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) { +Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name, bool p_for_export_data) { bool exit; Tag *tag = parse_tag(&exit); @@ -382,7 +382,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) int dictline = get_current_line(); - err=parse_property(key,tagname); + err=parse_property(key,tagname,p_for_export_data); if (err && err!=ERR_FILE_EOF) { ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error parsing dictionary: "+name+" (from line "+itos(dictline)+")"); @@ -392,7 +392,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) if (err) break; Variant value; - err=parse_property(value,tagname); + err=parse_property(value,tagname,p_for_export_data); if (err) { ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error parsing dictionary: "+name+" (from line "+itos(dictline)+")"); } @@ -429,7 +429,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) Variant v; String tagname; int idx=0; - while( (err=parse_property(v,tagname))==OK ) { + while( (err=parse_property(v,tagname,p_for_export_data))==OK ) { ERR_CONTINUE( idx <0 || idx >=len ); @@ -463,7 +463,20 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) if (tag->args.has("resource_type")) hint=tag->args["resource_type"]; + if (p_for_export_data) { + + String prop; + + if (path.begins_with("local://")) { + prop="@RESLOCAL:"+itos(path.replace("local://","").to_int()); + } + + r_v=prop; + return OK; + } + if (path.begins_with("local://")) + path=path.replace("local://",local_path+"::"); else if (path.find("://")==-1 && path.is_rel_path()) { // path is relative to file being loaded, so convert to a resource path @@ -488,6 +501,18 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) } else if (tag->args.has("external")) { int index = tag->args["external"].to_int(); + + + if (p_for_export_data) { + + String prop; + + prop="@RESEXTERNAL:"+itos(index); + + r_v=prop; + return OK; + } + if (ext_resources.has(index)) { String path=ext_resources[index].path; String type=ext_resources[index].type; @@ -1653,6 +1678,139 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> * } +Error ResourceInteractiveLoaderXML::get_export_data(FileAccess *p_f,ExportData& r_export_data) { + + open(p_f); + ERR_FAIL_COND_V(error!=OK,error); + + + + while (true) { + bool exit; + Tag *tag = parse_tag(&exit); + + if (!tag) { + error=ERR_FILE_CORRUPT; + if (!exit) // shouldn't have exited + ERR_FAIL_V(error); + error=ERR_FILE_EOF; + return error; + } + + + bool main; + + if (tag->name=="ext_resource") { + + ExportData::Dependency dep; + + error=ERR_FILE_CORRUPT; + ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> missing 'path' field."); + ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT); + + String type="Resource"; + if (tag->args.has("type")) + type=tag->args["type"]; + + String path = tag->args["path"]; + + dep.path=path; + dep.type=type; + + + if (tag->args.has("index")) { + ExtResource er; + er.path=path; + er.type=type; + r_export_data.dependencies[tag->args["index"].to_int()]=dep; + } else { + + int index = r_export_data.dependencies.size(); + r_export_data.dependencies[index]=dep; + + } + + + + Error err = close_tag("ext_resource"); + if (err) + return error; + + continue; + + } else if (tag->name=="resource") { + + main=false; + } else if (tag->name=="main_resource") { + main=true; + } else { + ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": unexpected main tag: "+tag->name); + error=ERR_FILE_CORRUPT; + ERR_FAIL_V(error); + } + + r_export_data.resources.resize( r_export_data.resources.size()+1 ); + + ExportData::ResourceData &res_data=r_export_data.resources[ r_export_data.resources.size()-1 ]; + + + res_data.index=-1; + + if (!main) { + //loading resource + + + String path=tag->args["path"]; + + error=OK; + + if (path.begins_with("local://")) { + //built-in resource (but really external) + + path=path.replace("local://",""); + res_data.index=path.to_int(); + } + + res_data.type= tag->args["type"]; + } else { + res_data.type=resource_type; + + + } + //load properties + + while(true) { + + String name; + Variant v; + Error err; + + err = parse_property(v,name); + + if (err==ERR_FILE_EOF) //tag closed + break; + + + if (err!=OK) { + ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": XML Parsing aborted."); + ERR_FAIL_COND_V(err!=OK,ERR_FILE_CORRUPT); + } + + ExportData::PropertyData prop; + prop.name=name; + prop.value=v; + res_data.properties.push_back(prop); + + } + if (main) { + return OK; + + } + } + return OK; +} + + Error ResourceInteractiveLoaderXML::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) { open(p_f); @@ -2021,6 +2179,23 @@ void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String> } +Error ResourceFormatLoaderXML::get_export_data(const String& p_path,ExportData& r_export_data) { + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + if (!f) { + + ERR_FAIL_V(ERR_CANT_OPEN); + } + + Ref<ResourceInteractiveLoaderXML> ria = memnew( ResourceInteractiveLoaderXML ); + ria->local_path=Globals::get_singleton()->localize_path(p_path); + ria->res_path=ria->local_path; + + return ria->get_export_data(f,r_export_data); + +} + + Error ResourceFormatLoaderXML::rename_dependencies(const String &p_path,const Map<String,String>& p_map) { FileAccess *f = FileAccess::open(p_path,FileAccess::READ); @@ -2036,6 +2211,7 @@ Error ResourceFormatLoaderXML::rename_dependencies(const String &p_path,const Ma return ria->rename_dependencies(f,p_path,p_map); } +ResourceFormatLoaderXML *ResourceFormatLoaderXML::singleton=NULL; /****************************************************************************************/ /****************************************************************************************/ diff --git a/core/io/resource_format_xml.h b/core/io/resource_format_xml.h index 097c2e43f..5923817b6 100644 --- a/core/io/resource_format_xml.h +++ b/core/io/resource_format_xml.h @@ -79,7 +79,7 @@ friend class ResourceFormatLoaderXML; _FORCE_INLINE_ void unquote(String& p_str); Error goto_end_of_tag(); Error parse_property_data(String &r_data); - Error parse_property(Variant& r_v, String &r_name); + Error parse_property(Variant& r_v, String &r_name,bool p_for_export_data=false); Error error; @@ -98,6 +98,7 @@ public: void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types); Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map); + Error get_export_data(FileAccess *p_f,ExportData& r_export_data); ~ResourceInteractiveLoaderXML(); @@ -106,6 +107,7 @@ public: class ResourceFormatLoaderXML : public ResourceFormatLoader { public: + static ResourceFormatLoaderXML *singleton; virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL); virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; @@ -113,7 +115,9 @@ public: virtual String get_resource_type(const String &p_path) const; virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false); virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map); + virtual Error get_export_data(const String& p_path,ExportData& r_export_data); + ResourceFormatLoaderXML() { singleton=this; } }; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 87e5d72a1..2fa3a996c 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -399,6 +399,34 @@ void ResourceLoader::get_dependencies(const String& p_path, List<String> *p_depe } } +Error ResourceLoader::get_export_data(const String& p_path,ExportData& r_export_data) { + + + String local_path; + if (p_path.is_rel_path()) + local_path="res://"+p_path; + else + local_path = Globals::get_singleton()->localize_path(p_path); + + String remapped_path = PathRemap::get_singleton()->get_remap(local_path); + + String extension=remapped_path.extension(); + + for (int i=0;i<loader_count;i++) { + + if (!loader[i]->recognize(extension)) + continue; + //if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) + // continue; + + return loader[i]->get_export_data(p_path,r_export_data); + + } + + return ERR_UNAVAILABLE; + +} + Error ResourceLoader::rename_dependencies(const String &p_path,const Map<String,String>& p_map) { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index de54dbde6..14a7ee83d 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -30,7 +30,7 @@ #define RESOURCE_LOADER_H #include "resource.h" - +#include "export_data.h" /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -67,6 +67,7 @@ public: virtual void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false); virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const { return ERR_UNAVAILABLE; } virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map) { return OK; } + virtual Error get_export_data(const String& p_path,ExportData& r_export_data) { return ERR_UNAVAILABLE; } virtual ~ResourceFormatLoader() {} }; @@ -107,6 +108,8 @@ public: static void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false); static Error rename_dependencies(const String &p_path,const Map<String,String>& p_map); + static Error get_export_data(const String& p_path,ExportData& r_export_data); + static String guess_full_filename(const String &p_path,const String& p_type); static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load=p_timestamp; } diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index 7b60baeeb..e3ec98dd6 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -178,9 +178,9 @@ Error DirAccess::make_dir_recursive(String p_dir) { for(int i=0;i<subdirs.size();i++) { curpath=curpath.plus_file(subdirs[i]); + Error err = make_dir(curpath); if (err != OK && err != ERR_ALREADY_EXISTS) { - ERR_FAIL_V(err); } } diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 6b7532ebf..910e809ff 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -907,32 +907,25 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in if (p_res_parser && id=="Resource" && p_res_parser->func){ - RES res; - Error err = p_res_parser->func(p_res_parser->userdata,p_stream,res,line,r_err_str); + Error err = p_res_parser->func(p_res_parser->userdata,p_stream,value,line,r_err_str); if (err) return err; - value=res; - return OK; } else if (p_res_parser && id=="ExtResource" && p_res_parser->ext_func){ - RES res; - Error err = p_res_parser->ext_func(p_res_parser->userdata,p_stream,res,line,r_err_str); + Error err = p_res_parser->ext_func(p_res_parser->userdata,p_stream,value,line,r_err_str); if (err) return err; - value=res; return OK; } else if (p_res_parser && id=="SubResource" && p_res_parser->sub_func){ - RES res; - Error err = p_res_parser->sub_func(p_res_parser->userdata,p_stream,res,line,r_err_str); + Error err = p_res_parser->sub_func(p_res_parser->userdata,p_stream,value,line,r_err_str); if (err) return err; - value=res; return OK; } else { diff --git a/core/variant_parser.h b/core/variant_parser.h index c69673b0e..d1fdb37d9 100644 --- a/core/variant_parser.h +++ b/core/variant_parser.h @@ -73,7 +73,7 @@ public: }; - typedef Error (*ParseResourceFunc)(void* p_self, Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str); + typedef Error (*ParseResourceFunc)(void* p_self, Stream* p_stream,Variant& r_res,int &line,String &r_err_str); struct ResourceParser { diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index abb66ff42..43834d1ce 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -54,7 +54,7 @@ Ref<Resource> ResourceInteractiveLoaderText::get_resource() { return resource; } -Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str) { +Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str) { VariantParser::Token token; VariantParser::get_token(p_stream,token,line,r_err_str); @@ -74,9 +74,9 @@ Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* return ERR_PARSE_ERROR; } - r_res=RES(ResourceCache::get(path)); + r_value_res=RES(ResourceCache::get(path)); } else { - r_res=RES(); + r_value_res=RES(); } VariantParser::get_token(p_stream,token,line,r_err_str); @@ -89,7 +89,7 @@ Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* return OK; } -Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str){ +Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str){ VariantParser::Token token; VariantParser::get_token(p_stream,token,line,r_err_str); @@ -116,15 +116,43 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* } - r_res=ResourceLoader::load(path,type); + RES res = ResourceLoader::load(path,type); - if (r_res.is_null()) { + if (res.is_null()) { WARN_PRINT(String("Couldn't load external resource: "+path).utf8().get_data()); } + + r_value_res=res; } else { - r_res=RES(); + r_value_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_sub_resource_export(VariantParser::Stream* p_stream,Variant& r_value_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; + + r_value_res="@RESLOCAL:"+itos(index); + VariantParser::get_token(p_stream,token,line,r_err_str); if (token.type!=VariantParser::TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; @@ -135,6 +163,34 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* return OK; } +Error ResourceInteractiveLoaderText::_parse_ext_resource_export(VariantParser::Stream* p_stream,Variant& r_value_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; + + { + + r_value_res="@RESEXTERNAL:"+itos(id); + + } + + 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() { @@ -684,6 +740,384 @@ void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f,List<String> } } +Error ResourceInteractiveLoaderText::get_export_data(FileAccess *p_f,ExportData& r_export_data) { + + + open(p_f); + ERR_FAIL_COND_V(error!=OK,error); + + + while(true) { + + print_line("next tag is: "+next_tag.name); + + 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"]; + + + ExportData::Dependency dep; + dep.path=path; + dep.type=type; + r_export_data.dependencies[index]=dep; + + error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp_export); + + if (error) { + _printerr(); + 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"]; + + r_export_data.resources.resize( r_export_data.resources.size()+1 ); + ExportData::ResourceData &res_data=r_export_data.resources[ r_export_data.resources.size()-1 ]; + + res_data.type=type; + res_data.index=id; + + + while(true) { + + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp_export); + print_line("get prop: "+assign); + + if (error) { + _printerr(); + return error; + } + + if (assign!=String()) { + + ExportData::PropertyData pdata; + pdata.name=assign; + pdata.value=value; + res_data.properties.push_back(pdata); + + //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; + } + + + } + + } 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; + } + + + r_export_data.resources.resize( r_export_data.resources.size()+1 ); + ExportData::ResourceData &res_data=r_export_data.resources[ r_export_data.resources.size()-1 ]; + res_data.index=-1; + res_data.type=res_type; + + while(true) { + + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp_export); + + if (error) { + if (error!=ERR_FILE_EOF) { + _printerr(); + } else { + return OK; + } + return error; + } + + if (assign!=String()) { + ExportData::PropertyData pdata; + pdata.name=assign; + pdata.value=value; + res_data.properties.push_back(pdata); + //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 { + return OK; + } + + } + + 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; + } + + + r_export_data.nodes.resize( r_export_data.nodes.size()+1 ); + ExportData::NodeData &node_data=r_export_data.nodes[ r_export_data.nodes.size()-1 ]; + + + if (next_tag.fields.has("name")) { + node_data.name=next_tag.fields["name"]; + } + + if (next_tag.fields.has("parent")) { + node_data.parent=next_tag.fields["parent"]; + } + + + + if (next_tag.fields.has("type")) { + node_data.type=next_tag.fields["type"]; + } + + if (next_tag.fields.has("instance")) { + + node_data.instance = next_tag.fields["instance"]; + } + + if (next_tag.fields.has("instance_placeholder")) { + + node_data.instance_placeholder = next_tag.fields["instance_placeholder"]; + } + + if (next_tag.fields.has("owner")) { + node_data.owner=next_tag.fields["owner"]; + } + + if (next_tag.fields.has("groups")) { + + Array groups = next_tag.fields["groups"]; + for (int i=0;i<groups.size();i++) { + node_data.groups.push_back(groups[i]); + } + } + + while(true) { + + String assign; + Variant value; + + error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp_export); + + print_line("get prop: "+assign); + + if (error) { + + if (error!=ERR_FILE_EOF) { + _printerr(); + return error; + } else { + + return OK; + } + + } + + if (assign!=String()) { + + ExportData::PropertyData pdata; + pdata.name=assign; + pdata.value=value; + node_data.properties.push_back(pdata); + //it's assignment + } else if (next_tag.name!=String()) { + print_line("found something else?"); + break; //something else + } else { + print_line("done i guess?"); + //all done? + 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"]; + } + + ExportData::Connection conn; + conn.from=from; + conn.to=to; + conn.method=method; + conn.signal=signal; + conn.binds=binds; + conn.flags=flags; + + r_export_data.connections.push_back(conn); + + error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp_export); + + if (error) { + if (error!=ERR_FILE_EOF) { + _printerr(); + return error; + } else { + return OK; + } + } + + continue; + + } 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"]; + + r_export_data.editables.push_back(path); + + error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp_export); + + if (error) { + if (error!=ERR_FILE_EOF) { + _printerr(); + return error; + } else { + return OK; + } + } + + continue; + + } else { + + error_text+="Unknown tag in file: "+next_tag.name; + _printerr(); + error=ERR_FILE_CORRUPT; + return error; + } + } + + ERR_FAIL_V(ERR_BUG); +} + Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) { @@ -878,6 +1312,11 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f,bool p_skip_first_tag) rp.func=NULL; rp.userdata=this; + rp_export.ext_func=_parse_ext_resources_export; + rp_export.sub_func=_parse_sub_resources_export; + rp_export.func=NULL; + rp_export.userdata=this; + } @@ -1024,6 +1463,30 @@ void ResourceFormatLoaderText::get_dependencies(const String& p_path,List<String } +ResourceFormatLoaderText* ResourceFormatLoaderText::singleton=NULL; + +Error ResourceFormatLoaderText::get_export_data(const String& p_path,ExportData& r_export_data) { + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + if (!f) { + + ERR_FAIL_V(ERR_CANT_OPEN); + } + + Ref<ResourceInteractiveLoaderText> 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) ); + Error err = ria->get_export_data(f,r_export_data); + if (err!=OK) { + ERR_PRINTS("ERROR: "+ria->error_text); + } + + return err; +} + + + Error ResourceFormatLoaderText::rename_dependencies(const String &p_path,const Map<String,String>& p_map) { FileAccess *f = FileAccess::open(p_path,FileAccess::READ); diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index 58660fa63..fdd7215f3 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -73,14 +73,22 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { Map<String,String> remaps; //void _printerr(); - static Error _parse_sub_resources(void* p_self, VariantParser::Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText*>(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<Resource>& r_res,int &line,String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText*>(p_self)->_parse_ext_resource(p_stream,r_res,line,r_err_str); } + static Error _parse_sub_resources(void* p_self, VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText*>(p_self)->_parse_sub_resource(p_stream,r_value_res,line,r_err_str); } + static Error _parse_ext_resources(void* p_self, VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText*>(p_self)->_parse_ext_resource(p_stream,r_value_res,line,r_err_str); } - Error _parse_sub_resource(VariantParser::Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str); - Error _parse_ext_resource(VariantParser::Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str); + Error _parse_sub_resource(VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str); + Error _parse_ext_resource(VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str); VariantParser::ResourceParser rp; + static Error _parse_sub_resources_export(void* p_self, VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText*>(p_self)->_parse_sub_resource_export(p_stream,r_value_res,line,r_err_str); } + static Error _parse_ext_resources_export(void* p_self, VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText*>(p_self)->_parse_ext_resource_export(p_stream,r_value_res,line,r_err_str); } + + Error _parse_sub_resource_export(VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str); + Error _parse_ext_resource_export(VariantParser::Stream* p_stream,Variant& r_value_res,int &line,String &r_err_str); + + VariantParser::ResourceParser rp_export; + Ref<PackedScene> packed_scene; @@ -104,6 +112,7 @@ public: String recognize(FileAccess *p_f); void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types); Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map); + Error get_export_data(FileAccess *p_f,ExportData& r_export_data); ~ResourceInteractiveLoaderText(); @@ -122,8 +131,10 @@ public: virtual String get_resource_type(const String &p_path) const; virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false); virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map); + virtual Error get_export_data(const String& p_path,ExportData& r_export_data); - + static ResourceFormatLoaderText* singleton; + ResourceFormatLoaderText() { singleton=this;} }; diff --git a/tools/editor/editor_export_godot3.cpp b/tools/editor/editor_export_godot3.cpp new file mode 100644 index 000000000..7ca48497f --- /dev/null +++ b/tools/editor/editor_export_godot3.cpp @@ -0,0 +1,1358 @@ +#include "editor_export_godot3.h" +#include "editor_node.h" +#include "io/resource_format_xml.h" +#include "io/resource_format_binary.h" +#include "scene/resources/scene_format_text.h" + +static const char* prop_renames[][2]={ +{"script/script","script"}, +{"pause/pause_mode","pause_mode"}, +{"anchor/left","anchor_left"}, +{"anchor/right","anchor_right"}, +{"anchor/bottom","anchor_bottom"}, +{"anchor/top","anchor_top"}, +{"focus_neighbour/left","focus_neighbour_left"}, +{"focus_neighbour/right","focus_neighbour_right"}, +{"focus_neighbour/bottom","focus_neighbour_bottom"}, +{"focus_neighbour/top","focus_neighbour_top"}, +{"focus/ignore_mouse","focus_ignore_mouse"}, +{"focus/stop_mouse","focus_stop_mouse"}, +{"size_flags/horizontal","size_flags_horizontal"}, +{"size_flags/vertical","size_flags_vertical"}, +{"size_flags/stretch_ratio","size_flags_stretch_ratio"}, +{"theme/theme","theme"}, +{"visibility/visible","visible"}, +{"visibility/behind_parent","show_behind_parent"}, +{"visibility/on_top","show_on_top"}, +{"visibility/light_mask","light_mask"}, +{"material/material","material"}, +{"material/use_parent","use_parent_material"}, +{"resource/path","resource_path"}, +{"resource/name","resource_name"}, +{"collision/layers","collision_layers"}, +{"collision/mask","collision_mask"}, +{"limit/left","limit_left"}, +{"limit/right","limit_right"}, +{"limit/bottom","limit_bottom"}, +{"limit/top","limit_top"}, +{"limit/smoothed","limit_smoothed"}, +{"draw_margin/h_enabled","draw_margin_h_enabled"}, +{"draw_margin/v_enabled","draw_margin_v_enabled"}, +{"smoothing/enable","smoothing_enabled"}, +{"smoothing/speed","smoothing_speed"}, +{"drag_margin/left","drag_margin_left"}, +{"drag_margin/top","drag_margin_top"}, +{"drag_margin/right","drag_margin_right"}, +{"drag_margin/bottom","drag_margin_bottom"}, +{"input/pickable","input_pickable"}, +{"bias/bias","bias"}, +{"collision/exclude_nodes","disable_collision"}, +{"range/height","range_height"}, +{"range/z_min","range_z_min"}, +{"range/z_max","range_z_max"}, +{"range/layer_max","range_layer_max"}, +{"range/item_cull_mask","range_item_cull_max"}, +{"shadow/enabled","shadow_enabled"}, +{"shadow/color","shadow_color"}, +{"shadow/buffer_size","shadow_buffer_size"}, +{"shadow/gradient_length","shadow_gradient_length"}, +{"shadow/filter","shadow_filter"}, +{"shadow/item_cull_mask","shadow_item_cull_mask"}, +{"transform/pos","position"}, +{"transform/rot","rotation"}, +{"transform/scale","scale"}, +{"z/z","z"}, +{"z/relative","z_as_relative"}, +{"scroll/offset","scroll_offset"}, +{"scroll/base_offset","scroll_base_offset"}, +{"scroll/base_scale","scroll_base_scale"}, +{"scroll/limit_begin","scroll_limit_begin"}, +{"scroll/limit_end","scroll_limit_end"}, +{"scroll/ignore_camera_zoom","scroll_ignore_camera_zoom"}, +{"motion/scale","motion_scale"}, +{"motion/offset","motion_offset"}, +{"motion/mirroring","motion_mirroring"}, +{"collision/layers","collision_layer"}, +{"collision/mask","collision_mask"}, +{"texture/texture","texture"}, +{"texture/offset","texture_offset"}, +{"texture/rotation","texture_rotation"}, +{"texture/scale","texture_scale"}, +{"invert/enable","invert_enable"}, +{"invert/border","invert_border"}, +{"config/polyphony","polyphony"}, +{"config/samples","samples"}, +{"config/pitch_random","random_pitch"}, +{"params/volume_db","volume_db"}, +{"params/pitch_scale","pitch_scale"}, +{"params/attenuation/min_distance","attenuation_min_distance"}, +{"params/attenuation/max_distance","attenuation_max_distance"}, +{"params/attenuation/distance_exp","attenuation_distance_exp"}, +{"cell/size","cell_size"}, +{"cell/quadrant_size","cell_quadrant_size"}, +{"cell/half_offset","cell_half_offset"}, +{"cell/tile_origin","cell_tile_origin"}, +{"cell/y_sort","cell_y_sort"}, +{"collision/use_kinematic","collision_use_kinematic"}, +{"collision/friction","collision_friction"}, +{"collision/bounce","collision_bounce"}, +{"collision/layers","collision_layers"}, +{"collision/mask","collision_mask"}, +{"occluder/light_mask","occluder_light_mask"}, +{"enabler/pause_animations","pause_animations"}, +{"enabler/freeze_bodies","freeze_bodies"}, +{"enabler/pause_particles","pause_particles"}, +{"enabler/pause_animated_sprites","pause_animated_sprites"}, +{"enabler/process_parent","process_parent"}, +{"enabler/fixed_process_parent","fixed_process_parent"}, +{"sort/enabled","sort_enabled"}, +{"collision/layers","collision_layers"}, +{"collision/mask","collision_mask"}, +{"input/ray_pickable","input_ray_pickable"}, +{"input/capture_on_drag","input_capture_on_drag"}, +{"light/color","light_color"}, +{"light/energy","light_energy"}, +{"light/negative","light_negative"}, +{"light/specular","light_specular"}, +{"light/cull_mask","light_cull_mask"}, +{"shadow/enabled","shadow_enabled"}, +{"shadow/color","shadow_color"}, +{"shadow/bias","shadow_bias"}, +{"shadow/max_distance","shadow_max_distance"}, +{"editor/editor_only","editor_only"}, +{"directional_shadow/mode","directional_shadow_mode"}, +{"directional_shadow/split_1","directional_shadow_split_1"}, +{"directional_shadow/split_2","directional_shadow_split_2"}, +{"directional_shadow/split_3","directional_shadow_split_3"}, +{"directional_shadow/blend_splits","directional_shadow_blend_splits"}, +{"directional_shadow/normal_bias","directional_shadow_normal_bias"}, +{"directional_shadow/bias_split_scale","directional_shadow_bias_split_scale"}, +{"omni/range","omni_range"}, +{"omni/attenuation","omni_attenuation"}, +{"omni/shadow_mode","omni_shadow_mode"}, +{"omni/shadow_detail","omni_shadow_detail"}, +{"spot/range","spot_range"}, +{"spot/attenuation","spot_attenuation"}, +{"spot/angle","spot_angle"}, +{"spot/spot_attenuation","spot_angle_attenuation"}, +{"mesh/mesh","mesh"}, +{"mesh/skeleton","skeleton"}, +{"collision/layers","collision_layer"}, +{"collision/mask","collision_mask"}, +{"quad/axis","axis"}, +{"quad/size","size"}, +{"quad/offset","offset"}, +{"quad/centered","centered"}, +{"transform/local","transform"}, +{"transform/transiation","translation"}, +{"transform/rotation","rotation"}, +{"transform/scale","scale"}, +{"visibility/visible","visible"}, +{"params/volume_db","volume_db"}, +{"params/pitch_scale","pitch_scale"}, +{"params/attenuation/min_distance","attenuation_min_distance"}, +{"params/attenuation/max_distance","attenuation_max_distance"}, +{"params/attenuation/distance_exp","attenuation_distance_exp"}, +{"params/emission_cone/degrees","emission_cone_degrees"}, +{"params/emission_cone/attenuation_db","emission_cone_attenuation_db"}, +{"config/polyphony","polyphony"}, +{"config/samples","samples"}, +{"flags/transparent","transparent"}, +{"flags/shaded","shaded"}, +{"flags/alpha_cut","alpha_cut"}, +{"type/traction","use_as_traction"}, +{"type/steering","use_as_steering"}, +{"wheel/radius","wheel_radius"}, +{"wheel/rest_length","wheel_rest_length"}, +{"wheel/friction_slip","wheel_friction_sleep"}, +{"suspension/travel","suspension_travel"}, +{"suspension/stiffness","suspension_stiffness"}, +{"suspension/max_force","suspension_max_force"}, +{"damping/compression","damping_compression"}, +{"damping/relaxation","damping_relaxation"}, +{"motion/engine_force","engine_force"}, +{"motion/breake","breake"}, +{"motion/steering","steering"}, +{"body/mass","mass"}, +{"body/friction","friction"}, +{"enabler/pause_animations","pause_animations"}, +{"enabler/freeze_bodies","freeze_bodies"}, +{"geometry/material_override","material_override"}, +{"geometry/cast_shadow","cast_shadow"}, +{"geometry/extra_cull_margin","extra_cull_margin"}, +{"geometry/billboard","use_as_billboard"}, +{"geometry/billboard_y","use_as_y_billboard"}, +{"geometry/depth_scale","use_depth_scale"}, +{"geometry/visible_in_all_rooms","visible_in_all_rooms"}, +{"geometry/use_baked_light","use_in_baked_light"}, +{"playback/process_mode","playback_process_mode"}, +{"playback/default_blend_time","playback_default_blend_time"}, +{"root/root","root_node"}, +{"playback/process_mode","playback_process_mode"}, +{"stream/stream","stream"}, +{"stream/play","play"}, +{"stream/loop","loop"}, +{"stream/volume_db","volume_db"}, +{"stream/pitch_scale","pitch_scale"}, +{"stream/tempo_scale","tempo_scale"}, +{"stream/autoplay","autoplay"}, +{"stream/paused","paused"}, +{"stream/stream","stream"}, +{"stream/play","play"}, +{"stream/loop","loop"}, +{"stream/volume_db","volume_db"}, +{"stream/autoplay","autoplay"}, +{"stream/paused","paused"}, +{"stream/loop_restart_time","loop_restart_time"}, +{"stream/buffering_ms","buffering_ms"}, +{"stream/stream","stream"}, +{"stream/play","play"}, +{"stream/loop","loop"}, +{"stream/volume_db","volume_db"}, +{"stream/autoplay","autoplay"}, +{"stream/paused","paused"}, +{"stream/loop_restart_time","loop_restart_time"}, +{"stream/buffering_ms","buffering_ms"}, +{"window/title","window_title"}, +{"dialog/text","dialog_text"}, +{"dialog/hide_on_ok","dialog_hide_on_ok"}, +{"placeholder/text","placeholder_text"}, +{"placeholder/alpha","placeholder_alpha"}, +{"caret/caret_blink","caret_blink"}, +{"caret/caret_blink_speed","caret_blink_speed"}, +{"patch_margin/left","patch_margin_left"}, +{"patch_margin/right","patch_margin_right"}, +{"patch_margin/top","patch_margin_top"}, +{"patch_margin/bottom","patch_margin_bottom"}, +{"popup/exclusive","popup_exclusive"}, +{"percent/visible","percent_visible"}, +{"range/min","min_value"}, +{"range/max","max_value"}, +{"range/step","step"}, +{"range/page","page"}, +{"range/value","value"}, +{"range/exp_edit","exp_edit"}, +{"range/rounded","rounded"}, +{"velocity/linear","linear_velocity"}, +{"velocity/angular","angular_velocity"}, +{"damp_override_linear","linear_damp"}, +{"damp_override_angular","angular_damp"}, +{"velocity/linear","linear_velocity"}, +{"velocity/angular","angular_velocity"}, +{"damp_override_linear","linear_damp"}, +{"damp_override_angular","angular_damp"}, +{"playback/process_mode","playback_process_mode"}, +{"bbcode/enabled","bbcode_enabled"}, +{"bbcode/bbcode","bbcode_text"}, +{"scroll/horizontal","scroll_horizontal"}, +{"scroll/vertical","scroll_vertical"}, +{"split/offset","split_offset"}, +{"split/collapsed","collapsed"}, +{"split/dragger_visibility","dragger_visibility"}, +{"caret/block_caret","caret_block_mode"}, +{"caret/caret_blink","caret_blink"}, +{"caret/caret_blink_speed","caret_blink_speed"}, +{"textures/normal","texture_normal"}, +{"textures/pressed","texture_pressed"}, +{"textures/hover","texture_hover"}, +{"textures/disabled","texture_disabled"}, +{"textures/focused","texture_focused"}, +{"textures/click_mask","texture_click_mask"}, +{"params/scale","texture_scale"}, +{"params/modulate","self_modulate"}, +{"texture/under","texture_under"}, +{"texture/over","texture_over"}, +{"texture/progress","texture_progress"}, +{"mode","fill_mode"}, +{"radial_fill/initial_angle","radial_initial_angle"}, +{"radial_fill/fill_degrees","radial_fill_degrees"}, +{"radial_fill/center_offset","radial_center_offset"}, +{"stream/audio_track","audio_track"}, +{"stream/stream","stream"}, +{"stream/volume_db","volume_db"}, +{"stream/autoplay","stream_autoplay"}, +{"stream/paused","stream_paused"}, +{"font/size","size"}, +{"extra_spacing/top","extra_spacing_top"}, +{"extra_spacing/bottom","extra_spacing_bottom"}, +{"extra_spacing/char","extra_spacing_char"}, +{"extra_spacing/space","extra_spacing_space"}, +{"font/use_mipmaps","use_mipmaps"}, +{"font/use_filter","use_filter"}, +{"font/font","font_data"}, +{"content_margin/left","content_margin_left"}, +{"content_margin/right","content_margin_right"}, +{"content_margin/bottom","content_margin_bottom"}, +{"content_margin/top","content_margin_top"}, +{"margin/left","margin_left"}, +{"margin/top","margin_top"}, +{"margin/bottom","margin_bottom"}, +{"margin/right","margin_right"}, +{"expand_margin/left","expand_margin_left"}, +{"expand_margin/top","expand_margin_top"}, +{"expand_margin/bottom","expand_margin_bottom"}, +{"expand_margin/right","expand_margin_right"}, +{"modulate/color","modulate_color"}, +{"modulate","self_modulate"}, +{NULL,NULL} +}; + + + +static const char* type_renames[][2]={ +{"SpatialPlayer","Spatial"}, +{"SpatialSamplePlayer","Spatial"}, +{"SpatialStreamPlayer","Spatial"}, +{"SamplePlayer","Node"}, +{"SamplePlayer2D","Node2D"}, +{"SoundPlayer2D","Node2D"}, +{"StreamPlayer2D","Node2D"}, +{"SampleLibrary","Resource"}, +{"TextureFrame","TextureRect"}, +{NULL,NULL} +}; + + +static const char* signal_renames[][2]={ +{"area_enter","area_entered"}, +{"area_exit","area_exited"}, +{"area_enter_shape","area_shape_entered"}, +{"area_exit_shape","area_shape_exited"}, +{"body_enter","body_entered"}, +{"body_exit","body_exited"}, +{"body_enter_shape","body_shape_entered"}, +{"body_exit_shape","body_shape_exited"}, +{"mouse_enter","mouse_entered"}, +{"mouse_exit","mouse_exited"}, +{"focus_enter","focus_entered"}, +{"focus_exit","focus_exited"}, +{"modal_close","modal_closed"}, +{"enter_tree","tree_entered"}, +{"exit_tree","tree_exited"}, +{NULL,NULL} +}; + + + + +void EditorExportGodot3::_find_files(EditorFileSystemDirectory *p_dir,List<String> * r_files) { + + for(int i=0;i<p_dir->get_subdir_count();i++) { + _find_files(p_dir->get_subdir(i),r_files); + } + + for(int i=0;i<p_dir->get_file_count();i++) { + + r_files->push_back(p_dir->get_file_path(i)); + } +} + + +void EditorExportGodot3::_rename_properties(const String& p_type,List<ExportData::PropertyData> *p_props) { + + + for (List<ExportData::PropertyData>::Element *E=p_props->front();E;E=E->next()) { + + if (prop_rename_map.has(E->get().name)) { + E->get().name=prop_rename_map[E->get().name]; + } + } +} + +void EditorExportGodot3::_convert_resources(ExportData &resource) { + + + for(int i=0;i<resource.resources.size();i++) { + + _rename_properties(resource.resources[i].type,&resource.resources[i].properties); + + if (type_rename_map.has(resource.resources[i].type)) { + resource.resources[i].type=type_rename_map[resource.resources[i].type]; + } + + } + + for(int i=0;i<resource.nodes.size();i++) { + + _rename_properties(resource.nodes[i].type,&resource.nodes[i].properties); + + if (type_rename_map.has(resource.nodes[i].type)) { + resource.nodes[i].type=type_rename_map[resource.nodes[i].type]; + } + + } + + for(int i=0;i<resource.connections.size();i++) { + + if (signal_rename_map.has(resource.connections[i].signal)) { + resource.connections[i].signal=signal_rename_map[resource.connections[i].signal]; + } + } + +} + +void EditorExportGodot3::_unpack_packed_scene(ExportData &resource) { + + + Dictionary d; + for (List<ExportData::PropertyData>::Element *E=resource.resources[resource.resources.size()-1].properties.front();E;E=E->next()) { + if (E->get().name=="_bundled") { + d=E->get().value; + } + } + + ERR_FAIL_COND(d.empty()); + + ERR_FAIL_COND( !d.has("names")); + ERR_FAIL_COND( !d.has("variants")); + ERR_FAIL_COND( !d.has("node_count")); + ERR_FAIL_COND( !d.has("nodes")); + ERR_FAIL_COND( !d.has("conn_count")); + ERR_FAIL_COND( !d.has("conns")); + + + Vector<String> names; + + DVector<String> snames = d["names"]; + if (snames.size()) { + + int namecount = snames.size(); + names.resize(namecount); + DVector<String>::Read r =snames.read(); + for(int i=0;i<names.size();i++) + names[i]=r[i]; + } + + Array variants = d["variants"]; + + resource.nodes.resize(d["node_count"]); + + int nc=resource.nodes.size(); + if (nc) { + DVector<int> snodes = d["nodes"]; + DVector<int>::Read r = snodes.read(); + int idx=0; + for(int i=0;i<nc;i++) { + + int parent = r[idx++]; + int owner = r[idx++]; + int type = r[idx++]; + int name = r[idx++]; + int instance = r[idx++]; + + ExportData::NodeData node_data; + + node_data.text_data=false; + node_data.name=names[name]; + node_data.type=names[type]; + node_data.parent_int=parent; + node_data.owner_int=owner; + if (instance>=0) { + node_data.instance_is_placeholder=instance&SceneState::FLAG_INSTANCE_IS_PLACEHOLDER; + node_data.instance=variants[instance&SceneState::FLAG_MASK]; + } + + int prop_count = r[idx++]; + + for(int j=0;j<prop_count;j++) { + + int prop_name = r[idx++]; + int prop_value = r[idx++]; + + ExportData::PropertyData pdata; + pdata.name=names[prop_name]; + pdata.value=variants[prop_value]; + node_data.properties.push_back(pdata); + + } + + int group_count = r[idx++]; + for(int j=0;j<group_count;j++) { + + int group_name = r[idx++]; + node_data.groups.push_back(names[group_name]); + } + + resource.nodes.push_back(node_data); + } + + } + + int cc=d["conn_count"]; + + if (cc) { + + DVector<int> sconns = d["conns"]; + DVector<int>::Read r = sconns.read(); + int idx=0; + for(int i=0;i<cc;i++) { + + ExportData::Connection conn; + + conn.from_int=r[idx++]; + conn.to_int=r[idx++]; + conn.signal=names[r[idx++]]; + conn.method=names[r[idx++]]; + conn.flags=r[idx++]; + int bindcount = r[idx++]; + + for(int j=0;j<bindcount;j++) { + + conn.binds.push_back(variants[r[idx++]]); + } + + resource.connections.push_back(conn); + } + + } + + Array np; + if (d.has("node_paths")) { + np=d["node_paths"]; + } + + for(int i=0;i<np.size();i++) { + resource.node_paths.push_back(np[i]); + } + + Array ei; + if (d.has("editable_instances")) { + ei=d["editable_instances"]; + for(int i=0;i<ei.size();i++) { + resource.editables.push_back(ei[i]); + } + } + + if (d.has("base_scene")) { + resource.base_scene=variants[d["base_scene"]]; + } + + resource.resources.resize( resource.resources.size() -1 ); //erase packed +} + + + +void EditorExportGodot3::_pack_packed_scene(ExportData &resource) { + + pack_names.clear(); + pack_values.clear(); + + Dictionary d; + + d["node_count"]=resource.nodes.size(); + + Vector<int> node_data; + + for(int i=0;i<resource.nodes.size();i++) { + + const ExportData::NodeData &node = resource.nodes[i]; + + node_data.push_back(node.parent_int); + node_data.push_back(node.owner_int); + node_data.push_back(_pack_name(node.type)); + node_data.push_back(_pack_name(node.name)); + int instance=-1; + if (node.instance!=String()) { + instance=_pack_value(node.instance); + if (node.instance_is_placeholder) { + instance|=SceneState::FLAG_INSTANCE_IS_PLACEHOLDER; + } + } + node_data.push_back(instance); + + + node_data.push_back(node.properties.size()); + + for(int j=0;j<node.properties.size();j++) { + node_data.push_back(_pack_name(node.properties[j].name)); + node_data.push_back(_pack_value(node.properties[j].value)); + } + + node_data.push_back(node.groups.size()); + + for(int j=0;j<node.groups.size();j++) { + + node_data.push_back(_pack_name(node.groups[j])); + } + + } + + d["nodes"]=node_data; + + d["conn_count"]=resource.connections.size(); + + Vector<int> connections; + + for(int i=0;i<resource.connections.size();i++) { + const ExportData::Connection &conn=resource.connections[i]; + + connections.push_back(conn.from_int); + connections.push_back(conn.to_int); + connections.push_back(_pack_name(conn.signal)); + connections.push_back(_pack_name(conn.method)); + connections.push_back(conn.flags); + connections.push_back(conn.binds.size()); + for(int j=0;j<conn.binds.size();j++) { + connections.push_back(_pack_value(conn.binds[j])); + } + } + + d["connections"]=connections; + + Array np; + for(int i=0;i<resource.node_paths.size();i++) { + np.push_back(resource.node_paths[i]); + } + + d["node_paths"]=np; + + Array ei; + for(int i=0;i<resource.editables.size();i++) { + ei.push_back(resource.editables[i]); + } + + d["editable_instances"]=ei; + + if (resource.base_scene.get_type()) { + + d["base_scene"]=_pack_value(resource.base_scene); + } + + + DVector<String> names; + names.resize(pack_names.size()); + { + DVector<String>::Write w=names.write(); + for(Map<String,int>::Element *E=pack_names.front();E;E=E->next()) { + w[E->get()]=E->key(); + } + } + + d["names"]=names; + + Array values; + + const Variant*K=NULL; + while((K=pack_values.next(K))) { + + values[pack_values[*K]]=*K; + } + + d["variants"]=values; + + ExportData::ResourceData packed_scene; + packed_scene.type="PackedScene"; + packed_scene.index=-1; + ExportData::PropertyData pd; + pd.name="_bundled"; + pd.value=d; + packed_scene.properties.push_back(pd); + + resource.resources.push_back(packed_scene); + resource.nodes.clear(); + resource.connections.clear(); + resource.editables.clear(); + resource.node_paths.clear();; + resource.base_scene=Variant(); + + +} + +static String rtosfix(double p_value) { + + + if (p_value==0.0) + return "0"; //avoid negative zero (-0) being written, which may annoy git, svn, etc. for changes when they don't exist. + else + return rtoss(p_value); +} + +Error EditorExportGodot3::_get_property_as_text(const Variant& p_variant,String&p_string) { + + switch( p_variant.get_type() ) { + + case Variant::NIL: { + p_string+=("null"); + } break; + case Variant::BOOL: { + + p_string+=(p_variant.operator bool() ? "true":"false" ); + } break; + case Variant::INT: { + + p_string+=( itos(p_variant.operator int()) ); + } break; + case Variant::REAL: { + + String s = rtosfix(p_variant.operator real_t()); + if (s.find(".")==-1 && s.find("e")==-1) + s+=".0"; + p_string+=( s ); + } break; + case Variant::STRING: { + + String str=p_variant; + if (str.begins_with("@RESLOCAL:")) { + p_string+="SubResource("+str.get_slice(":",1)+")"; + } else if (str.begins_with("@RESEXTERNAL:")) { + p_string+="ExtResource("+str.get_slice(":",1)+")"; + } else { + + str="\""+str.c_escape_multiline()+"\""; + p_string+=( str ); + } + + } break; + case Variant::VECTOR2: { + + Vector2 v = p_variant; + p_string+=("Vector2( "+rtosfix(v.x) +", "+rtosfix(v.y)+" )" ); + } break; + case Variant::RECT2: { + + Rect2 aabb = p_variant; + p_string+=("Rect2( "+rtosfix(aabb.pos.x) +", "+rtosfix(aabb.pos.y) +", "+rtosfix(aabb.size.x) +", "+rtosfix(aabb.size.y)+" )" ); + + } break; + case Variant::VECTOR3: { + + Vector3 v = p_variant; + p_string+=("Vector3( "+rtosfix(v.x) +", "+rtosfix(v.y)+", "+rtosfix(v.z)+" )"); + } break; + case Variant::PLANE: { + + Plane p = p_variant; + p_string+=("Plane( "+rtosfix(p.normal.x) +", "+rtosfix(p.normal.y)+", "+rtosfix(p.normal.z)+", "+rtosfix(p.d)+" )" ); + + } break; + case Variant::_AABB: { + + Rect3 aabb = p_variant; + p_string+=("Rect3( "+rtosfix(aabb.pos.x) +", "+rtosfix(aabb.pos.y) +", "+rtosfix(aabb.pos.z) +", "+rtosfix(aabb.size.x) +", "+rtosfix(aabb.size.y) +", "+rtosfix(aabb.size.z)+" )" ); + + } break; + case Variant::QUAT: { + + Quat quat = p_variant; + p_string+=("Quat( "+rtosfix(quat.x)+", "+rtosfix(quat.y)+", "+rtosfix(quat.z)+", "+rtosfix(quat.w)+" )"); + + } break; + case Variant::MATRIX32: { + + String s="Transform2D( "; + Matrix32 m3 = p_variant; + for (int i=0;i<3;i++) { + for (int j=0;j<2;j++) { + + if (i!=0 || j!=0) + s+=", "; + s+=rtosfix( m3.elements[i][j] ); + } + } + + p_string+=(s+" )"); + + } break; + case Variant::MATRIX3: { + + String s="Basis( "; + Matrix3 m3 = p_variant; + for (int i=0;i<3;i++) { + for (int j=0;j<3;j++) { + + if (i!=0 || j!=0) + s+=", "; + s+=rtosfix( m3.elements[i][j] ); + } + } + + p_string+=(s+" )"); + + } break; + case Variant::TRANSFORM: { + + String s="Transform( "; + Transform t = p_variant; + Matrix3 &m3 = t.basis; + for (int i=0;i<3;i++) { + for (int j=0;j<3;j++) { + + if (i!=0 || j!=0) + s+=", "; + s+=rtosfix( m3.elements[i][j] ); + } + } + + s=s+", "+rtosfix(t.origin.x) +", "+rtosfix(t.origin.y)+", "+rtosfix(t.origin.z); + + p_string+=(s+" )"); + } break; + + // misc types + case Variant::COLOR: { + + Color c = p_variant; + p_string+=("Color( "+rtosfix(c.r) +", "+rtosfix(c.g)+", "+rtosfix(c.b)+", "+rtosfix(c.a)+" )"); + + } break; + case Variant::IMAGE: { + + + Image img=p_variant; + + if (img.empty()) { + p_string+=("Image()"); + break; + } + + String imgstr="Image()"; + p_string+=imgstr; //do not convert this for now + + /*imgstr+=itos(img.get_width()); + imgstr+=", "+itos(img.get_height()); + imgstr+=", "+String(img.get_mipmaps()?"true":"false"); + imgstr+=", "+Image::get_format_name(img.get_format()); + + String s; + + PoolVector<uint8_t> data = img.get_data(); + int len = data.size(); + PoolVector<uint8_t>::Read r = data.read(); + const uint8_t *ptr=r.ptr(); + for (int i=0;i<len;i++) { + + if (i>0) + s+=", "; + s+=itos(ptr[i]); + } + + imgstr+=", "; + p_string+=(imgstr); + p_string+=(s); + p_string+=(" )");*/ + } break; + case Variant::NODE_PATH: { + + String str=p_variant; + + str="NodePath(\""+str.c_escape()+"\")"; + p_string+=(str); + + } break; + + case Variant::OBJECT: { + + //should never arrive here! + ERR_FAIL_V(ERR_BUG); + } break; + case Variant::INPUT_EVENT: { + + String str="InputEvent("; + + InputEvent ev=p_variant; + switch(ev.type) { + case InputEvent::KEY: { + + str+="KEY,"+itos(ev.key.scancode); + String mod; + if (ev.key.mod.alt) + mod+="A"; + if (ev.key.mod.shift) + mod+="S"; + if (ev.key.mod.control) + mod+="C"; + if (ev.key.mod.meta) + mod+="M"; + + if (mod!=String()) + str+=","+mod; + } break; + case InputEvent::MOUSE_BUTTON: { + + str+="MBUTTON,"+itos(ev.mouse_button.button_index); + } break; + case InputEvent::JOYSTICK_BUTTON: { + str+="JBUTTON,"+itos(ev.joy_button.button_index); + + } break; + case InputEvent::JOYSTICK_MOTION: { + str+="JAXIS,"+itos(ev.joy_motion.axis)+","+itos(ev.joy_motion.axis_value); + } break; + case InputEvent::NONE: { + str+="NONE"; + } break; + default: {} + } + + str+=")"; + + p_string+=(str); //will be added later + + } break; + case Variant::DICTIONARY: { + + Dictionary dict = p_variant; + + List<Variant> keys; + dict.get_key_list(&keys); + keys.sort(); + + p_string+=("{\n"); + for(List<Variant>::Element *E=keys.front();E;E=E->next()) { + + /* + if (!_check_type(dict[E->get()])) + continue; + */ + _get_property_as_text(E->get(),p_string); + p_string+=(": "); + _get_property_as_text(dict[E->get()],p_string); + if (E->next()) + p_string+=(",\n"); + } + + + p_string+=("\n}"); + + + } break; + case Variant::ARRAY: { + + p_string+=("[ "); + Array array = p_variant; + int len=array.size(); + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + _get_property_as_text(array[i],p_string); + + } + p_string+=(" ]"); + + } break; + + case Variant::RAW_ARRAY: { + + p_string+=("PoolByteArray( "); + String s; + DVector<uint8_t> data = p_variant; + int len = data.size(); + DVector<uint8_t>::Read r = data.read(); + const uint8_t *ptr=r.ptr(); + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + + p_string+=(itos(ptr[i])); + + } + + p_string+=(" )"); + + } break; + case Variant::INT_ARRAY: { + + p_string+=("PoolIntArray( "); + DVector<int> data = p_variant; + int len = data.size(); + DVector<int>::Read r = data.read(); + const int *ptr=r.ptr(); + + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + + p_string+=(itos(ptr[i])); + } + + + p_string+=(" )"); + + } break; + case Variant::REAL_ARRAY: { + + p_string+=("PoolFloatArray( "); + DVector<real_t> data = p_variant; + int len = data.size(); + DVector<real_t>::Read r = data.read(); + const real_t *ptr=r.ptr(); + + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + p_string+=(rtosfix(ptr[i])); + } + + p_string+=(" )"); + + } break; + case Variant::STRING_ARRAY: { + + p_string+=("PoolStringArray( "); + DVector<String> data = p_variant; + int len = data.size(); + DVector<String>::Read r = data.read(); + const String *ptr=r.ptr(); + String s; + //write_string("\n"); + + + + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + String str=ptr[i]; + p_string+=("\""+str.c_escape()+"\""); + } + + p_string+=(" )"); + + } break; + case Variant::VECTOR2_ARRAY: { + + p_string+=("PoolVector2Array( "); + DVector<Vector2> data = p_variant; + int len = data.size(); + DVector<Vector2>::Read r = data.read(); + const Vector2 *ptr=r.ptr(); + + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + p_string+=(rtosfix(ptr[i].x)+", "+rtosfix(ptr[i].y) ); + } + + p_string+=(" )"); + + } break; + case Variant::VECTOR3_ARRAY: { + + p_string+=("PoolVector3Array( "); + DVector<Vector3> data = p_variant; + int len = data.size(); + DVector<Vector3>::Read r = data.read(); + const Vector3 *ptr=r.ptr(); + + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + p_string+=(rtosfix(ptr[i].x)+", "+rtosfix(ptr[i].y)+", "+rtosfix(ptr[i].z) ); + } + + p_string+=(" )"); + + } break; + case Variant::COLOR_ARRAY: { + + p_string+=("PoolColorArray( "); + + DVector<Color> data = p_variant; + int len = data.size(); + DVector<Color>::Read r = data.read(); + const Color *ptr=r.ptr(); + + for (int i=0;i<len;i++) { + + if (i>0) + p_string+=(", "); + + p_string+=(rtosfix(ptr[i].r)+", "+rtosfix(ptr[i].g)+", "+rtosfix(ptr[i].b)+", "+rtosfix(ptr[i].a) ); + + } + p_string+=(" )"); + + } break; + default: {} + + } + + return OK; +} + +void EditorExportGodot3::_save_text(const String& p_path,ExportData &resource) { + + FileAccessRef f = FileAccess::open(p_path,FileAccess::WRITE); + + if (resource.nodes.size()) { + f->store_line("[gd_scene load_steps="+itos(resource.nodes.size()+resource.resources.size())+" format=2]\n"); + } else { + f->store_line("[gd_resource type=\""+resource.resources[resource.resources.size()-1].type+"\" load_steps="+itos(resource.resources.size())+" format=2]\n"); + } + + for (Map<int,ExportData::Dependency>::Element *E=resource.dependencies.front();E;E=E->next()) { + + f->store_line("[ext_resource type=\""+E->get().type+"\" path=\""+E->get().path+"\" id="+itos(E->key())+"]\n"); + + } + + for (int i=0;i<resource.resources.size();i++) { + + if (resource.nodes.size() || i<resource.resources.size()-1) { + + f->store_line("\n[sub_resource type=\""+resource.resources[i].type+"\" id="+itos(resource.resources[i].index)+"]\n"); + } else { + f->store_line("\n[resource]\n"); + } + + for( List<ExportData::PropertyData>::Element *E=resource.resources[i].properties.front();E;E=E->next() ) { + + String prop; + _get_property_as_text(E->get().value,prop); + f->store_line(E->get().name+"="+prop); + + } + + + } + + for (int i=0;i<resource.nodes.size();i++) { + + String node_txt = "\n[node "; + + if (resource.nodes[i].name!=String()) { + node_txt+=" name=\""+String(resource.nodes[i].name).c_escape()+"\""; + } + + if (resource.nodes[i].parent!=NodePath()) { + node_txt+=" parent=\""+String(resource.nodes[i].parent).c_escape()+"\""; + } + + if (resource.nodes[i].owner!=NodePath()) { + node_txt+=" owner=\""+String(resource.nodes[i].owner).c_escape()+"\""; + } + + if (resource.nodes[i].type!=String()) { + node_txt+=" type=\""+resource.nodes[i].type+"\""; + } + + if (resource.nodes[i].instance!=String()) { + String prop; + _get_property_as_text(resource.nodes[i].instance,prop); + node_txt+=" instance="+prop+""; + } + + node_txt+="]\n"; + f->store_line(node_txt); + + + for( List<ExportData::PropertyData>::Element *E=resource.nodes[i].properties.front();E;E=E->next() ) { + + String prop; + _get_property_as_text(E->get().value,prop); + f->store_line(E->get().name+"="+prop); + } + + + } + + for(int i=0;i<resource.connections.size();i++) { + + String prop; + _get_property_as_text(resource.connections[i].binds,prop); + + f->store_line("\n[connection signal=\""+resource.connections[i].signal+"\" from=\""+String(resource.connections[i].from).c_escape()+"\" to=\""+String(resource.connections[i].to).c_escape()+"\" method=\""+resource.connections[i].method+"\" binds="+prop+"]"); + + } + + for(int i=0;i<resource.editables.size();i++) { + + f->store_line("[editable path=\""+String(resource.editables[i]).c_escape()+"\"]"); + } + +} + +void EditorExportGodot3::_save_binary(const String& p_path,ExportData &resource) { + + + +} + +void EditorExportGodot3::_save_config(const String &p_path) { + + FileAccessRef f = FileAccess::open(p_path.plus_file("godot.cfg"),FileAccess::WRITE); + + f->store_line("[application]\n"); + String name = Globals::get_singleton()->get("application/name"); + f->store_line("name=\""+name.c_escape()+"\""); + String main_scene = Globals::get_singleton()->get("application/main_scene"); + f->store_line("main_scene=\""+_replace_resource(main_scene).c_escape()+"\""); + + +} + +Error EditorExportGodot3::export_godot3(const String& p_path) { + + List<String> files; + _find_files(EditorFileSystem::get_singleton()->get_filesystem(),&files); + + EditorProgress progress("exporting","Exporting Godot 3.0",files.size()); + + //find XML resources + + resource_replace_map.clear(); + + Set<String> xml_extensions; + Set<String> binary_extensions; + Set<String> text_extensions; + + { + List<String> xml_exts; + ResourceFormatLoaderXML::singleton->get_recognized_extensions(&xml_exts); + for (List<String>::Element *E=xml_exts.front();E;E=E->next()) { + xml_extensions.insert(E->get()); + } + } + + { + List<String> binary_exts; + ResourceFormatLoaderBinary::singleton->get_recognized_extensions(&binary_exts); + for (List<String>::Element *E=binary_exts.front();E;E=E->next()) { + binary_extensions.insert(E->get()); + } + } + + { + List<String> text_exts; + ResourceFormatLoaderText::singleton->get_recognized_extensions(&text_exts); + for (List<String>::Element *E=text_exts.front();E;E=E->next()) { + text_extensions.insert(E->get()); + } + } + + for(List<String>::Element *E=files.front();E;E=E->next()) { + + String file=E->get(); + if (xml_extensions.has(file.extension().to_lower())) { + if (ResourceLoader::get_resource_type(file)=="PackedScene") { + resource_replace_map[file]=file.basename()+".tscn"; + } else { + resource_replace_map[file]=file.basename()+".tres"; + } + } + } + + DirAccess *directory = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + + if (directory->change_dir(p_path)!=OK) { + memdelete(directory); + ERR_FAIL_V(ERR_CANT_OPEN); + } + + + int idx=0; + for(List<String>::Element *E=files.front();E;E=E->next()) { + + String path = E->get(); + String extension = path.extension().to_lower(); + + String target_path; + bool repack=false; + + target_path = p_path.plus_file(path.replace("res://","")); + + progress.step(target_path.get_file(),idx++); + + print_line("exporting: "+target_path); + + if (directory->make_dir_recursive(target_path.get_base_dir())!=OK) { + memdelete(directory); + ERR_FAIL_V(ERR_CANT_CREATE); + } + + ExportData resource_data; + + if (xml_extensions.has(extension)) { + Error err = ResourceLoader::get_export_data(path,resource_data); + if (err!=OK) { + memdelete(directory); + ERR_FAIL_V(err); + } + } else if (text_extensions.has(extension)) { + Error err = ResourceLoader::get_export_data(path,resource_data); + if (err!=OK) { + memdelete(directory); + ERR_FAIL_V(err); + } + } else if (binary_extensions.has(extension)) { + + Error err = ResourceLoader::get_export_data(path,resource_data); + if (err!=OK) { + memdelete(directory); + ERR_FAIL_V(err); + } + + } else { + //single file, copy it + Error err = directory->copy(path,target_path); + if (err!=OK) { + memdelete(directory); + ERR_FAIL_V(err); + } + continue; //no longer needed to do anything, just copied the file! + } + + if (resource_data.nodes.size()==0 && resource_data.resources[resource_data.resources.size()-1].type=="PackedScene") { + //must unpack a PackedScene + _unpack_packed_scene(resource_data); + repack=true; + } + + _convert_resources(resource_data); + + if (repack) { + + _pack_packed_scene(resource_data); + + } + + + if (xml_extensions.has(extension)) { + + String save_path=resource_replace_map[target_path]; + _save_text(save_path,resource_data); + } else if (text_extensions.has(extension)) { + _save_text(target_path,resource_data); + } else if (binary_extensions.has(extension)) { + _save_binary(target_path,resource_data); + } + + } + + memdelete(directory); + _save_config(p_path); + + return OK; +} + +EditorExportGodot3::EditorExportGodot3() { + + int idx=0; + while(prop_renames[idx][0]!=NULL) { + + prop_rename_map[prop_renames[idx][0]]=prop_renames[idx][1]; + idx++; + } + + idx=0; + + while(type_renames[idx][0]!=NULL) { + + type_rename_map[type_renames[idx][0]]=type_renames[idx][1]; + idx++; + } + + idx=0; + + while(signal_renames[idx][0]!=NULL) { + + signal_rename_map[signal_renames[idx][0]]=signal_renames[idx][1]; + idx++; + } +} diff --git a/tools/editor/editor_export_godot3.h b/tools/editor/editor_export_godot3.h new file mode 100644 index 000000000..579198a43 --- /dev/null +++ b/tools/editor/editor_export_godot3.h @@ -0,0 +1,66 @@ +#ifndef EDITOR_EXPORT_GODOT3_H +#define EDITOR_EXPORT_GODOT3_H + +#include "scene/main/node.h" +#include "tools/editor/editor_file_system.h" +#include "io/export_data.h" + +class EditorExportGodot3 { + + Map<String,int> pack_names; + HashMap<Variant,int,VariantHasher> pack_values; + + int _pack_name(const String& p_name) { + if (pack_names.has(p_name)) { + return pack_names[p_name]; + } + + int idx = pack_names.size(); + pack_names[p_name]=idx; + return idx; + } + + int _pack_value(const Variant& p_value) { + if (pack_values.has(p_value)) { + return pack_values[p_value]; + } + + int idx = pack_values.size(); + pack_values[p_value]=idx; + return idx; + } + + Map<String,String> prop_rename_map; + Map<String,String> type_rename_map; + Map<String,String> signal_rename_map; + + Map<String,String> resource_replace_map; + + String _replace_resource(const String& p_res) { + if (resource_replace_map.has(p_res)) + return resource_replace_map[p_res]; + else + return p_res; + } + + Error _get_property_as_text(const Variant& p_variant,String&p_string); + + void _save_text(const String& p_path,ExportData &resource); + void _save_binary(const String& p_path,ExportData &resource); + void _save_config(const String &p_path); + + void _rename_properties(const String& p_type,List<ExportData::PropertyData> *p_props); + void _convert_resources(ExportData &resource); + void _unpack_packed_scene(ExportData &resource); + void _pack_packed_scene(ExportData &resource); + + void _find_files(EditorFileSystemDirectory *p_dir, List<String> * r_files); +public: + + + Error export_godot3(const String& p_path); + + EditorExportGodot3(); +}; + +#endif // EDITOR_EXPORT_GODOT3_H diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 6662afb39..79455688b 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -2426,7 +2426,10 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { orphan_resources->show(); } break; + case TOOLS_EXPORT_GODOT3: { + export_godot3_dialog->popup_centered_ratio(); + } break; case EDIT_REVERT: { Node *scene = get_edited_scene(); @@ -5305,6 +5308,7 @@ void EditorNode::_bind_methods() { ObjectTypeDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box); ObjectTypeDB::bind_method("_clear_undo_history",&EditorNode::_clear_undo_history); ObjectTypeDB::bind_method("_dropped_files",&EditorNode::_dropped_files); + ObjectTypeDB::bind_method("_export_godot3_path",&EditorNode::_export_godot3_path); @@ -5325,6 +5329,15 @@ void EditorNode::_bind_methods() { } + +void EditorNode::_export_godot3_path(const String& p_path) { + + Error err = export_godot3.export_godot3(p_path); + if (err!=OK) { + show_warning("Error exporting to Godot 3.0"); + } +} + EditorNode::EditorNode() { EditorHelp::generate_doc(); //before any editor classes are crated @@ -5797,6 +5810,7 @@ EditorNode::EditorNode() { p=tool_menu->get_popup(); p->connect("item_pressed",this,"_menu_option"); p->add_item(TTR("Orphan Resource Explorer"),TOOLS_ORPHAN_RESOURCES); + p->add_item(TTR("Export to Godot 3.0"),TOOLS_EXPORT_GODOT3); export_button = memnew( ToolButton ); export_button->set_tooltip(TTR("Export the project to many platforms.")); @@ -6623,7 +6637,11 @@ EditorNode::EditorNode() { } } - + export_godot3_dialog = memnew( FileDialog ); + export_godot3_dialog->set_access(FileDialog::ACCESS_FILESYSTEM); + export_godot3_dialog->set_mode(FileDialog::MODE_OPEN_DIR); + gui_base->add_child(export_godot3_dialog); + export_godot3_dialog->connect("dir_selected",this,"_export_godot3_path"); Node::set_human_readable_collision_renaming(true); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index ca5327abf..19cca549e 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -80,6 +80,7 @@ #include "fileserver/editor_file_server.h" #include "editor_resource_preview.h" +#include "editor_export_godot3.h" #include "progress_dialog.h" @@ -146,6 +147,7 @@ private: EDIT_REDO, EDIT_REVERT, TOOLS_ORPHAN_RESOURCES, + TOOLS_EXPORT_GODOT3, RESOURCE_NEW, RESOURCE_LOAD, RESOURCE_SAVE, @@ -281,6 +283,9 @@ private: HBoxContainer *search_bar; LineEdit *search_box; + EditorExportGodot3 export_godot3; + FileDialog *export_godot3_dialog; + CreateDialog *create_dialog; CallDialog *call_dialog; @@ -573,6 +578,8 @@ private: void _update_addon_config(); + void _export_godot3_path(const String& p_path); + static void _file_access_close_error_notify(const String& p_str); protected: |
