summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct11
-rw-r--r--core/variant_call.cpp4
-rw-r--r--core/variant_op.cpp6
-rw-r--r--core/variant_parser.cpp1398
-rw-r--r--core/variant_parser.h100
-rw-r--r--doc/base/classes.xml24
-rw-r--r--drivers/SCsub6
-rw-r--r--drivers/ogg/SCsub3
-rw-r--r--drivers/register_driver_types.cpp17
-rw-r--r--drivers/theora/SCsub36
-rw-r--r--drivers/theora/encint.h1
-rw-r--r--drivers/theora/video_stream_theora.cpp16
-rw-r--r--drivers/vorbis/SCsub4
-rw-r--r--main/main.cpp19
-rw-r--r--platform/android/detect.py1
-rw-r--r--platform/osx/detect.py2
-rw-r--r--platform/windows/SCsub10
-rw-r--r--platform/windows/detect.py2
-rw-r--r--platform/x11/detect.py2
-rw-r--r--scene/gui/video_player.cpp4
-rw-r--r--scene/register_scene_types.cpp7
-rw-r--r--scene/resources/scene_format_text.cpp785
-rw-r--r--scene/resources/scene_format_text.h82
-rw-r--r--tools/editor/editor_help.cpp14
-rw-r--r--tools/editor/editor_help.h3
-rw-r--r--tools/editor/editor_node.cpp30
-rw-r--r--tools/editor/editor_node.h6
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp15
-rw-r--r--tools/editor/project_export.cpp12
-rw-r--r--tools/editor/project_manager.cpp5
-rw-r--r--tools/editor/scene_tree_dock.cpp5
31 files changed, 2519 insertions, 111 deletions
diff --git a/SConstruct b/SConstruct
index 05c53a15fc..46edf06a42 100644
--- a/SConstruct
+++ b/SConstruct
@@ -84,6 +84,9 @@ env_base.__class__.disable_module = methods.disable_module
env_base.__class__.add_source_files = methods.add_source_files
+env_base["x86_opt_gcc"]=False
+env_base["x86_opt_vc"]=False
+
customs = ['custom.py']
profile = ARGUMENTS.get("profile", False)
@@ -106,7 +109,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')
@@ -304,8 +307,12 @@ if selected_platform in platform_list:
if (env['opus']=='yes'):
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']);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 51d683f1fe..48c38f05f9 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -1291,8 +1291,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(STRING,STRING,String,pad_decimals,INT,"digits",varray());
ADDFUNC1(STRING,STRING,String,pad_zeros,INT,"digits",varray());
- ADDFUNC0(STRING,STRING,String,to_ascii,varray());
- ADDFUNC0(STRING,STRING,String,to_utf8,varray());
+ ADDFUNC0(STRING,RAW_ARRAY,String,to_ascii,varray());
+ ADDFUNC0(STRING,RAW_ARRAY,String,to_utf8,varray());
ADDFUNC0(VECTOR2,VECTOR2,Vector2,normalized,varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index eabd647837..1bcfa7d2ae 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -2818,9 +2818,9 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
} break;
case MATRIX32: {
- p_list->push_back( PropertyInfo(Variant::REAL,"x"));
- p_list->push_back( PropertyInfo(Variant::REAL,"y"));
- p_list->push_back( PropertyInfo(Variant::REAL,"o"));
+ p_list->push_back( PropertyInfo(Variant::VECTOR2,"x"));
+ p_list->push_back( PropertyInfo(Variant::VECTOR2,"y"));
+ p_list->push_back( PropertyInfo(Variant::VECTOR2,"o"));
} break;
case PLANE: {
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
new file mode 100644
index 0000000000..2bf9fd7f32
--- /dev/null
+++ b/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);
+
+}
+
+
diff --git a/core/variant_parser.h b/core/variant_parser.h
new file mode 100644
index 0000000000..d4ec6c6cf5
--- /dev/null
+++ b/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
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index a26458a14f..12f9062888 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -12551,7 +12551,7 @@ This approximation makes straight segments between each point, then subdivides t
<description>
Connect to a host. This needs to be done before any requests are sent.
The host should not have http:// prepended but will strip the protocol identifier if provided.
-
+
verify_host will check the SSL identity of the host if set to true.
</description>
</method>
@@ -12576,9 +12576,9 @@ verify_host will check the SSL identity of the host if set to true.
Sends a request to the connected host. The url is the what is normally behind the hostname, i.e:
http://somehost.com/index.php
url would be "index.php"
-
+
Headers are HTTP request headers
-
+
To create a POST request with query strings to push to the server, do:
var fields = {"username" : "user",
"password" : "pass"}
@@ -12693,10 +12693,10 @@ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, qu
</argument>
<description>
Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary.
-
+
var fields = {"username": "user", "password": "pass"}
String queryString = httpClient.query_string_from_dict(fields)
-
+
returns:= "username=user&amp;password=pass"
</description>
</method>
@@ -16735,11 +16735,11 @@ returns:= "username=user&amp;password=pass"
</method>
</methods>
<members>
- <member name="x" type="float">
+ <member name="x" type="Vector2">
</member>
- <member name="y" type="float">
+ <member name="y" type="Vector2">
</member>
- <member name="o" type="float">
+ <member name="o" type="Vector2">
</member>
</members>
<constants>
@@ -26372,12 +26372,14 @@ This method controls whether the position between two cached points is interpola
<return type="String">
</return>
<description>
+ Returns a copy of the array's contents formatted as String. Fast alternative to get_string_from_utf8(), assuming the content is ASCII-only (unlike the UTF-8 function, this function maps every byte to a character in the string, so any multibyte sequence will be torn apart).
</description>
</method>
<method name="get_string_from_utf8">
<return type="String">
</return>
<description>
+ Returns a copy of the array's contents formatted as String, assuming the array is formatted as UTF-8. Slower than get_string_from_ascii(), but works for UTF-8. Usually you should prefer this function over get_string_from_ascii() to support international input.
</description>
</method>
<method name="push_back">
@@ -33134,9 +33136,10 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="to_ascii">
- <return type="String">
+ <return type="RawArray">
</return>
<description>
+ Convert the String (which is a character array) to RawArray (which is an array of bytes). The conversion is speeded up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters.
</description>
</method>
<method name="to_float">
@@ -33168,9 +33171,10 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="to_utf8">
- <return type="String">
+ <return type="RawArray">
</return>
<description>
+ Convert the String (which is an array of characters) to RawArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii().
</description>
</method>
<method name="xml_escape">
diff --git a/drivers/SCsub b/drivers/SCsub
index b94309013a..8e241830f8 100644
--- a/drivers/SCsub
+++ b/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");
diff --git a/drivers/ogg/SCsub b/drivers/ogg/SCsub
index c85d4404f3..3ee1bb6408 100644
--- a/drivers/ogg/SCsub
+++ b/drivers/ogg/SCsub
@@ -6,5 +6,4 @@ ogg_sources = [
"ogg/framing.c",
]
-if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes":
- env.drivers_sources+=ogg_sources
+env.drivers_sources+=ogg_sources
diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp
index c4ab54d102..11c4e7dd29 100644
--- a/drivers/register_driver_types.cpp
+++ b/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"
@@ -108,10 +104,6 @@ static ResourceFormatLoaderAudioStreamSpeex *speex_stream_loader=NULL;
static ResourceFormatLoaderVideoStreamTheora* theora_stream_loader = NULL;
#endif
-#ifdef THEORAPLAYER_ENABLED
-static ResourceFormatLoaderVideoStreamTheoraplayer* theoraplayer_stream_loader = NULL;
-#endif
-
#ifdef MUSEPACK_ENABLED
static ResourceFormatLoaderAudioStreamMPC * mpc_stream_loader=NULL;
#endif
@@ -233,12 +225,6 @@ void register_driver_types() {
ObjectTypeDB::register_type<VideoStreamTheora>();
#endif
-#ifdef THEORAPLAYER_ENABLED
- theoraplayer_stream_loader = memnew( ResourceFormatLoaderVideoStreamTheoraplayer );
- ResourceLoader::add_resource_format_loader(theoraplayer_stream_loader);
- ObjectTypeDB::register_type<VideoStreamTheoraplayer>();
-#endif
-
#ifdef TOOLS_ENABLED
#ifdef SQUISH_ENABLED
@@ -277,9 +263,6 @@ void unregister_driver_types() {
memdelete (theora_stream_loader);
#endif
-#ifdef THEORAPLAYER_ENABLED
- memdelete (theoraplayer_stream_loader);
-#endif
#ifdef MUSEPACK_ENABLED
diff --git a/drivers/theora/SCsub b/drivers/theora/SCsub
index faa1ede6a7..fa85b49804 100644
--- a/drivers/theora/SCsub
+++ b/drivers/theora/SCsub
@@ -31,5 +31,37 @@ sources = [
"theora/video_stream_theora.cpp",
]
-if env['use_theoraplayer_binary'] != "yes":
- env.drivers_sources += sources
+sources_x86 = [
+ "theora/x86/mmxencfrag.c",
+ "theora/x86/mmxfdct.c",
+ "theora/x86/mmxfrag.c",
+ "theora/x86/mmxidct.c",
+ "theora/x86/mmxstate.c",
+ "theora/x86/sse2fdct.c",
+ "theora/x86/x86enc.c",
+ "theora/x86/x86state.c",
+]
+
+sources_x86_vc = [
+ "theora/x86_vc/mmxencfrag.c",
+ "theora/x86_vc/mmxfdct.c",
+ "theora/x86_vc/mmxfrag.c",
+ "theora/x86_vc/mmxidct.c",
+ "theora/x86_vc/mmxstate.c",
+ "theora/x86_vc/x86enc.c",
+ "theora/x86_vc/x86state.c",
+]
+
+env.drivers_sources += sources
+
+if (env["x86_opt_gcc"]):
+ env.Append(CCFLAGS=["-DOC_X86_ASM"])
+ env.drivers_sources += sources_x86
+
+if (env["x86_opt_vc"]):
+ env.Append(CCFLAGS=["-DOC_X86_ASM"])
+ env.drivers_sources += sources_x86_vc
+
+
+
+
diff --git a/drivers/theora/encint.h b/drivers/theora/encint.h
index 97897d5a04..82338256dc 100644
--- a/drivers/theora/encint.h
+++ b/drivers/theora/encint.h
@@ -14,6 +14,7 @@
last mod: $Id: encint.h 16503 2009-08-22 18:14:02Z giles $
********************************************************************/
+
#if !defined(_encint_H)
# define _encint_H (1)
# if defined(HAVE_CONFIG_H)
diff --git a/drivers/theora/video_stream_theora.cpp b/drivers/theora/video_stream_theora.cpp
index ed2565177a..f301bd7515 100644
--- a/drivers/theora/video_stream_theora.cpp
+++ b/drivers/theora/video_stream_theora.cpp
@@ -441,8 +441,10 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
//print_line("play "+rtos(p_delta));
time+=p_delta;
- if (videobuf_time>get_time())
+ if (videobuf_time>get_time()) {
+
return; //no new frames need to be produced
+ }
bool frame_done=false;
bool audio_done=false;
@@ -541,7 +543,7 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
if(ogg_stream_packetout(&to,&op)>0){
- if(pp_inc){
+ if(false && pp_inc){
pp_level+=pp_inc;
th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,
sizeof(pp_level));
@@ -569,16 +571,20 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
keyframing. Soon enough libtheora will be able to deal
with non-keyframe seeks. */
- if(videobuf_time>=get_time())
+ if(videobuf_time>=get_time()) {
frame_done=true;
- else{
+ print_line("frame!");
+ } else{
/*If we are too slow, reduce the pp level.*/
pp_inc=pp_level>0?-1:0;
+ print_line("skip!");
}
}
- } else
+ } else {
+ print_line("no packet..");
break;
+ }
}
if (file && /*!videobuf_ready && */ file->eof_reached()) {
diff --git a/drivers/vorbis/SCsub b/drivers/vorbis/SCsub
index 4a16e80dfc..87805cc2d8 100644
--- a/drivers/vorbis/SCsub
+++ b/drivers/vorbis/SCsub
@@ -33,6 +33,4 @@ sources_lib = [
]
env.drivers_sources += sources
-
-if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes":
- env.drivers_sources += sources_lib
+env.drivers_sources += sources_lib
diff --git a/main/main.cpp b/main/main.cpp
index b6bc10cee7..80a7cbc5fc 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -432,7 +432,6 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
} else if (I->get()=="-e" || I->get()=="-editor") { // fonud editor
editor=true;
- init_maximized=true;
} else if (I->get()=="-nowindow") { // fullscreen
OS::get_singleton()->set_no_window_mode(true);
@@ -649,6 +648,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
if (editor) {
main_args.push_back("-editor");
+ init_maximized=true;
use_custom_res=false;
}
@@ -870,21 +870,14 @@ 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)*/) {
+ print_line("Boot splash path: "+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()) {
@@ -901,7 +894,7 @@ Error Main::setup2() {
} else {
#ifndef NO_DEFAULT_BOOT_LOGO
- MAIN_PRINT("Main: Create botsplash");
+ MAIN_PRINT("Main: Create bootsplash");
Image splash(boot_splash_png);
MAIN_PRINT("Main: ClearColor");
@@ -944,10 +937,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);
}
@@ -1093,7 +1086,7 @@ bool Main::start() {
#endif
- if(script=="" && game_path=="" && !editor && String(GLOBAL_DEF("application/main_scene",""))!="") {
+ if(script=="" && game_path=="" && String(GLOBAL_DEF("application/main_scene",""))!="") {
game_path=GLOBAL_DEF("application/main_scene","");
}
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 9db5d02b48..fe83798c56 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -98,6 +98,7 @@ def configure(env):
if env['android_arch']=='x86':
env['NDK_TARGET']=env['NDK_TARGET_X86']
+ env["x86_opt_gcc"]=True
if env['PLATFORM'] == 'win32':
import methods
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 22cee0527e..f7cf5111f5 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -116,4 +116,4 @@ def configure(env):
env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
#env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
-
+ env["x86_opt_gcc"]=True
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index 1fa793e2de..f98c1b01ff 100644
--- a/platform/windows/SCsub
+++ b/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"])
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index fcde14030f..4ec4b054db 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -263,6 +263,7 @@ def configure(env):
env.Append(CCFLAGS=["/I"+DIRECTX_PATH+"/Include"])
env.Append(LIBPATH=[DIRECTX_PATH+"/Lib/x86"])
env['ENV'] = os.environ;
+ env["x86_opt_vc"]=True
else:
# Workaround for MinGW. See:
@@ -361,6 +362,7 @@ def configure(env):
env['AR'] = mingw_prefix+"ar"
env['RANLIB'] = mingw_prefix+"ranlib"
env['LD'] = mingw_prefix+"g++"
+ env["x86_opt_gcc"]=True
#env['CC'] = "winegcc"
#env['CXX'] = "wineg++"
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 9a52a7c92b..a37005738a 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -180,3 +180,5 @@ def configure(env):
env.Append(CPPFLAGS=['-DNEW_WM_API'])
env.ParseConfig('pkg-config xinerama --cflags --libs')
+ env["x86_opt_gcc"]=True
+
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index 9b9c797ed9..d99da5e906 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "video_player.h"
-
+#include "os/os.h"
int VideoPlayer::InternalStream::get_channel_count() const {
@@ -130,7 +130,7 @@ void VideoPlayer::_notification(int p_notification) {
if (!playback->is_playing())
return;
- double audio_time = AudioServer::get_singleton()->get_mix_time();
+ double audio_time = OS::get_singleton()->get_ticks_usec()/1000000.0; //AudioServer::get_singleton()->get_mix_time();
double delta = last_audio_time==0?0:audio_time-last_audio_time;
last_audio_time=audio_time;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index fe6b192d78..b3a9ab922e 100644
--- a/scene/register_scene_types.cpp
+++ b/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();
}
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index 8403c06ad1..4fc3ece758 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/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]));
}
diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h
index 576a78d183..16260835f8 100644
--- a/scene/resources/scene_format_text.h
+++ b/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 {
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index 321ac76240..1a009214ac 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -36,6 +36,14 @@
#include "os/keyboard.h"
+void EditorHelpSearch::popup() {
+ popup_centered_ratio(0.6);
+ if (search_box->get_text()!="") {
+ search_box->select_all();
+ _update_search();
+ }
+ search_box->grab_focus();
+}
void EditorHelpSearch::popup(const String& p_term) {
@@ -263,7 +271,7 @@ void EditorHelpSearch::_confirmed() {
String mdata=ti->get_metadata(0);
emit_signal("go_to_help",mdata);
- editor->call("_editor_select",3); // in case EditorHelpSearch beeen invoked on top of other editor window
+ editor->call("_editor_select",EditorNode::EDITOR_SCRIPT); // in case EditorHelpSearch beeen invoked on top of other editor window
// go to that
hide();
}
@@ -1049,7 +1057,7 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
void EditorHelp::_request_help(const String& p_string) {
Error err = _goto_desc(p_string);
if (err==OK) {
- editor->call("_editor_select",3);
+ editor->call("_editor_select",EditorNode::EDITOR_SCRIPT);
}
//100 palabras
}
@@ -1350,7 +1358,6 @@ void EditorHelp::_notification(int p_what) {
// forward->set_icon(get_icon("Forward","EditorIcons"));
// back->set_icon(get_icon("Back","EditorIcons"));
_update_doc();
- editor->connect("request_help",this,"_request_help");
} break;
}
@@ -1408,7 +1415,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"));
diff --git a/tools/editor/editor_help.h b/tools/editor/editor_help.h
index b5ee6eca6c..04ac4d35ff 100644
--- a/tools/editor/editor_help.h
+++ b/tools/editor/editor_help.h
@@ -68,7 +68,8 @@ protected:
static void _bind_methods();
public:
- void popup(const String& p_term="");
+ void popup();
+ void popup(const String& p_term);
EditorHelpSearch();
};
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 4e22592880..2db099d9bf 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -167,11 +167,20 @@ void EditorNode::_unhandled_input(const InputEvent& p_event) {
/*case KEY_F1:
if (!p_event.key.mod.shift && !p_event.key.mod.command)
- _editor_select(3);
+ _editor_select(EDITOR_SCRIPT);
break;*/
- case KEY_F1: _editor_select(0); break;
- case KEY_F2: _editor_select(1); break;
- case KEY_F3: _editor_select(2); break;
+ case KEY_F1:
+ if (!p_event.key.mod.shift && !p_event.key.mod.command)
+ _editor_select(EDITOR_2D);
+ break;
+ case KEY_F2:
+ if (!p_event.key.mod.shift && !p_event.key.mod.command)
+ _editor_select(EDITOR_3D);
+ break;
+ case KEY_F3:
+ if (!p_event.key.mod.shift && !p_event.key.mod.command)
+ _editor_select(EDITOR_SCRIPT);
+ break;
case KEY_F5: _menu_option_confirm((p_event.key.mod.control&&p_event.key.mod.shift)?RUN_PLAY_CUSTOM_SCENE:RUN_PLAY,true); break;
case KEY_F6: _menu_option_confirm(RUN_PLAY_SCENE,true); break;
case KEY_F7: _menu_option_confirm(RUN_PAUSE,true); break;
@@ -289,7 +298,7 @@ void EditorNode::_notification(int p_what) {
VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport(),true);
VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(),true);
- _editor_select(1);
+ _editor_select(EDITOR_3D);
if (defer_load_scene!="") {
@@ -879,7 +888,7 @@ void EditorNode::_save_scene_with_preview(String p_file) {
}
}
- _editor_select(is2d?0:1);
+ _editor_select(is2d?EDITOR_2D:EDITOR_3D);
VS::get_singleton()->viewport_queue_screen_capture(viewport);
save.step("Creating Thumbnail",2);
@@ -2519,7 +2528,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
case OBJECT_REQUEST_HELP: {
if (current) {
- _editor_select(3);
+ _editor_select(EDITOR_SCRIPT);
emit_signal("request_help",current->get_type());
}
@@ -3296,9 +3305,9 @@ void EditorNode::_set_main_scene_state(Dictionary p_state) {
int n2d=0,n3d=0;
_find_node_types(get_edited_scene(),n2d,n3d);
if (n2d>n3d) {
- _editor_select(0);
+ _editor_select(EDITOR_2D);
} else if (n3d>n2d) {
- _editor_select(1);
+ _editor_select(EDITOR_3D);
}
}
@@ -3857,7 +3866,8 @@ bool EditorNode::_find_editing_changed_scene(Node *p_from) {
void EditorNode::add_io_error(const String& p_error) {
-
+ CharString err_ut = p_error.utf8();
+ ERR_PRINT(err_ut.get_data());
_load_error_notify(singleton,p_error);
}
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 7d8b97688e..2b91929b94 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -529,6 +529,12 @@ protected:
static void _bind_methods();
public:
+ enum EditorTable {
+ EDITOR_2D = 0,
+ EDITOR_3D,
+ EDITOR_SCRIPT
+ };
+
static EditorNode* get_singleton() { return singleton; }
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 65ed420a51..e01cf72149 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -881,18 +881,17 @@ void ScriptEditor::_menu_option(int p_option) {
} break;
case SEARCH_HELP: {
- help_search_dialog->popup("current");
+ help_search_dialog->popup();
} break;
case SEARCH_CLASSES: {
- if (tab_container->get_tab_count()==0)
- break;
-
String current;
- EditorHelp *eh = tab_container->get_child( tab_container->get_current_tab() )->cast_to<EditorHelp>();
- if (eh) {
- current=eh->get_class_name();
+ if (tab_container->get_tab_count()>0) {
+ EditorHelp *eh = tab_container->get_child( tab_container->get_current_tab() )->cast_to<EditorHelp>();
+ if (eh) {
+ current=eh->get_class_name();
+ }
}
help_index->popup_centered_ratio(0.6);
@@ -1388,6 +1387,7 @@ void ScriptEditor::_notification(int p_what) {
if (p_what==NOTIFICATION_READY) {
get_tree()->connect("tree_changed",this,"_tree_changed");
+ editor->connect("request_help",this,"_request_help");
}
if (p_what==NOTIFICATION_EXIT_TREE) {
@@ -2205,6 +2205,7 @@ void ScriptEditor::_bind_methods() {
ObjectTypeDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged);
ObjectTypeDB::bind_method("_help_class_open",&ScriptEditor::_help_class_open);
ObjectTypeDB::bind_method("_help_class_goto",&ScriptEditor::_help_class_goto);
+ ObjectTypeDB::bind_method("_request_help",&ScriptEditor::_help_class_open);
ObjectTypeDB::bind_method("_history_forward",&ScriptEditor::_history_forward);
ObjectTypeDB::bind_method("_history_back",&ScriptEditor::_history_back);
}
diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp
index cd6dc06f75..3464b3c9bb 100644
--- a/tools/editor/project_export.cpp
+++ b/tools/editor/project_export.cpp
@@ -491,6 +491,18 @@ Error ProjectExportDialog::export_platform(const String& p_platform, const Strin
Ref<EditorExportPlatform> exporter = EditorImportExport::get_singleton()->get_export_platform(p_platform);
if (exporter.is_null()) {
ERR_PRINT("Invalid platform for export");
+
+ List<StringName> platforms;
+ EditorImportExport::get_singleton()->get_export_platforms(&platforms);
+ print_line("Valid export plaftorms are:");
+ for (List<StringName>::Element *E=platforms.front();E;E=E->next())
+ print_line(" \""+E->get()+"\"");
+
+ if (p_quit_after) {
+ OS::get_singleton()->set_exit_code(255);
+ get_tree()->quit();
+ }
+
return ERR_INVALID_PARAMETER;
}
Error err = exporter->export_project(p_path,p_debug);
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index 893df04709..04705017d2 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -624,11 +624,6 @@ void ProjectManager::_open_project_confirm() {
args.push_back("-editor");
- const String &selected_main = E->get();
- if (selected_main!="") {
- args.push_back(selected_main);
- }
-
String exec = OS::get_singleton()->get_executable_path();
OS::ProcessID pid=0;
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index 0cafe7459b..8b5bf8c1e1 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -1264,7 +1264,10 @@ void SceneTreeDock::import_subscene() {
void SceneTreeDock::_import_subscene() {
Node* parent = scene_tree->get_selected();
- ERR_FAIL_COND(!parent);
+ if (!parent) {
+ parent = editor_data->get_edited_scene_root();
+ ERR_FAIL_COND(!parent);
+ }
import_subscene_dialog->move(parent,edited_scene);
editor_data->get_undo_redo().clear_history(); //no undo for now..