Prechádzať zdrojové kódy

-Fixed bug with scene inheritance, should work again
-Proper .tscn and .tres parsing, should work, please test well!

Juan Linietsky 9 rokov pred
rodič
commit
7aa39b7cae

+ 170 - 73
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<float>& r_construct,int &line,String &r_err_str) {
+template<class T>
+Error VariantParser::_parse_construct(Stream *p_stream,Vector<T>& 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<float>& 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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<uint8_t>::Write w=buffer.write();
 
 				for(int i=0;i<len;i++) {
-
+					get_token(p_stream,token,line,r_err_str);
 					if (token.type!=TK_COMMA) {
 						r_err_str="Expected ','";
 						return ERR_PARSE_ERROR;
 					}
 
+					get_token(p_stream,token,line,r_err_str);
 					if (token.type!=TK_NUMBER) {
 						r_err_str="Expected number";
 						return ERR_PARSE_ERROR;
@@ -702,7 +714,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
 
 			get_token(p_stream,token,line,r_err_str);
 			if (token.type!=TK_STRING) {
-				r_err_str="Expected string as argument";
+				r_err_str="Expected string as argument for NodePath()";
 				return ERR_PARSE_ERROR;
 			}
 
@@ -741,7 +753,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
 
 			return OK;
 
-		} else if (id=="Resource") {
+		} else if (id=="Resource" || id=="SubResource" || id=="ExtResource") {
 
 
 
@@ -751,28 +763,31 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
 				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;
-				}
+			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);
+				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);
+				if (err)
+					return err;
+
+				value=res;
 
-			} else if (p_res_parser && p_res_parser->func){
+				return OK;
+			} else if (p_res_parser && id=="SubResource" && p_res_parser->sub_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->sub_func(p_res_parser->userdata,p_stream,res,line,r_err_str);
 				if (err)
 					return err;
 
@@ -781,12 +796,33 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
 				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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Vector<uint8_t> args;
+			Error err = _parse_construct<uint8_t>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Vector<int32_t> args;
+			Error err = _parse_construct<int32_t>(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<int32_t>::Write w = arr.write();
 				for(int i=0;i<len;i++) {
-					w[i]=Math::fast_ftoi(args[i]);
+					w[i]=int(args[i]);
 				}
 			}
 
@@ -995,7 +1031,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
 		} else if (id=="FloatArray") {
 
 			Vector<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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<float> args;
-			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			Error err = _parse_construct<float>(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,8 +1277,13 @@ 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) {
 
@@ -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);
 
 }

+ 7 - 4
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<float>& r_construct, int &line, String &r_err_str);
+	template<class T>
+	static Error _parse_construct(Stream *p_stream, Vector<T>& 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);

+ 82 - 1
scene/resources/packed_scene.cpp

@@ -1280,15 +1280,18 @@ StringName SceneState::get_node_name(int p_idx) const {
 
 Ref<PackedScene> SceneState::get_node_instance(int p_idx) const {
 	ERR_FAIL_INDEX_V(p_idx,nodes.size(),Ref<PackedScene>());
+
 	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<PackedScene>();
 
 
@@ -1438,6 +1441,84 @@ Array SceneState::get_connection_binds(int p_idx) const {
 Vector<NodePath> 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<int>& p_binds){
+
+	ERR_FAIL_INDEX(p_signal,names.size());
+	ERR_FAIL_INDEX(p_method,names.size());
+
+	for(int i=0;i<p_binds.size();i++) {
+		ERR_FAIL_INDEX(p_binds[i],variants.size());
+	}
+	ConnectionData c;
+	c.from=p_from;
+	c.to=p_to;
+	c.signal=p_signal;
+	c.method=p_method;
+	c.flags=p_flags;
+	c.binds=p_binds;
+	connections.push_back(c);
+
+}
+void SceneState::add_editable_instance(const NodePath& p_path){
+
+	editable_instances.push_back(p_path);
+}
+
 
 
 SceneState::SceneState() {

+ 14 - 1
scene/resources/packed_scene.h

@@ -126,7 +126,7 @@ public:
 	Node *instance(bool p_gen_edit_state=false) const;
 
 
-	//build-unbuild API
+	//unbuild API
 
 	int get_node_count() const;
 	StringName get_node_type(int p_idx) const;
@@ -150,6 +150,19 @@ public:
 
 	Vector<NodePath> 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<int>& p_binds);
+	void add_editable_instance(const NodePath& p_path);
+
+
 	SceneState();
 };
 

+ 466 - 211
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,44 +31,114 @@ Ref<Resource> 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<Resource>& r_res,int &line,String &r_err_str) {
 
-	bool exit;
-	Tag *tag = parse_tag(&exit);
+	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;
 
-	if (!tag) {
-		error=ERR_FILE_CORRUPT;
-		if (!exit) // shouldn't have exited
-			ERR_FAIL_V(error);
-		error=ERR_FILE_EOF;
-		return error;
+	String path = local_path+"::"+itos(index);
+
+	if (!ResourceCache::has(path)) {
+		r_err_str="Can't load cached sub-resource: "+path;
+		return ERR_PARSE_ERROR;
 	}
 
-	RES res;
-	//Object *obj=NULL;
+	r_res=RES(ResourceCache::get(path));
 
-	bool main;
+	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;
+	}
 
-	if (tag->name=="ext_resource") {
 
-		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);
+	return OK;
+}
+
+Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str){
+
+	VariantParser::Token token;
+	VariantParser::get_token(p_stream,token,line,r_err_str);
+	if (token.type!=VariantParser::TK_NUMBER) {
+		r_err_str="Expected number (sub-resource index)";
+		return ERR_PARSE_ERROR;
+	}
+
+	int id = token.value;
+
+
+	if (!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::poll() {
+
+	if (error!=OK)
+		return error;
+
+	if (next_tag.name=="ext_resource") {
+
+
+		if (!next_tag.fields.has("path")) {
+			error=ERR_FILE_CORRUPT;
+			error_text="Missing 'path' in external resource tag";
+			_printerr();
+			return error;
+		}
 
-		String type="Resource";
-		if (tag->args.has("type"))
-			type=tag->args["type"];
+		if (!next_tag.fields.has("type")) {
+			error=ERR_FILE_CORRUPT;
+			error_text="Missing 'type' in external resource tag";
+			_printerr();
+			return error;
+		}
 
-		String path = tag->args["path"];
+		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"];
 
-		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> 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
@@ -82,8 +154,10 @@ Error ResourceInteractiveLoaderText::poll() {
 		if (res.is_null()) {
 
 			if (ResourceLoader::get_abort_on_missing_resources()) {
-				ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> referenced nonexistent resource at: "+path);
-				ERR_FAIL_V(error);
+				error=ERR_FILE_CORRUPT;
+				error_text="[ext_resource] referenced nonexistent resource at: "+path;
+				_printerr();
+				return error;
 			} else {
 				ResourceLoader::notify_dependency_error(local_path,path,type);
 			}
@@ -92,236 +166,425 @@ Error ResourceInteractiveLoaderText::poll() {
 			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;
+		ExtResource er;
+		er.path=path;
+		er.type=type;
+		ext_resources[index]=er;
+
+		error = VariantParser::parse_tag(&stream,lines,error_text,next_tag,&rp);
+
+		if (error) {
+			_printerr();
 		}
 
+		return error;
+
+
+	} else if (next_tag.name=="sub_resource") {
+
 
-		Error err = close_tag("ext_resource");
-		if (err)
+		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;
+		}
 
-		error=OK;
-		resource_current++;
-		return error;
+		String type=next_tag.fields["type"];
+		int id=next_tag.fields["id"];
 
-	} else if (tag->name=="resource") {
+		String path = local_path+"::"+itos(id);
 
-		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);
-	}
 
+		//bool exists=ResourceCache::has(path);
 
-	String type;
-	String path;
-	int subres=0;
+		Ref<Resource> res;
 
-	if (!main) {
-		//loading resource
+		if ( !ResourceCache::has(path)) { //only if it doesn't exist
 
-		error=ERR_FILE_CORRUPT;
-		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <resource> missing 'len' field.");
-		ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT);
-		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <resource> missing 'type' field.");
-		ERR_FAIL_COND_V(!tag->args.has("type"),ERR_FILE_CORRUPT);
-		path=tag->args["path"];
+			Object *obj = ObjectTypeDB::instance(type);
+			if (!obj) {
+
+				error_text+="Can't create sub resource of type: "+type;
+				_printerr();
+				error=ERR_FILE_CORRUPT;
+				return error;
+			}
 
-		error=OK;
 
-		if (path.begins_with("local://")) {
-			//built-in resource (but really external)
+			Resource *r = obj->cast_to<Resource>();
+			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<Resource>(r);
+			resource_cache.push_back(res);
+			res->set_path(path);
 
-			path=path.replace("local://","");
-			subres=path.to_int();
-			path=local_path+"::"+path;
 		}
 
+		while(true) {
+
+			String assign;
+			Variant value;
+
+			error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp);
 
-		if (ResourceCache::has(path)) {
-			Error err = close_tag(tag->name);
-			if (err) {
+			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;
 			}
-			ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Unable to close <resource> tag.");
-			ERR_FAIL_COND_V( err, err );
-			resource_current++;
-			error=OK;
-			return OK;
+
+
 		}
 
-		type = tag->args["type"];
-	} else {
-		type=resource_type;
-	}
+		return OK;
 
-	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);
+	} else if (next_tag.name=="resource") {
 
-	Resource *r = obj->cast_to<Resource>();
-	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);
-	}
+		if (is_scene) {
 
-	res = RES( r );
-	if (path!="")
-		r->set_path(path);
-	r->set_subindex(subres);
+			error_text+="found the 'resource' tag on a scene file!";
+			_printerr();
+			error=ERR_FILE_CORRUPT;
+			return error;
+		}
 
-	//load properties
+		Object *obj = ObjectTypeDB::instance(res_type);
+		if (!obj) {
 
-	while(true) {
+			error_text+="Can't create sub resource of type: "+res_type;
+			_printerr();
+			error=ERR_FILE_CORRUPT;
+			return error;
+		}
 
-		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);
+
+		Resource *r = obj->cast_to<Resource>();
+		if (!r) {
+
+			error_text+="Can't create sub resource of type, because not a resource: "+res_type;
+			_printerr();
+			error=ERR_FILE_CORRUPT;
+			return error;
 		}
 
-		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;
+		resource=Ref<Resource>(r);
 
-	}
-	error=OK;
-#endif
-	return OK;
-}
+		while(true) {
 
-int ResourceInteractiveLoaderText::get_stage() const {
+			String assign;
+			Variant value;
 
-	return resource_current;
-}
-int ResourceInteractiveLoaderText::get_stage_count() const {
+			error = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,&rp);
 
-	return resources_total;//+ext_resources;
-}
+			if (error) {
+				if (error!=ERR_FILE_EOF) {
+					_printerr();
+				}
+				return error;
+			}
 
-ResourceInteractiveLoaderText::~ResourceInteractiveLoaderText() {
+			if (assign!=String()) {
+				resource->set(assign,value);
+				//it's assignment
+			} else if (next_tag.name!=String()) {
 
-	memdelete(f);
-}
+				error=ERR_FILE_CORRUPT;
+				error_text="Extra tag found when parsing main resource file";
+				_printerr();
+				return error;
+			} else {
+				error=ERR_FILE_EOF;
+				return error;
+			}
 
-void ResourceInteractiveLoaderText::get_dependencies(FileAccess *f,List<String> *p_dependencies,bool p_add_types) {
+		}
 
-#if 0
-	open(f);
-	ERR_FAIL_COND(error!=OK);
+		return OK;
 
-	while(true) {
-		bool exit;
-		Tag *tag = parse_tag(&exit);
+	} else if (next_tag.name=="node") {
 
+		if (!is_scene) {
 
-		if (!tag) {
+			error_text+="found the 'node' tag on a resource file!";
+			_printerr();
 			error=ERR_FILE_CORRUPT;
-			ERR_FAIL_COND(!exit);
-			error=ERR_FILE_EOF;
-			return;
+			return error;
 		}
 
-		if (tag->name!="ext_resource") {
+		/*
+		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<int>& 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"]);
+		}
 
-			return;
+		if (next_tag.fields.has("parent")) {
+			parent=packed_scene->get_state()->add_node_path(next_tag.fields["parent"]);
 		}
 
-		error=ERR_FILE_CORRUPT;
-		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> missing 'path' field.");
-		ERR_FAIL_COND(!tag->args.has("path"));
+		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
+		}
 
-		String path = tag->args["path"];
 
-		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> can't use a local path, this is a bug?.");
-		ERR_FAIL_COND(path.begins_with("local://"));
+		if (next_tag.fields.has("type")) {
+			type=packed_scene->get_state()->add_name(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 (next_tag.fields.has("instance")) {
+
+			instance=packed_scene->get_state()->add_value(next_tag.fields["instance"]);
+
+			if (packed_scene->get_state()->get_node_count()==0 && parent==-1) {
+				packed_scene->get_state()->set_base_scene(instance);
+				instance=-1;
+			}
 		}
 
-		if (path.ends_with("*")) {
-			ERR_FAIL_COND(!tag->args.has("type"));
-			String type = tag->args["type"];
-			path = ResourceLoader::guess_full_filename(path,type);
+		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;
+			}
+
 		}
 
-		if (p_add_types && tag->args.has("type")) {
-			path+="::"+tag->args["type"];
+		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;
 		}
 
-		p_dependencies->push_back(path);
+		if (!next_tag.fields.has("from")) {
+			error=ERR_FILE_CORRUPT;
+			error_text="missing 'from' field fron connection tag";
+			return error;
+		}
 
-		Error err = close_tag("ext_resource");
-		if (err)
-			return;
+		if (!next_tag.fields.has("to")) {
+			error=ERR_FILE_CORRUPT;
+			error_text="missing 'to' field fron connection tag";
+			return error;
+		}
 
-		error=OK;
-	}
-#endif
-}
+		if (!next_tag.fields.has("signal")) {
+			error=ERR_FILE_CORRUPT;
+			error_text="missing 'signal' field fron connection tag";
+			return error;
+		}
 
-Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) {
+		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.name=="ext_resource") {
+		if (next_tag.fields.has("binds")) {
+			binds=next_tag.fields["binds"];
+		}
 
-		Error err;
+		Vector<int> bind_ints;
+		for(int i=9;i<binds.size();i++) {
+			bind_ints.push_back( packed_scene->get_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")) {
-			err=ERR_FILE_CORRUPT;
-			error_text="Missing 'path' in external resource tag";
+			error=ERR_FILE_CORRUPT;
+			error_text="missing 'path' field fron connection tag";
 			_printerr();
-			return err;
+			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<String> *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")) {
-			err=ERR_FILE_CORRUPT;
+			error=ERR_FILE_CORRUPT;
 			error_text="Missing 'type' in external resource tag";
 			_printerr();
-			return err;
+			return;
 		}
 
-		if (!next_tag.fields.has("index")) {
-			err=ERR_FILE_CORRUPT;
+		if (!next_tag.fields.has("id")) {
+			error=ERR_FILE_CORRUPT;
 			error_text="Missing 'index' in external resource tag";
 			_printerr();
-			return err;
+			return;
 		}
 
 		String path=next_tag.fields["path"];
 		String type=next_tag.fields["type"];
-		int index=next_tag.fields["index"];
 
 
 		if (path.find("://")==-1 && path.is_rel_path()) {
@@ -329,45 +592,29 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const
 			path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
 		}
 
-		if (remaps.has(path)) {
-			path=remaps[path];
-		}
-
-		RES res = ResourceLoader::load(path,type);
-
-		if (res.is_null()) {
-
-			if (ResourceLoader::get_abort_on_missing_resources()) {
-				error=ERR_FILE_CORRUPT;
-				error_text="[ext_resource] referenced nonexistent resource at: "+path;
-				_printerr();
-				return error;
-			} else {
-				ResourceLoader::notify_dependency_error(local_path,path,type);
-			}
-		} else {
 
-			resource_cache.push_back(res);
+		if (p_add_types) {
+			path+="::"+type;
 		}
 
-		ExtResource er;
-		er.path=path;
-		er.type=type;
-		ext_resources[index]=er;
+		p_dependencies->push_back(path);
 
-		err = VariantParser::parse_tag(&stream,lines,error_text,next_tag);
+		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;
-			return error;
 		}
 
-		return OK;
-
 
 	}
+}
+
+Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& 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<PackedScene> instance = state->get_node_instance(i);
 			Vector<StringName> 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;j<groups.size();j++) {
 					if (j>0)
 						sgroups+=", ";
-					sgroups+="\""+groups[i].operator String().c_escape()+"\"";
+					sgroups+="\""+groups[j].operator String().c_escape()+"\"";
 				}
 				sgroups+=" ]";
 				header+=sgroups;

+ 13 - 1
scene/resources/scene_format_text.h

@@ -43,7 +43,19 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader {
 	mutable int lines;
 
 	Map<String,String> remaps;
-	void _printerr();
+	//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); }
+
+	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);
+
+	VariantParser::ResourceParser rp;
+
+
+	Ref<PackedScene> packed_scene;
+
 
 friend class ResourceFormatLoaderText;
 

+ 4 - 3
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<SceneState> 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<SceneState>());
 
 	set_edited_scene(new_scene);
 	_get_scene_metadata();