diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 2bf9fd7f32d..fed8c287404 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -54,6 +54,10 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri p_stream->saved=0; } else { cchar=p_stream->get_char(); + if (p_stream->is_eof()) { + r_token.type=TK_EOF; + return OK; + } } switch(cchar) { @@ -202,6 +206,9 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri } } + if (p_stream->is_utf8()) { + str.parse_utf8( str.ascii(true).get_data() ); + } r_token.type=TK_STRING; r_token.value=str; return OK; @@ -215,7 +222,7 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri if (cchar=='-' || (cchar>='0' && cchar<='9')) { //a number - print_line("a numbar"); + String num; #define READING_SIGN 0 @@ -228,7 +235,6 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri if (cchar=='-') { num+='-'; cchar=p_stream->get_char(); - print_line("isnegative"); } @@ -246,14 +252,11 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri if (c>='0' && c<='9') { //pass - print_line("num: regular"); } else if (c=='.') { reading=READING_DEC; - print_line("num: decimal"); is_float=true; } else if (c=='e') { reading=READING_EXP; - print_line("num: exp"); } else { reading=READING_DONE; } @@ -262,11 +265,10 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri case READING_DEC: { if (c>='0' && c<='9') { - print_line("dec: exp"); } else if (c=='e') { reading=READING_EXP; - print_line("dec: expe"); + } else { reading=READING_DONE; } @@ -276,10 +278,10 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri if (c>='0' && c<='9') { exp_beg=true; - print_line("exp: num"); + } else if ((c=='-' || c=='+') && !exp_sign && !exp_beg) { exp_sign=true; - print_line("exp: sgn"); + } else { reading=READING_DONE; } @@ -290,13 +292,13 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri break; num+=String::chr(c); c = p_stream->get_char(); - print_line("add to c"); + } p_stream->saved=c; - print_line("num was: "+num); + r_token.type=TK_NUMBER; if (is_float) r_token.value=num.to_double(); @@ -307,11 +309,13 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri } else if ((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_') { String id; + bool first=true; - while((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_') { + while((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_' || (!first && cchar>='0' && cchar<='9')) { id+=String::chr(cchar); cchar=p_stream->get_char(); + first=false; } p_stream->saved=cchar; @@ -332,14 +336,14 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri return ERR_PARSE_ERROR; } - -Error VariantParser::_parse_construct(Stream *p_stream,Vector& r_construct,int &line,String &r_err_str) { +template +Error VariantParser::_parse_construct(Stream *p_stream,Vector& r_construct,int &line,String &r_err_str) { Token token; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_OPEN) { - r_err_str="Expected '('"; + r_err_str="Expected '(' in constructor"; return ERR_PARSE_ERROR; } @@ -351,21 +355,23 @@ Error VariantParser::_parse_construct(Stream *p_stream,Vector& r_construc get_token(p_stream,token,line,r_err_str); if (token.type==TK_COMMA) { //do none - } else if (token.type!=TK_PARENTHESIS_CLOSE) { + } else if (token.type==TK_PARENTHESIS_CLOSE) { break; } else { - r_err_str="Expected ',' or ')'"; + r_err_str="Expected ',' or ')' in constructor"; return ERR_PARSE_ERROR; } } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { - r_err_str="Expected float"; + r_err_str="Expected float in constructor"; return ERR_PARSE_ERROR; } + r_construct.push_back(token.value); + first=false; } return OK; @@ -444,7 +450,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in else if (id=="Vector2"){ Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -457,7 +463,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Vector3"){ Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -470,7 +476,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Matrix32"){ Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -486,7 +492,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Plane") { Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -499,7 +505,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Quat") { Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -513,7 +519,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="AABB"){ Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -527,7 +533,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Matrix3"){ Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -540,7 +546,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Transform"){ Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -554,7 +560,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Color") { Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -600,6 +606,8 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } int height=token.value; + + get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; @@ -612,6 +620,8 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } int mipmaps=token.value; + + get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; @@ -624,6 +634,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in return ERR_PARSE_ERROR; } + String sformat=token.value; Image::Format format; @@ -666,12 +677,13 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in DVector::Write w=buffer.write(); for(int i=0;ifunc){ + 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); @@ -778,15 +773,56 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in 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); + 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); + if (err) + return err; + + value=res; + return OK; } else { - r_err_str="Expected string as argument."; - return ERR_PARSE_ERROR; + get_token(p_stream,token,line,r_err_str); + if (token.type==TK_STRING) { + String path=token.value; + RES res = ResourceLoader::load(path); + if (res.is_null()) { + r_err_str="Can't load resource at path: '"+path+"'."; + return ERR_PARSE_ERROR; + } + + get_token(p_stream,token,line,r_err_str); + if (token.type!=TK_PARENTHESIS_CLOSE) { + r_err_str="Expected ')'"; + return ERR_PARSE_ERROR; + } + + value=res; + return OK; + + } else { + r_err_str="Expected string as argument for Resource()."; + return ERR_PARSE_ERROR; + } } return OK; + } else if (id=="InputEvent") { @@ -952,8 +988,8 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="ByteArray") { - Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Vector args; + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -973,8 +1009,8 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="IntArray") { - Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Vector args; + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -984,7 +1020,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in arr.resize(len); DVector::Write w = arr.write(); for(int i=0;i args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -1066,7 +1102,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Vector2Array") { Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -1087,7 +1123,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="Vector3Array") { Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -1108,7 +1144,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } else if (id=="ColorArray") { Vector args; - Error err = _parse_construct(p_stream,args,line,r_err_str); + Error err = _parse_construct(p_stream,args,line,r_err_str); if (err) return err; @@ -1191,7 +1227,12 @@ Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, Str bool need_comma=false; - while(!p_stream->is_eof()) { + while(true) { + + if (p_stream->is_eof()) { + r_err_str="Unexpected End of File while parsing array"; + return ERR_FILE_CORRUPT; + } Error err = get_token(p_stream,token,line,r_err_str); if (err!=OK) @@ -1236,9 +1277,14 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int bool need_comma=false; - while(!p_stream->is_eof()) { + while(true) { + if (p_stream->is_eof()) { + r_err_str="Unexpected End of File while parsing dictionary"; + return ERR_FILE_CORRUPT; + } + if (at_key) { Error err = get_token(p_stream,token,line,r_err_str); @@ -1301,7 +1347,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int } -Error VariantParser::_parse_tag(Token& token,Stream *p_stream, int &line, String &r_err_str,Tag& r_tag) { +Error VariantParser::_parse_tag(Token& token, Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser) { r_tag.fields.clear(); @@ -1321,10 +1367,13 @@ Error VariantParser::_parse_tag(Token& token,Stream *p_stream, int &line, String r_tag.name=token.value; - print_line("tag name: "+r_tag.name); - while(true) { + if (p_stream->is_eof()) { + r_err_str="Unexpected End of File while parsing tag: "+r_tag.name; + return ERR_FILE_CORRUPT; + } + get_token(p_stream,token,line,r_err_str); if (token.type==TK_BRACKET_CLOSE) break; @@ -1336,7 +1385,6 @@ Error VariantParser::_parse_tag(Token& token,Stream *p_stream, int &line, String String id=token.value; - print_line("got ID: "+id); get_token(p_stream,token,line,r_err_str); if (token.type!=TK_EQUAL) { @@ -1344,17 +1392,13 @@ Error VariantParser::_parse_tag(Token& token,Stream *p_stream, int &line, String return ERR_PARSE_ERROR; } - print_line("got tk: "+String(tk_name[token.type])); - get_token(p_stream,token,line,r_err_str); Variant value; - Error err = parse_value(token,value,p_stream,line,r_err_str); + Error err = parse_value(token,value,p_stream,line,r_err_str,p_res_parser); if (err) return err; - print_line("id: "+id+" value: "+String(value)); - - r_tag.fields[id]=value; + r_tag.fields[id]=value; } @@ -1363,23 +1407,71 @@ Error VariantParser::_parse_tag(Token& token,Stream *p_stream, int &line, String } -Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag) { +Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, ResourceParser *p_res_parser) { Token token; get_token(p_stream,token,line,r_err_str); + + if (token.type==TK_EOF) { + return ERR_FILE_EOF; + } + if (token.type!=TK_BRACKET_OPEN) { r_err_str="Expected '['"; return ERR_PARSE_ERROR; } - return _parse_tag(token,p_stream,line,r_err_str,r_tag); + return _parse_tag(token,p_stream,line,r_err_str,r_tag,p_res_parser); } -Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,String &r_assign) { +Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser) { - r_tag.name.clear(); - r_assign=String(); + + //assign.. + String what; + + while(true) { + + + CharType c; + if (p_stream->saved) { + c=p_stream->saved; + p_stream->saved=0; + + } else { + c=p_stream->get_char(); + } + + if (p_stream->is_eof()) + return ERR_FILE_EOF; + + if (c=='[' && what.length()==0) { + //it's a tag! + p_stream->saved='['; //go back one + + Error err = parse_tag(p_stream,line,r_err_str,r_tag,p_res_parser); + + return err; + } + + if (c>32) { + if (c!='=') { + what+=String::chr(c); + } else { + r_assign=what; + Token token; + get_token(p_stream,token,line,r_err_str); + Error err = parse_value(token,r_value,p_stream,line,r_err_str,p_res_parser); + if (err) { + + } + return err; + } + } else if (c=='\n') { + line++; + } + } return OK; } @@ -1391,6 +1483,11 @@ Error VariantParser::parse(Stream *p_stream, Variant& r_ret, String &r_err_str, Error err = get_token(p_stream,token,r_err_line,r_err_str); if (err) return err; + + if (token.type==TK_EOF) { + return ERR_FILE_EOF; + } + return parse_value(token,r_ret,p_stream,r_err_line,r_err_str,p_res_parser); } diff --git a/core/variant_parser.h b/core/variant_parser.h index d4ec6c6cf5f..e1d25f75122 100644 --- a/core/variant_parser.h +++ b/core/variant_parser.h @@ -38,6 +38,8 @@ public: void *userdata; ParseResourceFunc func; + ParseResourceFunc ext_func; + ParseResourceFunc sub_func; }; @@ -82,15 +84,16 @@ public: private: static const char * tk_name[TK_MAX]; - static Error _parse_construct(Stream *p_stream, Vector& r_construct, int &line, String &r_err_str); + template + static Error _parse_construct(Stream *p_stream, Vector& r_construct, int &line, String &r_err_str); static Error _parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL); static Error _parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL); - static Error _parse_tag(Token& token,Stream *p_stream, int &line, String &r_err_str,Tag& r_tag); + static Error _parse_tag(Token& token,Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL); public: - static Error parse_tag(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag); - static Error parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,String &r_assign); + static Error parse_tag(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,ResourceParser *p_res_parser=NULL); + static Error parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag& r_tag, String &r_assign, Variant &r_value,ResourceParser *p_res_parser=NULL); static Error parse_value(Token& token,Variant &value, Stream *p_stream, int &line, String &r_err_str,ResourceParser *p_res_parser=NULL); static Error get_token(Stream *p_stream,Token& r_token,int &line,String &r_err_str); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 896b4fb2fae..863f2be699c 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -1280,15 +1280,18 @@ StringName SceneState::get_node_name(int p_idx) const { Ref SceneState::get_node_instance(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,nodes.size(),Ref()); + if (nodes[p_idx].instance>=0) { return variants[nodes[p_idx].instance]; - } else if (nodes[p_idx].parent<=0 || nodes[p_idx].parent==NO_PARENT_SAVED) { + } else if (nodes[p_idx].parent<0 || nodes[p_idx].parent==NO_PARENT_SAVED) { if (base_scene_idx>=0) { return variants[base_scene_idx]; } } + + return Ref(); @@ -1438,6 +1441,84 @@ Array SceneState::get_connection_binds(int p_idx) const { Vector SceneState::get_editable_instances() const { return editable_instances; } +//add + +int SceneState::add_name(const StringName& p_name) { + + names.push_back(p_name); + return names.size()-1; +} + +int SceneState::add_value(const Variant& p_value) { + + variants.push_back(p_value); + return variants.size()-1; +} + +int SceneState::add_node_path(const NodePath& p_path){ + + node_paths.push_back(p_path); + return (node_paths.size()-1)|FLAG_ID_IS_PATH; +} +int SceneState::add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance){ + + NodeData nd; + nd.parent=p_parent; + nd.owner=p_owner; + nd.type=p_type; + nd.name=p_name; + nd.instance=p_instance; + + nodes.push_back(nd); + + return nodes.size()-1; +} +void SceneState::add_node_property(int p_node,int p_name,int p_value){ + + ERR_FAIL_INDEX(p_node,nodes.size()); + ERR_FAIL_INDEX(p_name,names.size()); + ERR_FAIL_INDEX(p_value,variants.size()); + + NodeData::Property prop; + prop.name=p_name; + prop.value=p_value; + nodes[p_node].properties.push_back(prop); +} +void SceneState::add_node_group(int p_node,int p_group){ + + ERR_FAIL_INDEX(p_node,nodes.size()); + ERR_FAIL_INDEX(p_group,names.size()); + nodes[p_node].groups.push_back(p_group); + +} +void SceneState::set_base_scene(int p_idx){ + + ERR_FAIL_INDEX(p_idx,variants.size()); + base_scene_idx=p_idx; +} +void SceneState::add_connection(int p_from,int p_to, int p_signal, int p_method, int p_flags,const Vector& p_binds){ + + ERR_FAIL_INDEX(p_signal,names.size()); + ERR_FAIL_INDEX(p_method,names.size()); + + for(int i=0;i get_editable_instances() const; + //build API + + 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); + + SceneState(); }; diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index 4fc3ece758c..5f41dc2ce8f 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -9,6 +9,8 @@ #include "version.h" #include "os/dir_access.h" +#define _printerr() ERR_PRINT(String(res_path+":"+itos(lines)+" - Parse Error: "+error_text).utf8().get_data()); + Error ResourceInteractiveLoaderText::parse_property(Variant& r_v, String &r_name) { @@ -29,299 +31,113 @@ Ref ResourceInteractiveLoaderText::get_resource() { return resource; } -Error ResourceInteractiveLoaderText::poll() { -#if 0 - if (error!=OK) - return error; +Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str) { - 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; + 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; } - RES res; - //Object *obj=NULL; + int index = token.value; - bool main; + String path = local_path+"::"+itos(index); - if (tag->name=="ext_resource") { + if (!ResourceCache::has(path)) { + r_err_str="Can't load cached sub-resource: "+path; + return ERR_PARSE_ERROR; + } - error=ERR_FILE_CORRUPT; - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": missing 'path' field."); - ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT); + r_res=RES(ResourceCache::get(path)); - String type="Resource"; - if (tag->args.has("type")) - type=tag->args["type"]; - - String path = tag->args["path"]; - - - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": can't use a local path, this is a bug?."); - ERR_FAIL_COND_V(path.begins_with("local://"),ERR_FILE_CORRUPT); - - 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()) { - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": referenced nonexistent resource at: "+path); - ERR_FAIL_V(error); - } else { - ResourceLoader::notify_dependency_error(local_path,path,type); - } - } else { - - resource_cache.push_back(res); - } - - if (tag->args.has("index")) { - ExtResource er; - er.path=path; - er.type=type; - ext_resources[tag->args["index"].to_int()]=er; - } - - - Error err = close_tag("ext_resource"); - if (err) - return error; - - - error=OK; - resource_current++; - return error; - - } 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); + 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; } - String type; - String path; - int subres=0; - - if (!main) { - //loading resource - - error=ERR_FILE_CORRUPT; - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": missing 'len' field."); - ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT); - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": missing 'type' field."); - ERR_FAIL_COND_V(!tag->args.has("type"),ERR_FILE_CORRUPT); - path=tag->args["path"]; - - error=OK; - - if (path.begins_with("local://")) { - //built-in resource (but really external) - - path=path.replace("local://",""); - subres=path.to_int(); - path=local_path+"::"+path; - } - - - if (ResourceCache::has(path)) { - Error err = close_tag(tag->name); - if (err) { - error=ERR_FILE_CORRUPT; - } - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Unable to close tag."); - ERR_FAIL_COND_V( err, err ); - resource_current++; - error=OK; - return OK; - } - - type = tag->args["type"]; - } else { - type=resource_type; - } - - Object *obj = ObjectTypeDB::instance(type); - if (!obj) { - error=ERR_FILE_CORRUPT; - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Object of unrecognized type in file: "+type); - } - ERR_FAIL_COND_V(!obj,ERR_FILE_CORRUPT); - - Resource *r = obj->cast_to(); - if (!r) { - error=ERR_FILE_CORRUPT; - memdelete(obj); //bye - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Object type in resource field not a resource, type is: "+obj->get_type()); - ERR_FAIL_COND_V(!r,ERR_FILE_CORRUPT); - } - - res = RES( r ); - if (path!="") - r->set_path(path); - r->set_subindex(subres); - - //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())+": Text Parsing aborted."); - ERR_FAIL_COND_V(err!=OK,ERR_FILE_CORRUPT); - } - - obj->set(name,v); - } -#ifdef TOOLS_ENABLED - res->set_edited(false); -#endif - resource_cache.push_back(res); //keep it in mem until finished loading - resource_current++; - if (main) { - f->close(); - resource=res; - resource->set_path(res_path); - error=ERR_FILE_EOF; - return error; - - } - error=OK; -#endif return OK; } -int ResourceInteractiveLoaderText::get_stage() const { +Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* p_stream,Ref& r_res,int &line,String &r_err_str){ - 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) { - -#if 0 - open(f); - ERR_FAIL_COND(error!=OK); - - while(true) { - bool exit; - Tag *tag = parse_tag(&exit); - - - if (!tag) { - error=ERR_FILE_CORRUPT; - ERR_FAIL_COND(!exit); - error=ERR_FILE_EOF; - return; - } - - if (tag->name!="ext_resource") { - - return; - } - - error=ERR_FILE_CORRUPT; - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": missing 'path' field."); - ERR_FAIL_COND(!tag->args.has("path")); - - String path = tag->args["path"]; - - ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": can't use a local path, this is a bug?."); - ERR_FAIL_COND(path.begins_with("local://")); - - 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 (path.ends_with("*")) { - ERR_FAIL_COND(!tag->args.has("type")); - String type = tag->args["type"]; - path = ResourceLoader::guess_full_filename(path,type); - } - - if (p_add_types && tag->args.has("type")) { - path+="::"+tag->args["type"]; - } - - p_dependencies->push_back(path); - - Error err = close_tag("ext_resource"); - if (err) - return; - - error=OK; + 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; } -#endif + + int id = token.value; + + + 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()) { + r_err_str="Couldn't load external resource: "+path; + return ERR_PARSE_ERROR; + } + + 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::rename_dependencies(FileAccess *p_f, const String &p_path,const Map& p_map) { +Error ResourceInteractiveLoaderText::poll() { + if (error!=OK) + return error; if (next_tag.name=="ext_resource") { - Error err; if (!next_tag.fields.has("path")) { - err=ERR_FILE_CORRUPT; + error=ERR_FILE_CORRUPT; error_text="Missing 'path' in external resource tag"; _printerr(); - return err; + return error; } if (!next_tag.fields.has("type")) { - err=ERR_FILE_CORRUPT; + error=ERR_FILE_CORRUPT; error_text="Missing 'type' in external resource tag"; _printerr(); - return err; + return error; } - if (!next_tag.fields.has("index")) { - err=ERR_FILE_CORRUPT; - error_text="Missing 'index' in external resource tag"; + if (!next_tag.fields.has("id")) { + error=ERR_FILE_CORRUPT; + error_text="Missing 'id' in external resource tag"; _printerr(); - return err; + return error; } String path=next_tag.fields["path"]; String type=next_tag.fields["type"]; - int index=next_tag.fields["index"]; + int index=next_tag.fields["id"]; if (path.find("://")==-1 && path.is_rel_path()) { @@ -355,19 +171,450 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const er.type=type; ext_resources[index]=er; - err = VariantParser::parse_tag(&stream,lines,error_text,next_tag); + error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); - if (err) { - error_text="Unexpected end of file"; + 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"]; + + 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); + + } + + 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); + + 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(); + } + 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("owner")) { + owner=packed_scene->get_state()->add_node_path(next_tag.fields["owner"]); + } else { + if (parent!=-1) + owner=0; //if no owner, owner is root + } + + + if (next_tag.fields.has("type")) { + type=packed_scene->get_state()->add_name(next_tag.fields["type"]); + } + + 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; + } + } + + int node_id = packed_scene->get_state()->add_node(parent,owner,type,name,instance); + + + 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; + } + 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=9;iget_state()->add_value( bind_ints[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); + 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) { + 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) { + + + #if 0 open(p_f); @@ -562,10 +809,11 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f) { } } - print_line("TAG NAME: "+tag.name); 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"; @@ -593,7 +841,7 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f) { } - err = VariantParser::parse_tag(&stream,lines,error_text,next_tag); + err = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp); if (err) { error_text="Unexpected end of file"; @@ -601,12 +849,14 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f) { error=ERR_FILE_CORRUPT; } + rp.ext_func=_parse_ext_resources; + rp.sub_func=_parse_sub_resources; + rp.func=NULL; + rp.userdata=this; + } -void ResourceInteractiveLoaderText::_printerr() { - ERR_PRINT(String(res_path+":"+itos(lines)+" - Parse Error: "+error_text).utf8().get_data()); -} String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { @@ -707,6 +957,8 @@ 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.. @@ -978,7 +1230,7 @@ void ResourceFormatSaverTextInstance::write_property(const String& p_name,const if (external_resources.has(res)) { - f->store_string("Resource( "+itos(external_resources[res]+1)+" )"); + f->store_string("ExtResource( "+itos(external_resources[res]+1)+" )"); } else { if (internal_resources.has(res)) { @@ -1434,6 +1686,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re Ref instance = state->get_node_instance(i); Vector groups = state->get_node_groups(i); + if (instance.is_valid()) + print_line("for path "+String(path)+" instance "+instance->get_path()); + String header="[node"; header+=" name=\""+String(name)+"\""; if (type!=StringName()) { @@ -1451,7 +1706,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re for(int j=0;j0) sgroups+=", "; - sgroups+="\""+groups[i].operator String().c_escape()+"\""; + sgroups+="\""+groups[j].operator String().c_escape()+"\""; } sgroups+=" ]"; header+=sgroups; diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index 16260835f88..4f18af2b628 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -43,7 +43,19 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { mutable int lines; Map remaps; - void _printerr(); + //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; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 01e53ead18b..9d4cb2c8a2e 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -3543,13 +3543,14 @@ Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps,bo if (p_set_inherited) { Ref state = sdata->get_state(); - state->set_path(lpath); + state->set_path(lpath); new_scene->set_scene_inherited_state(state); new_scene->set_filename(String()); - if (new_scene->get_scene_instance_state().is_valid()) - new_scene->get_scene_instance_state()->set_path(String()); + //if (new_scene->get_scene_instance_state().is_valid()) + // new_scene->get_scene_instance_state()->set_path(String()); } + new_scene->set_scene_instance_state(Ref()); set_edited_scene(new_scene); _get_scene_metadata();