Browse Source

-work in progress resourceparser and .tscn parser. Still non-functional
-fixed theora so it can compile theoralib but not theora
-fixed generation of windows icon in .rc, which didn't previously work in 32 bits

Juan Linietsky 9 years ago
parent
commit
ccd40f76e8

+ 5 - 2
SConstruct

@@ -106,7 +106,7 @@ opts.Add('opus','Build Opus Audio Format Support: (yes/no)','yes')
 opts.Add('minizip','Build Minizip Archive Support: (yes/no)','yes')
 opts.Add('squish','Squish BC Texture Compression in editor (yes/no)','yes')
 opts.Add('theora','Theora Video (yes/no)','yes')
-opts.Add('use_theoraplayer_binary', "Use precompiled binaries from libtheoraplayer for ogg/theora/vorbis (yes/no)", "no")
+opts.Add('theoralib','Theora Video (yes/no)','no')
 opts.Add('freetype','Freetype support in editor','yes')
 opts.Add('speex','Speex Audio (yes/no)','yes')
 opts.Add('xml','XML Save/Load support (yes/no)','yes')
@@ -305,7 +305,10 @@ if selected_platform in platform_list:
 		env.Append(CPPFLAGS=['-DOPUS_ENABLED']);
 
 	if (env['theora']=='yes'):
-		env.Append(CPPFLAGS=['-DTHEORA_ENABLED']);
+		env['theoralib']='yes'
+		env.Append(CPPFLAGS=['-DTHEORA_ENABLED']);		
+	if (env['theoralib']=='yes'):
+		env.Append(CPPFLAGS=['-DTHEORALIB_ENABLED']);
 
 	if (env['png']=='yes'):
 		env.Append(CPPFLAGS=['-DPNG_ENABLED']);

+ 1398 - 0
core/variant_parser.cpp

@@ -0,0 +1,1398 @@
+#include "variant_parser.h"
+#include "io/resource_loader.h"
+#include "os/keyboard.h"
+
+
+
+CharType VariantParser::StreamFile::get_char() {
+
+	return f->get_8();
+}
+
+bool VariantParser::StreamFile::is_utf8() const {
+
+	return true;
+}
+bool VariantParser::StreamFile::is_eof() const {
+
+	return f->eof_reached();
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+const char * VariantParser::tk_name[TK_MAX] = {
+	"'{'",
+	"'}'",
+	"'['",
+	"']'",
+	"'('",
+	"')'",
+	"identifier",
+	"string",
+	"number",
+	"':'",
+	"','",
+	"'='",
+	"EOF",
+	"ERROR"
+};
+
+
+
+Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, String &r_err_str) {
+
+	while (true) {
+
+		CharType cchar;
+		if (p_stream->saved) {
+			cchar=p_stream->saved;
+			p_stream->saved=0;
+		} else {
+			cchar=p_stream->get_char();
+		}
+
+		switch(cchar) {
+
+			case '\n': {
+
+				line++;
+				break;
+			};
+			case 0: {
+				r_token.type=TK_EOF;
+				return OK;
+			} break;
+			case '{': {
+
+				r_token.type=TK_CURLY_BRACKET_OPEN;
+				return OK;
+			};
+			case '}': {
+
+				r_token.type=TK_CURLY_BRACKET_CLOSE;
+				return OK;
+			};
+			case '[': {
+
+				r_token.type=TK_BRACKET_OPEN;
+				return OK;
+			};
+			case ']': {
+
+				r_token.type=TK_BRACKET_CLOSE;
+				return OK;
+			};
+			case '(': {
+
+				r_token.type=TK_PARENTHESIS_OPEN;
+				return OK;
+			};
+			case ')': {
+
+				r_token.type=TK_PARENTHESIS_CLOSE;
+				return OK;
+			};
+			case ':': {
+
+				r_token.type=TK_COLON;
+				return OK;
+			};
+			case ',': {
+
+				r_token.type=TK_COMMA;
+				return OK;
+			};
+			case '=': {
+
+				r_token.type=TK_EQUAL;
+				return OK;
+			};
+			case '"': {
+
+
+				String str;
+				while(true) {
+
+					CharType ch=p_stream->get_char();
+
+					if (ch==0) {
+						r_err_str="Unterminated String";
+						r_token.type=TK_ERROR;
+						return ERR_PARSE_ERROR;
+					} else if (ch=='"') {
+						break;
+					} else if (ch=='\\') {
+						//escaped characters...
+						CharType next = p_stream->get_char();
+						if (next==0) {
+							r_err_str="Unterminated String";
+							r_token.type=TK_ERROR;
+							return  ERR_PARSE_ERROR;
+						}
+						CharType res=0;
+
+						switch(next) {
+
+							case 'b': res=8; break;
+							case 't': res=9; break;
+							case 'n': res=10; break;
+							case 'f': res=12; break;
+							case 'r': res=13; break;
+							case 'u': {
+								//hexnumbarh - oct is deprecated
+
+
+								for(int j=0;j<4;j++) {
+									CharType c = p_stream->get_char();
+									if (c==0) {
+										r_err_str="Unterminated String";
+										r_token.type=TK_ERROR;
+										return ERR_PARSE_ERROR;
+									}
+									if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) {
+
+										r_err_str="Malformed hex constant in string";
+										r_token.type=TK_ERROR;
+										return ERR_PARSE_ERROR;
+									}
+									CharType v;
+									if (c>='0' && c<='9') {
+										v=c-'0';
+									} else if (c>='a' && c<='f') {
+										v=c-'a';
+										v+=10;
+									} else if (c>='A' && c<='F') {
+										v=c-'A';
+										v+=10;
+									} else {
+										ERR_PRINT("BUG");
+										v=0;
+									}
+
+									res<<=4;
+									res|=v;
+
+
+								}
+
+
+
+							} break;
+							//case '\"': res='\"'; break;
+							//case '\\': res='\\'; break;
+							//case '/': res='/'; break;
+							default: {
+								res = next;
+								//r_err_str="Invalid escape sequence";
+								//return ERR_PARSE_ERROR;
+							} break;
+						}
+
+						str+=res;
+
+					} else {
+						if (ch=='\n')
+							line++;
+						str+=ch;
+					}
+				}
+
+				r_token.type=TK_STRING;
+				r_token.value=str;
+				return OK;
+
+			} break;
+			default: {
+
+				if (cchar<=32) {
+					break;
+				}
+
+				if (cchar=='-' || (cchar>='0' && cchar<='9')) {
+					//a number
+					print_line("a numbar");
+
+					String num;
+#define READING_SIGN 0
+#define READING_INT 1
+#define READING_DEC 2
+#define READING_EXP 3
+#define READING_DONE 4
+					int reading=READING_INT;
+
+					if (cchar=='-') {
+						num+='-';
+						cchar=p_stream->get_char();
+						print_line("isnegative");
+
+					}
+
+
+
+					CharType c = cchar;
+					bool exp_sign=false;
+					bool exp_beg=false;
+					bool is_float=false;
+
+					while(true) {
+
+						switch(reading) {
+							case READING_INT: {
+
+								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;
+								}
+
+							 } break;
+							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;
+								}
+
+							 } break;
+							case READING_EXP: {
+
+								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;
+								}
+							 } break;
+						}
+
+						if (reading==READING_DONE)
+							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();
+					else
+						r_token.value=num.to_int();
+					return OK;
+
+				} else if ((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_') {
+
+					String id;
+
+					while((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_') {
+
+						id+=String::chr(cchar);
+						cchar=p_stream->get_char();
+					}
+
+					p_stream->saved=cchar;
+
+					r_token.type=TK_IDENTIFIER;
+					r_token.value=id;
+					return OK;
+				} else {
+					r_err_str="Unexpected character.";
+					r_token.type=TK_ERROR;
+					return ERR_PARSE_ERROR;
+				}
+			}
+		}
+	}
+
+	r_token.type=TK_ERROR;
+	return ERR_PARSE_ERROR;
+}
+
+
+Error VariantParser::_parse_construct(Stream *p_stream,Vector<float>& 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 '('";
+		return ERR_PARSE_ERROR;
+	}
+
+
+	bool first=true;
+	while(true) {
+
+		if (!first) {
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type==TK_COMMA) {
+				//do none
+			} else if (token.type!=TK_PARENTHESIS_CLOSE) {
+				break;
+			} else {
+				r_err_str="Expected ',' or ')'";
+				return ERR_PARSE_ERROR;
+
+			}
+		}
+		get_token(p_stream,token,line,r_err_str);
+		if (token.type!=TK_NUMBER) {
+			r_err_str="Expected float";
+			return ERR_PARSE_ERROR;
+		}
+
+		r_construct.push_back(token.value);
+	}
+
+	return OK;
+
+}
+
+Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,int &line,String &r_err_str,ResourceParser *p_res_parser) {
+
+
+
+/*	{
+		Error err = get_token(p_stream,token,line,r_err_str);
+		if (err)
+			return err;
+	}*/
+
+
+	if (token.type==TK_CURLY_BRACKET_OPEN) {
+
+		Dictionary d;
+		Error err = _parse_dictionary(d,p_stream,line,r_err_str,p_res_parser);
+		if (err)
+			return err;
+		value=d;
+		return OK;
+	} else if (token.type==TK_BRACKET_OPEN) {
+
+		Array a;
+		Error err = _parse_array(a,p_stream,line,r_err_str,p_res_parser);
+		if (err)
+			return err;
+		value=a;
+		return OK;
+
+	} else if (token.type==TK_IDENTIFIER) {
+/*
+		VECTOR2,		// 5
+		RECT2,
+		VECTOR3,
+		MATRIX32,
+		PLANE,
+		QUAT,			// 10
+		_AABB, //sorry naming convention fail :( not like it's used often
+		MATRIX3,
+		TRANSFORM,
+
+		// misc types
+		COLOR,
+		IMAGE,			// 15
+		NODE_PATH,
+		_RID,
+		OBJECT,
+		INPUT_EVENT,
+		DICTIONARY,		// 20
+		ARRAY,
+
+		// arrays
+		RAW_ARRAY,
+		INT_ARRAY,
+		REAL_ARRAY,
+		STRING_ARRAY,	// 25
+		VECTOR2_ARRAY,
+		VECTOR3_ARRAY,
+		COLOR_ARRAY,
+
+		VARIANT_MAX
+
+*/
+		String id = token.value;
+		if (id=="true")
+			value=true;
+		else if (id=="false")
+			value=false;
+		else if (id=="null")
+			value=Variant();
+		else if (id=="Vector2"){
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=2) {
+				r_err_str="Expected 2 arguments for constructor";
+			}
+
+			value=Vector2(args[0],args[1]);
+			return OK;
+		} else if (id=="Vector3"){
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=3) {
+				r_err_str="Expected 3 arguments for constructor";
+			}
+
+			value=Vector3(args[0],args[1],args[2]);
+			return OK;
+		} else if (id=="Matrix32"){
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=6) {
+				r_err_str="Expected 6 arguments for constructor";
+			}
+			Matrix32 m;
+			m[0]=Vector2(args[0],args[1]);
+			m[1]=Vector2(args[2],args[3]);
+			m[2]=Vector2(args[4],args[5]);
+			value=m;
+			return OK;
+		} else if (id=="Plane") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=4) {
+				r_err_str="Expected 4 arguments for constructor";
+			}
+
+			value=Plane(args[0],args[1],args[2],args[3]);
+			return OK;
+		} else if (id=="Quat") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=4) {
+				r_err_str="Expected 4 arguments for constructor";
+			}
+
+			value=Quat(args[0],args[1],args[2],args[3]);
+			return OK;
+
+		} else if (id=="AABB"){
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=6) {
+				r_err_str="Expected 6 arguments for constructor";
+			}
+
+			value=AABB(Vector3(args[0],args[1],args[2]),Vector3(args[3],args[4],args[5]));
+			return OK;
+
+		} else if (id=="Matrix3"){
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=9) {
+				r_err_str="Expected 9 arguments for constructor";
+			}
+
+			value=Matrix3(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
+			return OK;
+		} else if (id=="Transform"){
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=12) {
+				r_err_str="Expected 12 arguments for constructor";
+			}
+
+			value=Transform(Matrix3(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]),Vector3(args[9],args[10],args[11]));
+			return OK;
+
+		} else if (id=="Color") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			if (args.size()!=4) {
+				r_err_str="Expected 4 arguments for constructor";
+			}
+
+			value=Color(args[0],args[1],args[2],args[3]);
+			return OK;
+
+		} else if (id=="Image") {
+
+			//:|
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_OPEN) {
+				r_err_str="Expected '('";
+				return ERR_PARSE_ERROR;
+			}
+
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type==TK_PARENTHESIS_CLOSE) {
+				value=Image(); // just an Image()
+				return OK;
+			} else if (token.type!=TK_NUMBER) {
+				r_err_str="Expected number (width)";
+				return ERR_PARSE_ERROR;
+			}
+
+			get_token(p_stream,token,line,r_err_str);
+
+			int width=token.value;
+			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 (height)";
+				return ERR_PARSE_ERROR;
+			}
+
+			int height=token.value;
+			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 (mipmaps)";
+				return ERR_PARSE_ERROR;
+			}
+
+			int mipmaps=token.value;
+			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_IDENTIFIER) {
+				r_err_str="Expected identifier (format)";
+				return ERR_PARSE_ERROR;
+			}
+
+			String sformat=token.value;
+
+			Image::Format format;
+
+			if (sformat=="GRAYSCALE") format=Image::FORMAT_GRAYSCALE;
+			else if (sformat=="INTENSITY") format=Image::FORMAT_INTENSITY;
+			else if (sformat=="GRAYSCALE_ALPHA") format=Image::FORMAT_GRAYSCALE_ALPHA;
+			else if (sformat=="RGB") format=Image::FORMAT_RGB;
+			else if (sformat=="RGBA") format=Image::FORMAT_RGBA;
+			else if (sformat=="INDEXED") format=Image::FORMAT_INDEXED;
+			else if (sformat=="INDEXED_ALPHA") format=Image::FORMAT_INDEXED_ALPHA;
+			else if (sformat=="BC1") format=Image::FORMAT_BC1;
+			else if (sformat=="BC2") format=Image::FORMAT_BC2;
+			else if (sformat=="BC3") format=Image::FORMAT_BC3;
+			else if (sformat=="BC4") format=Image::FORMAT_BC4;
+			else if (sformat=="BC5") format=Image::FORMAT_BC5;
+			else if (sformat=="PVRTC2") format=Image::FORMAT_PVRTC2;
+			else if (sformat=="PVRTC2_ALPHA") format=Image::FORMAT_PVRTC2_ALPHA;
+			else if (sformat=="PVRTC4") format=Image::FORMAT_PVRTC4;
+			else if (sformat=="PVRTC4_ALPHA") format=Image::FORMAT_PVRTC4_ALPHA;
+			else if (sformat=="ATC") format=Image::FORMAT_ATC;
+			else if (sformat=="ATC_ALPHA_EXPLICIT") format=Image::FORMAT_ATC_ALPHA_EXPLICIT;
+			else if (sformat=="ATC_ALPHA_INTERPOLATED") format=Image::FORMAT_ATC_ALPHA_INTERPOLATED;
+			else if (sformat=="CUSTOM") format=Image::FORMAT_CUSTOM;
+			else {
+				r_err_str="Invalid image format: '"+sformat+"'";
+				return ERR_PARSE_ERROR;
+			};
+
+			int len = Image::get_image_data_size(width,height,format,mipmaps);
+
+			DVector<uint8_t> buffer;
+			buffer.resize(len);
+
+			if (buffer.size()!=len) {
+				r_err_str="Couldn't allocate image buffer of size: "+itos(len);
+			}
+
+			{
+				DVector<uint8_t>::Write w=buffer.write();
+
+				for(int i=0;i<len;i++) {
+
+					if (token.type!=TK_COMMA) {
+						r_err_str="Expected ','";
+						return ERR_PARSE_ERROR;
+					}
+
+					if (token.type!=TK_NUMBER) {
+						r_err_str="Expected number";
+						return ERR_PARSE_ERROR;
+					}
+
+					w[i]=int(token.value);
+
+				}
+			}
+
+
+			Image img(width,height,mipmaps,format,buffer);
+
+			value=img;
+
+			return OK;
+
+
+		} else if (id=="NodePath") {
+
+
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_OPEN) {
+				r_err_str="Expected '('";
+				return ERR_PARSE_ERROR;
+			}
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_STRING) {
+				r_err_str="Expected string as argument";
+				return ERR_PARSE_ERROR;
+			}
+
+			value=NodePath(String(token.value));
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_CLOSE) {
+				r_err_str="Expected ')'";
+				return ERR_PARSE_ERROR;
+			}
+
+		} else if (id=="RID") {
+
+
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_OPEN) {
+				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 as argument";
+				return ERR_PARSE_ERROR;
+			}
+
+			value=token.value;
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_CLOSE) {
+				r_err_str="Expected ')'";
+				return ERR_PARSE_ERROR;
+			}
+
+
+			return OK;
+
+		} else if (id=="Resource") {
+
+
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_OPEN) {
+				r_err_str="Expected '('";
+				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 if (p_res_parser && 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 {
+
+				r_err_str="Expected string as argument.";
+				return ERR_PARSE_ERROR;
+			}
+
+			return OK;
+
+		} else if (id=="InputEvent") {
+
+
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_OPEN) {
+				r_err_str="Expected '('";
+				return ERR_PARSE_ERROR;
+			}
+
+			get_token(p_stream,token,line,r_err_str);
+
+			if (token.type!=TK_IDENTIFIER) {
+				r_err_str="Expected identifier";
+				return ERR_PARSE_ERROR;
+			}
+
+
+			String id = token.value;
+
+			InputEvent ie;
+
+			if (id=="KEY") {
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_COMMA) {
+					r_err_str="Expected ','";
+					return ERR_PARSE_ERROR;
+				}
+
+				ie.type=InputEvent::KEY;
+
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type==TK_IDENTIFIER) {
+					String name=token.value;
+					ie.key.scancode=find_keycode(name);
+				} else if (token.type==TK_NUMBER) {
+
+					ie.key.scancode=token.value;
+				} else {
+
+					r_err_str="Expected string or integer for keycode";
+					return ERR_PARSE_ERROR;
+				}
+
+				get_token(p_stream,token,line,r_err_str);
+
+				if (token.type==TK_COMMA) {
+
+					get_token(p_stream,token,line,r_err_str);
+
+					if (token.type!=TK_IDENTIFIER) {
+						r_err_str="Expected identifier with modifier flas";
+						return ERR_PARSE_ERROR;
+					}
+
+					String mods=token.value;
+
+					if (mods.findn("C")!=-1)
+						ie.key.mod.control=true;
+					if (mods.findn("A")!=-1)
+						ie.key.mod.alt=true;
+					if (mods.findn("S")!=-1)
+						ie.key.mod.shift=true;
+					if (mods.findn("M")!=-1)
+						ie.key.mod.meta=true;
+
+					get_token(p_stream,token,line,r_err_str);
+					if (token.type!=TK_PARENTHESIS_CLOSE) {
+						r_err_str="Expected ')'";
+						return ERR_PARSE_ERROR;
+					}
+
+				} else if (token.type!=TK_PARENTHESIS_CLOSE) {
+
+					r_err_str="Expected ')' or modifier flags.";
+					return ERR_PARSE_ERROR;
+				}
+
+
+			} else if (id=="MBUTTON") {
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_COMMA) {
+					r_err_str="Expected ','";
+					return ERR_PARSE_ERROR;
+				}
+
+				ie.type=InputEvent::MOUSE_BUTTON;
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_NUMBER) {
+					r_err_str="Expected button index";
+					return ERR_PARSE_ERROR;
+				}
+
+				ie.mouse_button.button_index = token.value;
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_PARENTHESIS_CLOSE) {
+					r_err_str="Expected ')'";
+					return ERR_PARSE_ERROR;
+				}
+
+			} else if (id=="JBUTTON") {
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_COMMA) {
+					r_err_str="Expected ','";
+					return ERR_PARSE_ERROR;
+				}
+
+				ie.type=InputEvent::JOYSTICK_BUTTON;
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_NUMBER) {
+					r_err_str="Expected button index";
+					return ERR_PARSE_ERROR;
+				}
+
+				ie.joy_button.button_index = token.value;
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_PARENTHESIS_CLOSE) {
+					r_err_str="Expected ')'";
+					return ERR_PARSE_ERROR;
+				}
+
+			} else if (id=="JAXIS") {
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_COMMA) {
+					r_err_str="Expected ','";
+					return ERR_PARSE_ERROR;
+				}
+
+				ie.type=InputEvent::JOYSTICK_MOTION;
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_NUMBER) {
+					r_err_str="Expected axis index";
+					return ERR_PARSE_ERROR;
+				}
+
+				ie.joy_motion.axis = token.value;
+
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_PARENTHESIS_CLOSE) {
+					r_err_str="Expected ')'";
+					return ERR_PARSE_ERROR;
+				}
+
+			} else {
+
+				r_err_str="Invalid input event type.";
+				return ERR_PARSE_ERROR;
+			}
+
+			value=ie;
+
+			return OK;
+
+		} else if (id=="ByteArray") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			DVector<uint8_t> arr;
+			{
+				int len=args.size();
+				arr.resize(len);
+				DVector<uint8_t>::Write w = arr.write();
+				for(int i=0;i<len;i++) {
+					w[i]=args[i];
+				}
+			}
+
+			value=arr;
+
+			return OK;
+
+		} else if (id=="IntArray") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			DVector<int32_t> arr;
+			{
+				int len=args.size();
+				arr.resize(len);
+				DVector<int32_t>::Write w = arr.write();
+				for(int i=0;i<len;i++) {
+					w[i]=Math::fast_ftoi(args[i]);
+				}
+			}
+
+			value=arr;
+
+			return OK;
+
+		} else if (id=="FloatArray") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			DVector<float> arr;
+			{
+				int len=args.size();
+				arr.resize(len);
+				DVector<float>::Write w = arr.write();
+				for(int i=0;i<len;i++) {
+					w[i]=args[i];
+				}
+			}
+
+			value=arr;
+
+			return OK;
+		} else if (id=="StringArray") {
+
+
+			get_token(p_stream,token,line,r_err_str);
+			if (token.type!=TK_PARENTHESIS_OPEN) {
+				r_err_str="Expected '('";
+				return ERR_PARSE_ERROR;
+			}
+
+			Vector<String> cs;
+
+			bool first=true;
+			while(true) {
+
+				if (!first) {
+					get_token(p_stream,token,line,r_err_str);
+					if (token.type==TK_COMMA) {
+						//do none
+					} else if (token.type!=TK_PARENTHESIS_CLOSE) {
+						break;
+					} else {
+						r_err_str="Expected ',' or ')'";
+						return ERR_PARSE_ERROR;
+
+					}
+				}
+				get_token(p_stream,token,line,r_err_str);
+				if (token.type!=TK_STRING) {
+					r_err_str="Expected string";
+					return ERR_PARSE_ERROR;
+				}
+
+				cs.push_back(token.value);
+			}
+
+
+			DVector<String> arr;
+			{
+				int len=cs.size();
+				arr.resize(len);
+				DVector<String>::Write w = arr.write();
+				for(int i=0;i<len;i++) {
+					w[i]=cs[i];
+				}
+			}
+
+			value=arr;
+
+			return OK;
+
+
+		} else if (id=="Vector2Array") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			DVector<Vector2> arr;
+			{
+				int len=args.size()/2;
+				arr.resize(len);
+				DVector<Vector2>::Write w = arr.write();
+				for(int i=0;i<len;i++) {
+					w[i]=Vector2(args[i*2+0],args[i*2+1]);
+				}
+			}
+
+			value=arr;
+
+			return OK;
+
+		} else if (id=="Vector3Array") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			DVector<Vector3> arr;
+			{
+				int len=args.size()/3;
+				arr.resize(len);
+				DVector<Vector3>::Write w = arr.write();
+				for(int i=0;i<len;i++) {
+					w[i]=Vector3(args[i*3+0],args[i*3+1],args[i*3+2]);
+				}
+			}
+
+			value=arr;
+
+			return OK;
+
+		} else if (id=="ColorArray") {
+
+			Vector<float> args;
+			Error err = _parse_construct(p_stream,args,line,r_err_str);
+			if (err)
+				return err;
+
+			DVector<Color> arr;
+			{
+				int len=args.size()/4;
+				arr.resize(len);
+				DVector<Color>::Write w = arr.write();
+				for(int i=0;i<len;i++) {
+					w[i]=Color(args[i*3+0],args[i*3+1],args[i*3+2],args[i*3+3]);
+				}
+			}
+
+			value=arr;
+
+			return OK;
+
+		} else {
+			r_err_str="Unexpected identifier: '"+id+"'.";
+			return ERR_PARSE_ERROR;
+		}
+
+
+		/*
+				VECTOR2,		// 5
+				RECT2,
+				VECTOR3,
+				MATRIX32,
+				PLANE,
+				QUAT,			// 10
+				_AABB, //sorry naming convention fail :( not like it's used often
+				MATRIX3,
+				TRANSFORM,
+
+				// misc types
+				COLOR,
+				IMAGE,			// 15
+				NODE_PATH,
+				_RID,
+				OBJECT,
+				INPUT_EVENT,
+				DICTIONARY,		// 20
+				ARRAY,
+
+				// arrays
+				RAW_ARRAY,
+				INT_ARRAY,
+				REAL_ARRAY,
+				STRING_ARRAY,	// 25
+				VECTOR2_ARRAY,
+				VECTOR3_ARRAY,
+				COLOR_ARRAY,
+
+				VARIANT_MAX
+
+		*/
+
+		return OK;
+
+	} else if (token.type==TK_NUMBER) {
+
+		value=token.value;
+		return OK;
+	} else if (token.type==TK_STRING) {
+
+		value=token.value;
+		return OK;
+	} else {
+		r_err_str="Expected value, got "+String(tk_name[token.type])+".";
+		return ERR_PARSE_ERROR;
+	}
+
+	return ERR_PARSE_ERROR;
+}
+
+
+Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) {
+
+	Token token;
+	bool need_comma=false;
+
+
+	while(!p_stream->is_eof()) {
+
+		Error err = get_token(p_stream,token,line,r_err_str);
+		if (err!=OK)
+			return err;
+
+		if (token.type==TK_BRACKET_CLOSE) {
+
+			return OK;
+		}
+
+		if (need_comma) {
+
+			if (token.type!=TK_COMMA) {
+
+				r_err_str="Expected ','";
+				return ERR_PARSE_ERROR;
+			} else {
+				need_comma=false;
+				continue;
+			}
+		}
+
+		Variant v;
+		err = parse_value(token,v,p_stream,line,r_err_str,p_res_parser);
+		if (err)
+			return err;
+
+		array.push_back(v);
+		need_comma=true;
+
+	}
+
+	return OK;
+
+}
+
+Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) {
+
+	bool at_key=true;
+	Variant key;
+	Token token;
+	bool need_comma=false;
+
+
+	while(!p_stream->is_eof()) {
+
+
+		if (at_key) {
+
+			Error err = get_token(p_stream,token,line,r_err_str);
+			if (err!=OK)
+				return err;
+
+			if (token.type==TK_CURLY_BRACKET_CLOSE) {
+
+				return OK;
+			}
+
+			if (need_comma) {
+
+				if (token.type!=TK_COMMA) {
+
+					r_err_str="Expected '}' or ','";
+					return ERR_PARSE_ERROR;
+				} else {
+					need_comma=false;
+					continue;
+				}
+			}
+
+
+
+
+			err = parse_value(token,key,p_stream,line,r_err_str,p_res_parser);
+
+			if (err)
+				return err;
+
+			err = get_token(p_stream,token,line,r_err_str);
+
+			if (err!=OK)
+				return err;
+			if (token.type!=TK_COLON) {
+
+				r_err_str="Expected ':'";
+				return ERR_PARSE_ERROR;
+			}
+			at_key=false;
+		} else {
+
+
+			Error err = get_token(p_stream,token,line,r_err_str);
+			if (err!=OK)
+				return err;
+
+			Variant v;
+			err = parse_value(token,v,p_stream,line,r_err_str,p_res_parser);
+			if (err)
+				return err;
+			object[key]=v;
+			need_comma=true;
+			at_key=true;
+		}
+	}
+
+	return OK;
+}
+
+
+Error VariantParser::_parse_tag(Token& token,Stream *p_stream, int &line, String &r_err_str,Tag& r_tag) {
+
+	r_tag.fields.clear();
+
+	if (token.type!=TK_BRACKET_OPEN) {
+		r_err_str="Expected '['";
+		return ERR_PARSE_ERROR;
+	}
+
+
+	get_token(p_stream,token,line,r_err_str);
+
+
+	if (token.type!=TK_IDENTIFIER) {
+		r_err_str="Expected identifier (tag name)";
+		return ERR_PARSE_ERROR;
+	}
+
+	r_tag.name=token.value;
+
+	print_line("tag name: "+r_tag.name);
+
+	while(true) {
+
+		get_token(p_stream,token,line,r_err_str);
+		if (token.type==TK_BRACKET_CLOSE)
+			break;
+
+		if (token.type!=TK_IDENTIFIER) {
+			r_err_str="Expected Identifier";
+			return ERR_PARSE_ERROR;
+		}
+
+		String id=token.value;
+
+		print_line("got ID: "+id);
+
+		get_token(p_stream,token,line,r_err_str);
+		if (token.type!=TK_EQUAL) {
+			r_err_str="Expected '='";
+			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);
+		if (err)
+			return err;
+
+		print_line("id: "+id+" value: "+String(value));
+
+		r_tag.fields[id]=value;
+
+	}
+
+
+	return OK;
+
+}
+
+Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag) {
+
+	Token token;
+	get_token(p_stream,token,line,r_err_str);
+	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);
+
+}
+
+Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str,Tag& r_tag,String &r_assign) {
+
+	r_tag.name.clear();
+	r_assign=String();
+
+	return OK;
+}
+
+Error VariantParser::parse(Stream *p_stream, Variant& r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser) {
+
+
+	Token token;
+	Error err = get_token(p_stream,token,r_err_line,r_err_str);
+	if (err)
+		return err;
+	return parse_value(token,r_ret,p_stream,r_err_line,r_err_str,p_res_parser);
+
+}
+
+

+ 100 - 0
core/variant_parser.h

@@ -0,0 +1,100 @@
+#ifndef VARIANT_PARSER_H
+#define VARIANT_PARSER_H
+
+#include "variant.h"
+#include "os/file_access.h"
+#include "resource.h"
+
+class VariantParser {
+public:
+
+	struct Stream {
+
+		virtual CharType get_char()=0;
+		virtual bool is_utf8() const=0;
+		virtual bool is_eof() const=0;
+
+		CharType saved;
+
+		Stream() { saved=0; }
+		virtual ~Stream() {}
+	};
+
+	struct StreamFile : public Stream {
+
+		FileAccess *f;
+
+		virtual CharType get_char();
+		virtual bool is_utf8() const;
+		virtual bool is_eof() const;
+
+		StreamFile() { f=NULL; }
+
+	};
+
+	typedef Error (*ParseResourceFunc)(void* p_self, Stream* p_stream,Ref<Resource>& r_res,int &line,String &r_err_str);
+
+	struct ResourceParser {
+
+		void *userdata;
+		ParseResourceFunc func;
+
+	};
+
+	enum TokenType {
+		TK_CURLY_BRACKET_OPEN,
+		TK_CURLY_BRACKET_CLOSE,
+		TK_BRACKET_OPEN,
+		TK_BRACKET_CLOSE,
+		TK_PARENTHESIS_OPEN,
+		TK_PARENTHESIS_CLOSE,
+		TK_IDENTIFIER,
+		TK_STRING,
+		TK_NUMBER,
+		TK_COLON,
+		TK_COMMA,
+		TK_EQUAL,
+		TK_EOF,
+		TK_ERROR,
+		TK_MAX
+	};
+
+	enum Expecting {
+
+		EXPECT_OBJECT,
+		EXPECT_OBJECT_KEY,
+		EXPECT_COLON,
+		EXPECT_OBJECT_VALUE,
+	};
+
+	struct Token {
+
+		TokenType type;
+		Variant value;
+	};
+
+	struct Tag {
+
+		String name;
+		Map<String,Variant> fields;
+	};
+
+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);
+	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);
+
+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_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);
+	static Error parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line,ResourceParser *p_res_parser=NULL);
+};
+
+#endif // VARIANT_PARSER_H

+ 2 - 4
drivers/SCsub

@@ -31,7 +31,7 @@ SConscript("rtaudio/SCsub");
 SConscript("nedmalloc/SCsub");
 SConscript("nrex/SCsub");
 SConscript("chibi/SCsub");
-if (env["vorbis"]=="yes" or env["speex"]=="yes" or env["theora"]=="yes" or env["opus"]=="yes"):
+if (env["vorbis"]=="yes" or env["speex"]=="yes" or env["theoralib"]=="yes" or env["opus"]=="yes"):
         SConscript("ogg/SCsub");
 if (env["vorbis"]=="yes"):
         SConscript("vorbis/SCsub");
@@ -40,9 +40,7 @@ if (env["opus"]=="yes"):
 if (env["tools"]=="yes"):
 	SConscript("convex_decomp/SCsub");
 
-#if env["theora"]=="yes":
-#	SConscript("theoraplayer/SCsub")
-if (env["theora"]=="yes"):
+if (env["theoralib"]=="yes"):
 	SConscript("theora/SCsub");
 if (env['speex']=='yes'):
 	SConscript("speex/SCsub");

+ 0 - 4
drivers/register_driver_types.cpp

@@ -54,10 +54,6 @@
 #include "theora/video_stream_theora.h"
 #endif
 
-#ifdef THEORAPLAYER_ENABLED
-#include "theoraplayer/video_stream_theoraplayer.h"
-#endif
-
 
 #include "drivers/nrex/regex.h"
 

+ 1 - 2
drivers/theora/SCsub

@@ -31,5 +31,4 @@ sources = [
 	"theora/video_stream_theora.cpp",
 ]
 
-if env['use_theoraplayer_binary'] != "yes":
-	env.drivers_sources += sources
+env.drivers_sources += sources

+ 2 - 10
main/main.cpp

@@ -870,21 +870,13 @@ Error Main::setup2() {
 		String boot_logo_path=GLOBAL_DEF("application/boot_splash",String());
 		bool boot_logo_scale=GLOBAL_DEF("application/boot_splash_fullsize",true);
 		Globals::get_singleton()->set_custom_property_info("application/boot_splash",PropertyInfo(Variant::STRING,"application/boot_splash",PROPERTY_HINT_FILE,"*.png"));
-		print_line("BOOT SPLASH: "+boot_logo_path);
 
 		Image boot_logo;
 
 		boot_logo_path = boot_logo_path.strip_edges();
-		print_line("BOOT SPLASH IS : "+boot_logo_path);
 
 		if (boot_logo_path!=String() /*&& FileAccess::exists(boot_logo_path)*/) {
 			Error err = boot_logo.load(boot_logo_path);
-			if (err!=OK) {
-				print_line("ËRROR LOADING BOOT LOGO SPLASH :"+boot_logo_path);
-			} else {
-				print_line("BOOT SPLASH OK!");
-
-			}
 		}
 
 		if (!boot_logo.empty()) {
@@ -944,10 +936,10 @@ Error Main::setup2() {
 
 	if (String(Globals::get_singleton()->get("display/custom_mouse_cursor"))!=String()) {
 
-		print_line("use custom cursor");
+		//print_line("use custom cursor");
 		Ref<Texture> cursor=ResourceLoader::load(Globals::get_singleton()->get("display/custom_mouse_cursor"));
 		if (cursor.is_valid()) {
-			print_line("loaded ok");
+		//	print_line("loaded ok");
 			Vector2 hotspot = Globals::get_singleton()->get("display/custom_mouse_cursor_hotspot");
 			Input::get_singleton()->set_custom_mouse_cursor(cursor,hotspot);
 		}

+ 5 - 5
platform/windows/SCsub

@@ -11,11 +11,11 @@ common_win=[
 	"stream_peer_winsock.cpp",
 ]
 
-env.RES('godot_res.rc')
-if env["is_mingw"]:
-	common_win.append("godot_res.o")
-else:
-	common_win.append("godot_res.res")
+restarget="godot_res"+env["OBJSUFFIX"]
+
+obj = env.RES(restarget,'godot_res.rc')
+
+common_win.append(obj)
 
 env.Program('#bin/godot',['godot_win.cpp']+common_win,PROGSUFFIX=env["PROGSUFFIX"])
 

+ 7 - 0
scene/register_scene_types.cpp

@@ -231,6 +231,7 @@ static ResourceFormatLoaderTheme *resource_loader_theme=NULL;
 static ResourceFormatLoaderShader *resource_loader_shader=NULL;
 
 static ResourceFormatSaverText *resource_saver_text=NULL;
+static ResourceFormatLoaderText *resource_loader_text=NULL;
 
 //static SceneStringNames *string_names;
 
@@ -619,6 +620,9 @@ void register_scene_types() {
 	resource_saver_text = memnew( ResourceFormatSaverText );
 	ResourceSaver::add_resource_format_saver(resource_saver_text);
 
+	resource_loader_text = memnew( ResourceFormatLoaderText );
+	ResourceLoader::add_resource_format_loader(resource_loader_text);
+
 }
 
 void unregister_scene_types() {
@@ -640,5 +644,8 @@ void unregister_scene_types() {
 	if (resource_saver_text) {
 		memdelete(resource_saver_text);
 	}
+	if (resource_loader_text) {
+		memdelete(resource_loader_text);
+	}
 	SceneStringNames::free();
 }

+ 773 - 12
scene/resources/scene_format_text.cpp

@@ -6,6 +6,770 @@
 
 #define FORMAT_VERSION 1
 
+#include "version.h"
+#include "os/dir_access.h"
+
+
+Error ResourceInteractiveLoaderText::parse_property(Variant& r_v, String &r_name)  {
+
+	return OK;
+}
+
+
+
+
+///
+
+void ResourceInteractiveLoaderText::set_local_path(const String& p_local_path) {
+
+	res_path=p_local_path;
+}
+
+Ref<Resource> ResourceInteractiveLoaderText::get_resource() {
+
+	return resource;
+}
+Error ResourceInteractiveLoaderText::poll() {
+
+#if 0
+	if (error!=OK)
+		return error;
+
+	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;
+	}
+
+	RES res;
+	//Object *obj=NULL;
+
+	bool main;
+
+	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);
+
+		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())+": <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
+			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())+": <ext_resource> 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);
+	}
+
+
+	String type;
+	String path;
+	int subres=0;
+
+	if (!main) {
+		//loading resource
+
+		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"];
+
+		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 <resource> 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<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);
+	}
+
+	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 {
+
+	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) {
+
+#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())+": <ext_resource> missing 'path' field.");
+		ERR_FAIL_COND(!tag->args.has("path"));
+
+		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 (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;
+	}
+#endif
+}
+
+Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) {
+
+
+
+	if (next_tag.name=="ext_resource") {
+
+		Error err;
+
+		if (!next_tag.fields.has("path")) {
+			err=ERR_FILE_CORRUPT;
+			error_text="Missing 'path' in external resource tag";
+			_printerr();
+			return err;
+		}
+
+		if (!next_tag.fields.has("type")) {
+			err=ERR_FILE_CORRUPT;
+			error_text="Missing 'type' in external resource tag";
+			_printerr();
+			return err;
+		}
+
+		if (!next_tag.fields.has("index")) {
+			err=ERR_FILE_CORRUPT;
+			error_text="Missing 'index' in external resource tag";
+			_printerr();
+			return err;
+		}
+
+		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()) {
+			// path is relative to file being loaded, so convert to a resource path
+			path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
+		}
+
+		if (remaps.has(path)) {
+			path=remaps[path];
+		}
+
+		RES res = ResourceLoader::load(path,type);
+
+		if (res.is_null()) {
+
+			if (ResourceLoader::get_abort_on_missing_resources()) {
+				error=ERR_FILE_CORRUPT;
+				error_text="[ext_resource] referenced nonexistent resource at: "+path;
+				_printerr();
+				return error;
+			} else {
+				ResourceLoader::notify_dependency_error(local_path,path,type);
+			}
+		} else {
+
+			resource_cache.push_back(res);
+		}
+
+		ExtResource er;
+		er.path=path;
+		er.type=type;
+		ext_resources[index]=er;
+
+		err = VariantParser::parse_tag(&stream,lines,error_text,next_tag);
+
+		if (err) {
+			error_text="Unexpected end of file";
+			_printerr();
+			error=ERR_FILE_CORRUPT;
+			return error;
+		}
+
+		return OK;
+
+
+	}
+
+#if 0
+	open(p_f);
+	ERR_FAIL_COND_V(error!=OK,error);
+
+	//FileAccess
+
+	bool old_format=false;
+
+	FileAccess *fw = NULL;
+
+	String base_path=local_path.get_base_dir();
+
+	while(true) {
+		bool exit;
+		List<String> order;
+
+		Tag *tag = parse_tag(&exit,true,&order);
+
+		bool done=false;
+
+		if (!tag) {
+			if (fw) {
+				memdelete(fw);
+			}
+			error=ERR_FILE_CORRUPT;
+			ERR_FAIL_COND_V(!exit,error);
+			error=ERR_FILE_EOF;
+
+			return error;
+		}
+
+		if (tag->name=="ext_resource") {
+
+			if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) {
+				old_format=true;
+				break;
+			}
+
+			if (!fw) {
+
+				fw=FileAccess::open(p_path+".depren",FileAccess::WRITE);
+				fw->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); //no escape
+				fw->store_line("<resource_file type=\""+resource_type+"\" subresource_count=\""+itos(resources_total)+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\">");
+
+			}
+
+			String path = tag->args["path"];
+			String index = tag->args["index"];
+			String type = tag->args["type"];
+
+
+			bool relative=false;
+			if (!path.begins_with("res://")) {
+				path=base_path.plus_file(path).simplify_path();
+				relative=true;
+			}
+
+
+			if (p_map.has(path)) {
+				String np=p_map[path];
+				path=np;
+			}
+
+			if (relative) {
+				//restore relative
+				path=base_path.path_to_file(path);
+			}
+
+			tag->args["path"]=path;
+			tag->args["index"]=index;
+			tag->args["type"]=type;
+
+		} else {
+
+			done=true;
+		}
+
+		String tagt="\t<";
+		if (exit)
+			tagt+="/";
+		tagt+=tag->name;
+
+		for(List<String>::Element *E=order.front();E;E=E->next()) {
+			tagt+=" "+E->get()+"=\""+tag->args[E->get()]+"\"";
+		}
+		tagt+=">";
+		fw->store_line(tagt);
+		if (done)
+			break;
+		close_tag("ext_resource");
+		fw->store_line("\t</ext_resource>");
+
+	}
+
+
+	if (old_format) {
+		if (fw)
+			memdelete(fw);
+
+		DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		da->remove(p_path+".depren");
+		memdelete(da);
+		//fuck it, use the old approach;
+
+		WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data());
+
+		Error err;
+		FileAccess *f2 = FileAccess::open(p_path,FileAccess::READ,&err);
+		if (err!=OK) {
+			ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN);
+		}
+
+		Ref<ResourceInteractiveLoaderText> ria = memnew( ResourceInteractiveLoaderText );
+		ria->local_path=Globals::get_singleton()->localize_path(p_path);
+		ria->res_path=ria->local_path;
+		ria->remaps=p_map;
+	//	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
+		ria->open(f2);
+
+		err = ria->poll();
+
+		while(err==OK) {
+			err=ria->poll();
+		}
+
+		ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT);
+		RES res = ria->get_resource();
+		ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT);
+
+		return ResourceFormatSaverText::singleton->save(p_path,res);
+	}
+
+	if (!fw) {
+
+		return OK; //nothing to rename, do nothing
+	}
+
+	uint8_t c=f->get_8();
+	while(!f->eof_reached()) {
+		fw->store_8(c);
+		c=f->get_8();
+	}
+
+	bool all_ok = fw->get_error()==OK;
+
+	memdelete(fw);
+
+	if (!all_ok) {
+		return ERR_CANT_CREATE;
+	}
+
+	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	da->remove(p_path);
+	da->rename(p_path+".depren",p_path);
+	memdelete(da);
+#endif
+	return OK;
+
+}
+
+
+void ResourceInteractiveLoaderText::open(FileAccess *p_f) {
+
+	error=OK;
+
+	lines=1;
+	f=p_f;
+
+
+	stream.f=f;
+	is_scene=false;
+
+
+	VariantParser::Tag tag;
+	Error err = VariantParser::parse_tag(&stream,lines,error_text,tag);
+
+	if (err) {
+
+		error=err;
+		_printerr();
+		return;
+	}
+
+	if (tag.fields.has("format")) {
+		int fmt = tag.fields["format"];
+		if (fmt>FORMAT_VERSION) {
+			error_text="Saved with newer format version";
+			_printerr();
+			error=ERR_PARSE_ERROR;
+			return;
+		}
+	}
+
+	print_line("TAG NAME: "+tag.name);
+
+	if (tag.name=="gd_scene") {
+		is_scene=true;
+	} else if (tag.name=="gd_resource") {
+		if (!tag.fields.has("type")) {
+			error_text="Missing 'type' field in 'gd_resource' tag";
+			_printerr();
+			error=ERR_PARSE_ERROR;
+			return;
+		}
+
+		res_type=tag.fields["type"];
+
+	} else {
+		error_text="Unrecognized file type: "+tag.name;
+		_printerr();
+		error=ERR_PARSE_ERROR;
+		return;
+
+	}
+
+
+
+	if (tag.fields.has("load_steps")) {
+		resources_total=tag.fields["load_steps"];
+	} else {
+		resources_total=0;
+	}
+
+
+	err = VariantParser::parse_tag(&stream,lines,error_text,next_tag);
+
+	if (err) {
+		error_text="Unexpected end of file";
+		_printerr();
+		error=ERR_FILE_CORRUPT;
+	}
+
+}
+
+void ResourceInteractiveLoaderText::_printerr() {
+
+	ERR_PRINT(String(res_path+":"+itos(lines)+" - Parse Error: "+error_text).utf8().get_data());
+}
+
+
+String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) {
+
+	error=OK;
+
+	lines=1;
+	f=p_f;
+
+	stream.f=f;
+
+
+	VariantParser::Tag tag;
+	Error err = VariantParser::parse_tag(&stream,lines,error_text,tag);
+
+	if (err) {
+		_printerr();
+		return "";
+	}
+
+	if (tag.fields.has("format")) {
+		int fmt = tag.fields["format"];
+		if (fmt>FORMAT_VERSION) {
+			error_text="Saved with newer format version";
+			_printerr();
+			return "";
+		}
+	}
+
+	if (tag.name=="gd_scene")
+		return "PackedScene";
+
+	if (tag.name!="gd_resource")
+		return "";
+
+
+
+	if (!tag.fields.has("type")) {
+		error_text="Missing 'type' field in 'gd_resource' tag";
+		_printerr();
+		return "";
+	}
+
+	return tag.fields["type"];
+
+
+}
+
+/////////////////////
+
+Ref<ResourceInteractiveLoader> ResourceFormatLoaderText::load_interactive(const String &p_path, Error *r_error) {
+
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
+
+	Error err;
+	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
+
+
+	if (err!=OK) {
+
+		ERR_FAIL_COND_V(err!=OK,Ref<ResourceInteractiveLoader>());
+	}
+
+	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) );
+	ria->open(f);
+
+	return ria;
+}
+
+void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const {
+
+
+	if (p_type=="PackedScene")
+		p_extensions->push_back("tscn");
+	else
+		p_extensions->push_back("tres");
+
+}
+
+void ResourceFormatLoaderText::get_recognized_extensions(List<String> *p_extensions) const{
+
+	p_extensions->push_back("tscn");
+	p_extensions->push_back("tres");
+}
+
+bool ResourceFormatLoaderText::handles_type(const String& p_type) const{
+
+	return true;
+}
+String ResourceFormatLoaderText::get_resource_type(const String &p_path) const{
+
+
+
+	String ext=p_path.extension().to_lower();
+	if (ext=="tscn")
+		return "PackedScene";
+
+	//for anyhting else must test..
+
+	FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
+	if (!f) {
+
+		return ""; //could not rwead
+	}
+
+	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) );
+	String r = ria->recognize(f);
+	return r;
+}
+
+
+void ResourceFormatLoaderText::get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types) {
+
+	FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
+	if (!f) {
+
+		ERR_FAIL();
+	}
+
+	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) );
+	ria->get_dependencies(f,p_dependencies,p_add_types);
+
+
+}
+
+Error ResourceFormatLoaderText::rename_dependencies(const String &p_path,const Map<String,String>& p_map) {
+
+	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) );
+	return ria->rename_dependencies(f,p_path,p_map);
+}
+
+
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+/*****************************************************************************************************/
+
+
 void ResourceFormatSaverTextInstance::write_property(const String& p_name,const Variant& p_property,bool *r_ok) {
 
 	if (r_ok)
@@ -137,11 +901,11 @@ void ResourceFormatSaverTextInstance::write_property(const String& p_name,const
 			Image img=p_property;
 
 			if (img.empty()) {
-				f->store_string("RawImage()");
+				f->store_string("Image()");
 				break;
 			}
 
-			String imgstr="RawImage( ";
+			String imgstr="Image( ";
 			imgstr+=itos(img.get_width());
 			imgstr+=", "+itos(img.get_height());
 			imgstr+=", "+itos(img.get_mipmaps());
@@ -182,10 +946,9 @@ void ResourceFormatSaverTextInstance::write_property(const String& p_name,const
 			const uint8_t *ptr=r.ptr();;
 			for (int i=0;i<len;i++) {
 
-				uint8_t byte = ptr[i];
-				const char  hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-				char str[3]={ hex[byte>>4], hex[byte&0xF], 0};
-				s+=str;
+				if (i>0)
+					s+=", ";
+				s+=itos(ptr[i]);
 			}
 
 			imgstr+=", ";
@@ -215,7 +978,7 @@ void ResourceFormatSaverTextInstance::write_property(const String& p_name,const
 
 			if (external_resources.has(res)) {
 
-				f->store_string("ExtResource( "+itos(external_resources[res]+1)+" )");
+				f->store_string("Resource( "+itos(external_resources[res]+1)+" )");
 			} else {
 
 				if (internal_resources.has(res)) {
@@ -287,7 +1050,7 @@ void ResourceFormatSaverTextInstance::write_property(const String& p_name,const
 
 		case Variant::RAW_ARRAY: {
 
-			f->store_string("RawArray( ");
+			f->store_string("ByteArray( ");
 			String s;
 			DVector<uint8_t> data = p_property;
 			int len = data.size();
@@ -297,10 +1060,8 @@ void ResourceFormatSaverTextInstance::write_property(const String& p_name,const
 
 				if (i>0)
 					f->store_string(", ");
-				uint8_t byte = ptr[i];
-				const char  hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-				char str[3]={ hex[byte>>4], hex[byte&0xF], 0};
-				f->store_string(str);
+
+				f->store_string(itos(ptr[i]));
 
 			}
 

+ 82 - 0
scene/resources/scene_format_text.h

@@ -5,6 +5,88 @@
 #include "io/resource_saver.h"
 #include "os/file_access.h"
 #include "scene/resources/packed_scene.h"
+#include "variant_parser.h"
+
+
+
+class ResourceInteractiveLoaderText : public ResourceInteractiveLoader {
+
+	String local_path;
+	String res_path;
+	String error_text;
+
+	FileAccess *f;
+
+	VariantParser::StreamFile stream;
+
+	struct ExtResource {
+		String path;
+		String type;
+	};
+
+
+	bool is_scene;
+	String res_type;
+
+
+
+//	Map<String,String> remaps;
+
+	Map<int,ExtResource> ext_resources;
+
+	int resources_total;
+	int resource_current;
+	String resource_type;
+
+	VariantParser::Tag next_tag;
+
+	mutable int lines;
+
+	Map<String,String> remaps;
+	void _printerr();
+
+friend class ResourceFormatLoaderText;
+
+	List<RES> resource_cache;
+	Error parse_property(Variant& r_v, String &r_name);
+	Error error;
+
+	RES resource;
+
+public:
+
+	virtual void set_local_path(const String& p_local_path);
+	virtual Ref<Resource> get_resource();
+	virtual Error poll();
+	virtual int get_stage() const;
+	virtual int get_stage_count() const;
+
+	void open(FileAccess *p_f);
+	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);
+
+
+	~ResourceInteractiveLoaderText();
+
+};
+
+
+
+class ResourceFormatLoaderText : public ResourceFormatLoader {
+public:
+
+	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;
+	virtual bool handles_type(const String& p_type) const;
+	virtual String get_resource_type(const String &p_path) const;
+	virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false);
+	virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map);
+
+
+};
+
 
 class ResourceFormatSaverTextInstance  {
 

+ 0 - 1
tools/editor/editor_help.cpp

@@ -1408,7 +1408,6 @@ void EditorHelp::_bind_methods() {
 	ObjectTypeDB::bind_method("_unhandled_key_input",&EditorHelp::_unhandled_key_input);
 	ObjectTypeDB::bind_method("_search",&EditorHelp::_search);
 	ObjectTypeDB::bind_method("_search_cbk",&EditorHelp::_search_cbk);
-
 	ObjectTypeDB::bind_method("_help_callback",&EditorHelp::_help_callback);
 
 	ADD_SIGNAL(MethodInfo("go_to_help"));