diff options
103 files changed, 3124 insertions, 315 deletions
diff --git a/.gitignore b/.gitignore index a7ac2d2fc7..f24d91a7ee 100644 --- a/.gitignore +++ b/.gitignore @@ -296,3 +296,4 @@ cscope.po.out godot.creator.* projects/ +platform/windows/godot_res.res 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/globals.cpp b/core/globals.cpp index ffd4cf5d5e..aee708d0cd 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -332,6 +332,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) { String candidate = d->get_current_dir(); String current_dir = d->get_current_dir(); + String exec_name = OS::get_singleton()->get_executable_path().get_file().basename(); bool found = false; bool first_time=true; @@ -339,7 +340,16 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) { //try to load settings in ascending through dirs shape! //tries to open pack, but only first time - if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) { + if (first_time && (_load_resource_pack(current_dir+"/"+exec_name+".pck") || _load_resource_pack(current_dir+"/"+exec_name+".pcz") )) { + if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) { + + _load_settings("res://override.cfg"); + found=true; + + + } + break; + } else if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) { if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) { _load_settings("res://override.cfg"); diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index 66ae014dbc..48917a19ea 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -1955,7 +1955,6 @@ void ResourceFormatLoaderXML::get_recognized_extensions_for_type(const String& p if (ext=="res") continue; p_extensions->push_back("x"+ext); - p_extensions->push_back(ext); } p_extensions->push_back("xml"); 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/demos/2d/area_input/icon.png b/demos/2d/area_input/icon.png Binary files differindex d9bb881693..2f412ecf68 100644 --- a/demos/2d/area_input/icon.png +++ b/demos/2d/area_input/icon.png diff --git a/demos/2d/dynamic_collision_shapes/icon.png b/demos/2d/dynamic_collision_shapes/icon.png Binary files differindex ac01d401ba..b47506d7c8 100644 --- a/demos/2d/dynamic_collision_shapes/icon.png +++ b/demos/2d/dynamic_collision_shapes/icon.png diff --git a/demos/2d/fog_of_war/icon.png.flags b/demos/2d/fog_of_war/icon.png.flags deleted file mode 100644 index dbef2209e8..0000000000 --- a/demos/2d/fog_of_war/icon.png.flags +++ /dev/null @@ -1 +0,0 @@ -gen_mipmaps=true diff --git a/demos/2d/hdr/icon.png b/demos/2d/hdr/icon.png Binary files differindex 2df0ec38e9..461cd4638a 100644 --- a/demos/2d/hdr/icon.png +++ b/demos/2d/hdr/icon.png diff --git a/demos/2d/isometric_light/icon.png b/demos/2d/isometric_light/icon.png Binary files differindex 3de9749729..0801f78ea5 100644 --- a/demos/2d/isometric_light/icon.png +++ b/demos/2d/isometric_light/icon.png diff --git a/demos/2d/light_mask/icon.png b/demos/2d/light_mask/icon.png Binary files differindex c12b045e62..34a6b709f6 100644 --- a/demos/2d/light_mask/icon.png +++ b/demos/2d/light_mask/icon.png diff --git a/demos/2d/lights_shadows/icon.png b/demos/2d/lights_shadows/icon.png Binary files differindex c7f9e13bae..554f01bb46 100644 --- a/demos/2d/lights_shadows/icon.png +++ b/demos/2d/lights_shadows/icon.png diff --git a/demos/2d/lookat/engine.cfg b/demos/2d/lookat/engine.cfg index 56917a39ec..81df107f0e 100644 --- a/demos/2d/lookat/engine.cfg +++ b/demos/2d/lookat/engine.cfg @@ -2,3 +2,4 @@ name="Look At Pointer" main_scene="res://lookat.scn" +icon="res://icon.png" diff --git a/demos/2d/lookat/icon.png b/demos/2d/lookat/icon.png Binary files differnew file mode 100644 index 0000000000..442cc1799f --- /dev/null +++ b/demos/2d/lookat/icon.png diff --git a/demos/2d/motion/engine.cfg b/demos/2d/motion/engine.cfg index 261111904c..6e660572d6 100644 --- a/demos/2d/motion/engine.cfg +++ b/demos/2d/motion/engine.cfg @@ -2,6 +2,7 @@ name="Motion Test" main_scene="res://motion.scn" +icon="res://icon.png" [display] diff --git a/demos/2d/motion/icon.png b/demos/2d/motion/icon.png Binary files differnew file mode 100644 index 0000000000..9e64961d3c --- /dev/null +++ b/demos/2d/motion/icon.png diff --git a/demos/2d/navpoly/icon.png b/demos/2d/navpoly/icon.png Binary files differindex df7fb43633..7a28a367c6 100644 --- a/demos/2d/navpoly/icon.png +++ b/demos/2d/navpoly/icon.png diff --git a/demos/2d/normalmaps/icon.png b/demos/2d/normalmaps/icon.png Binary files differindex 4e5d835005..11ff5de829 100644 --- a/demos/2d/normalmaps/icon.png +++ b/demos/2d/normalmaps/icon.png diff --git a/demos/2d/polygon_path_finder/engine.cfg b/demos/2d/polygon_path_finder/engine.cfg new file mode 100644 index 0000000000..47450408af --- /dev/null +++ b/demos/2d/polygon_path_finder/engine.cfg @@ -0,0 +1,5 @@ +[application] + +name="Polygon Pathfinder" +main_scene="res://poly_with_holes.scn" +icon="res://icon.png" diff --git a/demos/2d/polygon_path_finder/icon.png b/demos/2d/polygon_path_finder/icon.png Binary files differnew file mode 100644 index 0000000000..643f5595ee --- /dev/null +++ b/demos/2d/polygon_path_finder/icon.png diff --git a/demos/2d/polygon_path_finder/poly_with_holes.scn b/demos/2d/polygon_path_finder/poly_with_holes.scn Binary files differnew file mode 100644 index 0000000000..6b340377b7 --- /dev/null +++ b/demos/2d/polygon_path_finder/poly_with_holes.scn diff --git a/demos/2d/polygon_path_finder_demo/polygonpathfinder.gd b/demos/2d/polygon_path_finder/polygonpathfinder.gd index a0e71dd127..a0e71dd127 100644 --- a/demos/2d/polygon_path_finder_demo/polygonpathfinder.gd +++ b/demos/2d/polygon_path_finder/polygonpathfinder.gd diff --git a/demos/2d/polygon_path_finder_demo/engine.cfg b/demos/2d/polygon_path_finder_demo/engine.cfg deleted file mode 100644 index de5593c417..0000000000 --- a/demos/2d/polygon_path_finder_demo/engine.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[application] - -name="polygon_path_finder_demo" -main_scene="res://new_scene_poly_with_holes.scn" -icon="res://icon.png" diff --git a/demos/2d/polygon_path_finder_demo/icon.png b/demos/2d/polygon_path_finder_demo/icon.png Binary files differdeleted file mode 100644 index 0c422e37b0..0000000000 --- a/demos/2d/polygon_path_finder_demo/icon.png +++ /dev/null diff --git a/demos/2d/polygon_path_finder_demo/icon.png.flags b/demos/2d/polygon_path_finder_demo/icon.png.flags deleted file mode 100644 index dbef2209e8..0000000000 --- a/demos/2d/polygon_path_finder_demo/icon.png.flags +++ /dev/null @@ -1 +0,0 @@ -gen_mipmaps=true diff --git a/demos/2d/polygon_path_finder_demo/new_scene_poly_with_holes.scn b/demos/2d/polygon_path_finder_demo/new_scene_poly_with_holes.scn Binary files differdeleted file mode 100644 index 07838be41e..0000000000 --- a/demos/2d/polygon_path_finder_demo/new_scene_poly_with_holes.scn +++ /dev/null diff --git a/demos/2d/screen_space_shaders/icon.png b/demos/2d/screen_space_shaders/icon.png Binary files differindex 65247f9ae7..e3cc049081 100644 --- a/demos/2d/screen_space_shaders/icon.png +++ b/demos/2d/screen_space_shaders/icon.png diff --git a/demos/2d/sdf_font/icon.png b/demos/2d/sdf_font/icon.png Binary files differindex be9fefa8b0..0c700ad77c 100644 --- a/demos/2d/sdf_font/icon.png +++ b/demos/2d/sdf_font/icon.png diff --git a/demos/2d/splash/icon.png b/demos/2d/splash/icon.png Binary files differindex 88620eb35b..b8e24f209e 100644 --- a/demos/2d/splash/icon.png +++ b/demos/2d/splash/icon.png diff --git a/demos/2d/sprite_shaders/icon.png b/demos/2d/sprite_shaders/icon.png Binary files differindex b044b31f93..8b13ef6bb4 100644 --- a/demos/2d/sprite_shaders/icon.png +++ b/demos/2d/sprite_shaders/icon.png diff --git a/demos/2d/texscreen/engine.cfg b/demos/2d/texscreen/engine.cfg index fb683dfc1d..92d0e98d5b 100644 --- a/demos/2d/texscreen/engine.cfg +++ b/demos/2d/texscreen/engine.cfg @@ -2,6 +2,7 @@ name="Glass Bubbles (Texscreen)" main_scene="res://bubbles.scn" +icon="res://icon.png" [display] diff --git a/demos/2d/texscreen/icon.png b/demos/2d/texscreen/icon.png Binary files differnew file mode 100644 index 0000000000..d74d025ced --- /dev/null +++ b/demos/2d/texscreen/icon.png diff --git a/demos/3d/navmesh/icon.png b/demos/3d/navmesh/icon.png Binary files differindex 5b354f931c..51fef7b2df 100644 --- a/demos/3d/navmesh/icon.png +++ b/demos/3d/navmesh/icon.png diff --git a/demos/3d/sat_test/icon.png b/demos/3d/sat_test/icon.png Binary files differindex b89c5a7467..194456e10f 100644 --- a/demos/3d/sat_test/icon.png +++ b/demos/3d/sat_test/icon.png diff --git a/demos/3d/truck_town/engine.cfg b/demos/3d/truck_town/engine.cfg index 3c340e6dcd..b2a463e1e2 100644 --- a/demos/3d/truck_town/engine.cfg +++ b/demos/3d/truck_town/engine.cfg @@ -2,6 +2,7 @@ name="Truck Town" main_scene="res://car_select.scn" +icon="res://icon.png" [display] diff --git a/demos/3d/truck_town/icon.png b/demos/3d/truck_town/icon.png Binary files differnew file mode 100644 index 0000000000..7d7bd42116 --- /dev/null +++ b/demos/3d/truck_town/icon.png diff --git a/demos/gui/drag_and_drop/engine.cfg b/demos/gui/drag_and_drop/engine.cfg index 448939c61d..49b9b93512 100644 --- a/demos/gui/drag_and_drop/engine.cfg +++ b/demos/gui/drag_and_drop/engine.cfg @@ -2,3 +2,4 @@ name="Drag & Drop (GUI)" main_scene="res://drag_and_drop.scn" +icon="res://icon.png" diff --git a/demos/gui/drag_and_drop/icon.png b/demos/gui/drag_and_drop/icon.png Binary files differnew file mode 100644 index 0000000000..f900d8d4a3 --- /dev/null +++ b/demos/gui/drag_and_drop/icon.png diff --git a/demos/gui/input_mapping/engine.cfg b/demos/gui/input_mapping/engine.cfg index 6470ec6cd8..811635ce25 100644 --- a/demos/gui/input_mapping/engine.cfg +++ b/demos/gui/input_mapping/engine.cfg @@ -2,6 +2,7 @@ name="Input Mapping GUI" main_scene="res://controls.scn" +icon="res://icon.png" [display] diff --git a/demos/gui/input_mapping/icon.png b/demos/gui/input_mapping/icon.png Binary files differnew file mode 100644 index 0000000000..5a1abf4f58 --- /dev/null +++ b/demos/gui/input_mapping/icon.png diff --git a/demos/gui/rich_text_bbcode/icon.png b/demos/gui/rich_text_bbcode/icon.png Binary files differindex 78358ba71b..6db48a3a9b 100644 --- a/demos/gui/rich_text_bbcode/icon.png +++ b/demos/gui/rich_text_bbcode/icon.png diff --git a/demos/gui/translation/engine.cfg b/demos/gui/translation/engine.cfg index 169b65e154..dcd3d1983d 100644 --- a/demos/gui/translation/engine.cfg +++ b/demos/gui/translation/engine.cfg @@ -2,6 +2,7 @@ name="Translation Demo" main_scene="res://main.scn" +icon="res://icon.png" [locale] diff --git a/demos/gui/translation/icon.png b/demos/gui/translation/icon.png Binary files differnew file mode 100644 index 0000000000..4be5ac1127 --- /dev/null +++ b/demos/gui/translation/icon.png diff --git a/demos/misc/instancing/icon.png b/demos/misc/instancing/icon.png Binary files differindex 7a6de677c5..79a4283de7 100644 --- a/demos/misc/instancing/icon.png +++ b/demos/misc/instancing/icon.png diff --git a/demos/misc/regex/engine.cfg b/demos/misc/regex/engine.cfg index 0a6f4f869c..ef5483e096 100644 --- a/demos/misc/regex/engine.cfg +++ b/demos/misc/regex/engine.cfg @@ -2,3 +2,4 @@ name="RegEx" main_scene="res://regex.scn" +icon="res://icon.png" diff --git a/demos/misc/regex/icon.png b/demos/misc/regex/icon.png Binary files differnew file mode 100644 index 0000000000..7a5232ec4b --- /dev/null +++ b/demos/misc/regex/icon.png diff --git a/demos/misc/tween/icon.png b/demos/misc/tween/icon.png Binary files differindex 3e991fcc29..ed55c24140 100644 --- a/demos/misc/tween/icon.png +++ b/demos/misc/tween/icon.png diff --git a/demos/misc/window_management/icon.png b/demos/misc/window_management/icon.png Binary files differindex 0c422e37b0..ec5c7891f9 100644 --- a/demos/misc/window_management/icon.png +++ b/demos/misc/window_management/icon.png diff --git a/demos/misc/window_management/icon.png.flags b/demos/misc/window_management/icon.png.flags deleted file mode 100644 index 5130fd1aab..0000000000 --- a/demos/misc/window_management/icon.png.flags +++ /dev/null @@ -1 +0,0 @@ -gen_mipmaps=false diff --git a/demos/viewport/3d_in_2d/engine.cfg b/demos/viewport/3d_in_2d/engine.cfg index cc893361b5..6d456d7bd4 100644 --- a/demos/viewport/3d_in_2d/engine.cfg +++ b/demos/viewport/3d_in_2d/engine.cfg @@ -2,3 +2,4 @@ name="3D in 2D" main_scene="res://main.scn" +icon="res://icon.png" diff --git a/demos/viewport/3d_in_2d/icon.png b/demos/viewport/3d_in_2d/icon.png Binary files differnew file mode 100644 index 0000000000..d8a332c18f --- /dev/null +++ b/demos/viewport/3d_in_2d/icon.png diff --git a/demos/viewport/gui_in_3d/engine.cfg b/demos/viewport/gui_in_3d/engine.cfg index 25a6636132..252e53ca33 100644 --- a/demos/viewport/gui_in_3d/engine.cfg +++ b/demos/viewport/gui_in_3d/engine.cfg @@ -2,3 +2,4 @@ name="GUI in 3D" main_scene="res://gui_3d.scn" +icon="res://icon.png" diff --git a/demos/viewport/gui_in_3d/icon.png b/demos/viewport/gui_in_3d/icon.png Binary files differnew file mode 100644 index 0000000000..22bdd791bb --- /dev/null +++ b/demos/viewport/gui_in_3d/icon.png diff --git a/demos/viewport/screen_capture/engine.cfg b/demos/viewport/screen_capture/engine.cfg index b25ed8258e..a843242720 100644 --- a/demos/viewport/screen_capture/engine.cfg +++ b/demos/viewport/screen_capture/engine.cfg @@ -2,6 +2,7 @@ name="Screen Capturing" main_scene="res://screen_capture.scn" +icon="res://icon.png" [display] diff --git a/demos/viewport/screen_capture/icon.png b/demos/viewport/screen_capture/icon.png Binary files differnew file mode 100644 index 0000000000..a696824775 --- /dev/null +++ b/demos/viewport/screen_capture/icon.png diff --git a/doc/base/classes.xml b/doc/base/classes.xml index da53cb90a5..12f9062888 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -3197,6 +3197,24 @@ <description> </description> </method> + <method name="set_animation_process_mode"> + <argument index="0" name="mode" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_animation_process_mode" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="advance"> + <argument index="0" name="delta" type="float"> + </argument> + <description> + </description> + </method> <method name="reset"> <description> </description> @@ -4353,7 +4371,7 @@ Stop a given voice. </description> </method> - <method name="free"> + <method name="free_rid"> <argument index="0" name="rid" type="RID"> </argument> <description> @@ -5477,7 +5495,7 @@ </constant> </constants> </class> -<class name="ButtonGroup" inherits="Control" category="Core"> +<class name="ButtonGroup" inherits="BoxContainer" category="Core"> <brief_description> Group of Buttons. </brief_description> @@ -5523,6 +5541,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="panel" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="Camera" inherits="Spatial" category="Core"> <brief_description> @@ -6628,7 +6650,7 @@ <argument index="0" name="radius" type="float"> </argument> <description> - Radius of the [CapsuleShape2D]. + Set the radius of the [CapsuleShape2D]. </description> </method> <method name="get_radius" qualifiers="const"> @@ -6642,7 +6664,7 @@ <argument index="0" name="height" type="float"> </argument> <description> - Height of the [CapsuleShape2D]. + Set the height of the [CapsuleShape2D]. </description> </method> <method name="get_height" qualifiers="const"> @@ -6947,7 +6969,7 @@ Base node for 2D collisionables. </brief_description> <description> - CollisionObject2D is the base class for 2D physics collisionables. They can hold any number of 2D collision shapes. Usually, they are edited by placing CollisionBody2D and CollisionPolygon2D nodes as children. Such nodes are for reference ant not present outside the editor, so code should use the regular shape API. + CollisionObject2D is the base class for 2D physics collisionables. They can hold any number of 2D collision shapes. Usually, they are edited by placing [CollisionBody2D] and [CollisionPolygon2D] nodes as children. Such nodes are for reference and not present outside the editor, so code should use the regular shape API. </description> <methods> <method name="_input_event" qualifiers="virtual"> @@ -7143,58 +7165,69 @@ </class> <class name="CollisionPolygon2D" inherits="Node2D" category="Core"> <brief_description> - Editor-Only class. + Editor-only class for easy editing of collision polygons. </brief_description> <description> - Editor-Only class. This is not present when running the game. It's used in the editor to properly edit and position collision shapes in [CollisionObject2D]. This is not accessible from regular code. This class is for editing custom shape polygons. + Editor-only class. This is not present when running the game. It's used in the editor to properly edit and position collision shapes in [CollisionObject2D]. This is not accessible from regular code. This class is for editing custom shape polygons. </description> <methods> <method name="set_polygon"> <argument index="0" name="polygon" type="Vector2Array"> </argument> <description> + Set the array of points forming the polygon. + When editing the point list via the editor, depending on [method get_build_mode], it has to be a list of points (for [code]build_mode[/code]=0), or a list of lines (for [code]build_mode[/code]=1). In the second case, the even elements of the array define the start point of the line, and the odd elements the end point. </description> </method> <method name="get_polygon" qualifiers="const"> <return type="Vector2Array"> </return> <description> + Return the list of points that define the polygon. </description> </method> <method name="set_build_mode"> <argument index="0" name="arg0" type="int"> </argument> <description> + Set whether the polygon is to be a [ConvexPolygon2D] ([code]build_mode[/code]=0), or a [ConcavePolygon2D] ([code]build_mode[/code]=1). </description> </method> <method name="get_build_mode" qualifiers="const"> <return type="int"> </return> <description> + Return whether the polygon is a [ConvexPolygon2D] ([code]build_mode[/code]=0), or a [ConcavePolygon2D] ([code]build_mode[/code]=1). </description> </method> <method name="set_trigger"> <argument index="0" name="arg0" type="bool"> </argument> <description> + Set whether this polygon is a trigger. A trigger polygon detects collisions, but is otherwise unaffected by physics (i.e. colliding objects will not get blocked). </description> </method> <method name="is_trigger" qualifiers="const"> <return type="bool"> </return> <description> + Return whether this polygon is a trigger. </description> </method> <method name="get_collision_object_first_shape" qualifiers="const"> <return type="int"> </return> <description> + Return the index of the first shape generated by the editor. + When [code]build_mode[/code] is set to generate convex polygons, the shape shown in the editor may be decomopsed into many convex polygons. In that case, a range of indexes is needed to directly access the [Shape2D]s. + When [code]build_mode[/code] is set to generate concave polygons, there is only one [Shape2D] generated, so the start index and the end index are the same. </description> </method> <method name="get_collision_object_last_shape" qualifiers="const"> <return type="int"> </return> <description> + Return the index of the last shape generated by the editor. </description> </method> </methods> @@ -7253,40 +7286,45 @@ </class> <class name="CollisionShape2D" inherits="Node2D" category="Core"> <brief_description> - Editor-Only class. + Editor-only class for easy editing of shapes. </brief_description> <description> - Editor-Only class. This is not present when running the game. It's used in the editor to properly edit and position collision shapes in [CollisionObject2D]. This is not accessible from regular code. + Editor-only class. This is not present when running the game. It's used in the editor to properly edit and position collision shapes in [CollisionObject2D]. This is not accessible from regular code. </description> <methods> <method name="set_shape"> <argument index="0" name="shape" type="Object"> </argument> <description> + Set this shape's [Shape2D]. This will not appear as a node, but can be directly edited as a property. </description> </method> <method name="get_shape" qualifiers="const"> <return type="Object"> </return> <description> + Return this shape's [Shape2D]. </description> </method> <method name="set_trigger"> <argument index="0" name="enable" type="bool"> </argument> <description> + Set whether this shape is a trigger. A trigger shape detects collisions, but is otherwise unaffected by physics (i.e. will not block movement of colliding objects). </description> </method> <method name="is_trigger" qualifiers="const"> <return type="bool"> </return> <description> + Return whether this shape is a trigger. </description> </method> <method name="get_collision_object_shape_index" qualifiers="const"> <return type="int"> </return> <description> + Return the index of this shape inside its container [CollisionObject2D]. This can be used to directly access the underlying [Shape2D]. </description> </method> </methods> @@ -7298,7 +7336,7 @@ Color in RGBA format. </brief_description> <description> - A color is represented as red, green and blue (r,g,b) components. Additionally, "a" represents the alpha component, often used for transparency. Values are in floating point and usually range from 0 to 1. Some methods (such as set_modulate() ) may accept values > 1. + A color is represented as red, green and blue (r,g,b) components. Additionally, "a" represents the alpha component, often used for transparency. Values are in floating point and usually range from 0 to 1. Some methods (such as set_modulate() ) may accept values > 1. </description> <methods> <method name="blend"> @@ -7666,7 +7704,7 @@ Concave polygon shape. </brief_description> <description> - Concave polygon shape resource, which can be set into a [PhysicsBody] or area. This shape is created by feeding a list of triangles. + Concave polygon shape resource, which can be set into a [PhysicsBody] or area. This shape is created by feeding a list of triangles. </description> <methods> <method name="set_faces"> @@ -7693,6 +7731,7 @@ </brief_description> <description> Concave polygon 2D shape resource for physics. It is made out of segments and is very optimal for complex polygonal concave collisions. It is really not advised to use for RigidBody nodes. A CollisionPolygon2D in convex decomposition mode (solids) or several convex objects are advised for that instead. Otherwise, a concave polygon 2D shape is better for static collisions. + The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection. </description> <methods> <method name="set_segments"> @@ -8583,14 +8622,15 @@ Convex Polygon Shape for 2D physics. </brief_description> <description> - Convex Polygon Shape for 2D physics. + Convex Polygon Shape for 2D physics. A convex polygon, whatever its shape, is internally decomposed into as many convex polygons as needed to ensure all collision checks against it are always done on convex polygons (which are faster to check). + The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex in order to speed up collision detection. </description> <methods> <method name="set_point_cloud"> <argument index="0" name="point_cloud" type="Vector2Array"> </argument> <description> - Create the point set from a point cloud. The resulting convex hull will be set as the shape. + Currently, this method does nothing. </description> </method> <method name="set_points"> @@ -8871,12 +8911,12 @@ Cubic interpolation tends to follow the curves better, but linear is faster (and </description> </method> <method name="tesselate" qualifiers="const"> + <return type="Vector2Array"> + </return> <argument index="0" name="max_stages" type="int" default="5"> </argument> <argument index="1" name="tolerance_degrees" type="float" default="4"> </argument> - <return type="Vector2Array"> - </return> <description> Returns a list of points along the curve, with a curvature controlled point density. That is, the curvier parts will have more points than the straighter parts. This approximation makes straight segments between each point, then subdivides those segments until the resulting shape is similar enough. @@ -8884,16 +8924,6 @@ This approximation makes straight segments between each point, then subdivides t "tolerance_degrees" controls how many degrees the midpoint of a segment may deviate from the real curve, before the segment has to be subdivided. </description> </method> - <method name="tesselate" qualifiers="const"> - <return type="Vector2Array"> - </return> - <argument index="0" name="max_stages" type="int" default="5"> - </argument> - <argument index="1" name="tolerance_degrees" type="float" default="4"> - </argument> - <description> - </description> - </method> </methods> <constants> </constants> @@ -9078,12 +9108,12 @@ Cubic interpolation tends to follow the curves better, but linear is faster (and </description> </method> <method name="tesselate" qualifiers="const"> + <return type="Vector3Array"> + </return> <argument index="0" name="max_stages" type="int" default="5"> </argument> <argument index="1" name="tolerance_degrees" type="float" default="4"> </argument> - <return type="Vector3Array"> - </return> <description> Returns a list of points along the curve, with a curvature controlled point density. That is, the curvier parts will have more points than the straighter parts. This approximation makes straight segments between each point, then subdivides those segments until the resulting shape is similar enough. @@ -9091,16 +9121,6 @@ This approximation makes straight segments between each point, then subdivides t "tolerance_degrees" controls how many degrees the midpoint of a segment may deviate from the real curve, before the segment has to be subdivided. </description> </method> - <method name="tesselate" qualifiers="const"> - <return type="Vector3Array"> - </return> - <argument index="0" name="max_stages" type="int" default="5"> - </argument> - <argument index="1" name="tolerance_degrees" type="float" default="4"> - </argument> - <description> - </description> - </method> </methods> <constants> </constants> @@ -10761,6 +10781,14 @@ This approximation makes straight segments between each point, then subdivides t </constant> <constant name="FLAG_DISCARD_ALPHA" value="3"> </constant> + <constant name="LIGHT_SHADER_LAMBERT" value="0"> + </constant> + <constant name="LIGHT_SHADER_WRAP" value="1"> + </constant> + <constant name="LIGHT_SHADER_VELVET" value="2"> + </constant> + <constant name="LIGHT_SHADER_TOON" value="3"> + </constant> </constants> </class> <class name="Font" inherits="Resource" category="Core"> @@ -12521,9 +12549,9 @@ This approximation makes straight segments between each point, then subdivides t <argument index="3" name="verify_host" type="bool" default="true"> </argument> <description> - Connect to a host. This needs to be done before any requests are sent. + 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> @@ -12545,13 +12573,12 @@ verify_host will check the SSL identity of the host if set to true. <argument index="3" name="body" type="String" default=""""> </argument> <description> - Sends a request to the connected host. The url is the what is normally behind the hostname, -i.e; + 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" - +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"} @@ -12566,8 +12593,8 @@ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, qu </return> <argument index="0" name="body" type="String"> </argument> - <description> - Stub function + <description> + Stub function </description> </method> <method name="send_body_data"> @@ -12576,7 +12603,7 @@ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, qu <argument index="0" name="body" type="RawArray"> </argument> <description> - Stub function + Stub function </description> </method> <method name="close"> @@ -12629,14 +12656,14 @@ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, qu <argument index="0" name="bytes" type="int"> </argument> <description> - Sets the size of the buffer used and maximum bytes to read per iteration + Sets the size of the buffer used and maximum bytes to read per iteration </description> </method> <method name="set_blocking_mode"> <argument index="0" name="enabled" type="bool"> </argument> <description> - If set to true, execute will wait until all data is read from the response. + If set to true, execute will wait until all data is read from the response. </description> </method> <method name="is_blocking_mode_enabled" qualifiers="const"> @@ -12649,30 +12676,30 @@ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, qu <return type="int"> </return> <description> - Returns a status string like STATUS_REQUESTING. Need to call [method poll] in order to get status updates. + Returns a status string like STATUS_REQUESTING. Need to call [method poll] in order to get status updates. </description> </method> <method name="poll"> <return type="Error"> </return> - <description> - This needs to be called in order to have any request processed. Check results with [method get_status] + <description> + This needs to be called in order to have any request processed. Check results with [method get_status] </description> </method> - <method name="query_string_from_dict"> - <return type="String"> - </return> - <argument index="0" name="fields" type="Dictionary"> - </argument> - <description> - Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary. - + <method name="query_string_from_dict"> + <return type="String"> + </return> + <argument index="0" name="fields" type="Dictionary"> + </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&password=pass" - </description> - </method> + </description> + </method> </methods> <constants> <constant name="METHOD_GET" value="0"> @@ -14453,6 +14480,12 @@ returns:= "username=user&password=pass" <description> </description> </method> + <method name="get_instance_path" qualifiers="const"> + <return type="String"> + </return> + <description> + </description> + </method> </methods> <constants> </constants> @@ -15902,6 +15935,18 @@ returns:= "username=user&password=pass" LineEdit provides a single line string editor, used for text fields. </description> <methods> + <method name="set_align"> + <argument index="0" name="align" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_align" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> <method name="clear"> <description> Clear the [LineEdit] text. @@ -16015,6 +16060,14 @@ returns:= "username=user&password=pass" </signal> </signals> <constants> + <constant name="ALIGN_LEFT" value="0"> + </constant> + <constant name="ALIGN_CENTER" value="1"> + </constant> + <constant name="ALIGN_RIGHT" value="2"> + </constant> + <constant name="ALIGN_FILL" value="3"> + </constant> </constants> <theme_items> <theme_item name="minimum_spaces" type="int"> @@ -16733,6 +16786,8 @@ returns:= "username=user&password=pass" </theme_item> <theme_item name="pressed" type="StyleBox"> </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> <theme_item name="disabled" type="StyleBox"> </theme_item> <theme_item name="normal" type="StyleBox"> @@ -18584,6 +18639,18 @@ returns:= "username=user&password=pass" Replace a node in a scene by a given one. Subscriptions that pass through this node will be lost. </description> </method> + <method name="set_scene_instance_load_placeholder"> + <argument index="0" name="load_placeholder" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_scene_instance_load_placeholder" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> <method name="get_viewport" qualifiers="const"> <return type="Object"> </return> @@ -21573,16 +21640,16 @@ This method controls whether the position between two cached points is interpola </methods> <constants> <constant name="ROTATION_NONE" value="0"> - Forbids the PathFollow to rotate. + Forbids the PathFollow to rotate. </constant> <constant name="ROTATION_Y" value="1"> - Allows the PathFollow to rotate in the Y axis only. + Allows the PathFollow to rotate in the Y axis only. </constant> <constant name="ROTATION_XY" value="2"> - Allows the PathFollow to rotate in both the X, and Y axes. + Allows the PathFollow to rotate in both the X, and Y axes. </constant> <constant name="ROTATION_XYZ" value="3"> - Allows the PathFollow to rotate in any axis. + Allows the PathFollow to rotate in any axis. </constant> </constants> </class> @@ -21697,10 +21764,6 @@ This method controls whether the position between two cached points is interpola </description> </method> </methods> - <members> - <member name="lookahead" type="float"> - </member> - </members> <constants> </constants> </class> @@ -26057,6 +26120,14 @@ This method controls whether the position between two cached points is interpola <description> </description> </method> + <method name="xform"> + <return type="Vector3"> + </return> + <argument index="0" name="v" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="Quat"> <return type="Quat"> </return> @@ -26301,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"> @@ -26584,19 +26657,21 @@ This method controls whether the position between two cached points is interpola Ray 2D shape resource for physics. </brief_description> <description> - Ray 2D shape resource for physics. A ray is not really a collision body, isntead it tries to separate itself from whatever is touching its far endpoint. It's often useful for ccharacters. + Ray 2D shape resource for physics. A ray is not really a collision body, isntead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. </description> <methods> <method name="set_length"> <argument index="0" name="length" type="float"> </argument> <description> + Set the length of the ray. </description> </method> <method name="get_length" qualifiers="const"> <return type="float"> </return> <description> + Return the length of the ray. </description> </method> </methods> @@ -26866,27 +26941,22 @@ This method controls whether the position between two cached points is interpola <methods> <method name="compile"> <return type="int"> - [OK] if the regular expression was valid. [FAIL] otherwise. </return> <argument index="0" name="pattern" type="String"> - The string to be converted into a regular expression. + </argument> + <argument index="1" name="expanded" type="bool" default="true"> </argument> <description> - Once created, a RegEx object needs a regular expression to be assigned to it. This method tries to convert the string given to an usable regular expression. </description> </method> <method name="find" qualifiers="const"> <return type="int"> - The position within the string (starting with 0) where the pattern was found. It will return -1 if the pattern was not found, it was invalid, or the start or end positions were beyond the string's end. </return> <argument index="0" name="text" type="String"> - The text to search the pattern in. </argument> <argument index="1" name="start" type="int" default="0"> - The position in the string (starting with 0) to start searching from. </argument> <argument index="2" name="end" type="int" default="-1"> - The position in the string (starting with 0) to stop searching. A value less than the start position means "end of the string". </argument> <description> This method tries to find the pattern within the string, and returns the position where it was found. It also stores any capturing group (see [method get_capture]) for further retrieval. @@ -26915,7 +26985,6 @@ This method controls whether the position between two cached points is interpola <return type="String"> </return> <argument index="0" name="capture" type="int"> - The number of the captured group, starting with 0. Like other regular expression engines, Godot's engine takes 0 as the full expression, and 1 as the first pair of capturing parentheses. </argument> <description> Returns a captured group. A captured group is the part of a string that matches a part of the pattern delimited by parentheses (unless they are non-capturing parentheses [i](?:)[/i]). @@ -26923,7 +26992,6 @@ This method controls whether the position between two cached points is interpola </method> <method name="get_captures" qualifiers="const"> <return type="StringArray"> - A list contining all the strings captured by the regular expression. </return> <description> Return a list of all the captures made by the regular expression. @@ -29543,24 +29611,28 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="a" type="Vector2"> </argument> <description> + Set the first point's position. </description> </method> <method name="get_a" qualifiers="const"> <return type="Vector2"> </return> <description> + Return the first point's position. </description> </method> <method name="set_b"> <argument index="0" name="b" type="Vector2"> </argument> <description> + Set the second point's position. </description> </method> <method name="get_b" qualifiers="const"> <return type="Vector2"> </return> <description> + Return the second point's position. </description> </method> </methods> @@ -30608,13 +30680,14 @@ This method controls whether the position between two cached points is interpola </argument> <description> Use a custom solver bias. No need to change this unless you really know what you are doing. + The solver bias is a factor controlling how much two objects "rebound" off each other, when colliding, to avoid them getting into each other because of numerical imprecision. </description> </method> <method name="get_custom_solver_bias" qualifiers="const"> <return type="float"> </return> <description> - Return the custom solver bias. No need to change this unless you really know what you are doing. + Return the custom solver bias. </description> </method> <method name="collide"> @@ -30627,6 +30700,8 @@ This method controls whether the position between two cached points is interpola <argument index="2" name="shape_xform" type="Matrix32"> </argument> <description> + Return whether this shape is colliding with another. + This method needs the transformation matrix for this shape ([code]local_xform[/code]), the shape to check collisions with ([code]with_shape[/code]), and the transformation matrix of that shape ([code]shape_xform[/code]). </description> </method> <method name="collide_with_motion"> @@ -30643,6 +30718,8 @@ This method controls whether the position between two cached points is interpola <argument index="4" name="shape_motion" type="Vector2"> </argument> <description> + Return whether this shape would collide with another, if a given movemen was applied. + This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test ont the other object ([code]shape_motion[/code]). </description> </method> <method name="collide_and_get_contacts"> @@ -30653,6 +30730,8 @@ This method controls whether the position between two cached points is interpola <argument index="2" name="shape_xform" type="Matrix32"> </argument> <description> + Return a list of the points where this shape touches another. If there are no collisions, the list is empty. + This method needs the transformation matrix for this shape ([code]local_xform[/code]), the shape to check collisions with ([code]with_shape[/code]), and the transformation matrix of that shape ([code]shape_xform[/code]). </description> </method> <method name="collide_with_motion_and_get_contacts"> @@ -30667,6 +30746,8 @@ This method controls whether the position between two cached points is interpola <argument index="4" name="shape_motion" type="Vector2"> </argument> <description> + Return a list of the points where this shape would touch another, if a given movement was applied. If there are no collisions, the list is empty. + This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test ont the other object ([code]shape_motion[/code]). </description> </method> </methods> @@ -33055,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"> @@ -33089,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"> @@ -33988,15 +34071,17 @@ This method controls whether the position between two cached points is interpola <method name="cursor_set_column"> <argument index="0" name="column" type="int"> </argument> + <argument index="1" name="arg1" type="bool"> + </argument> <description> - Set the current column of the text editor. </description> </method> <method name="cursor_set_line"> <argument index="0" name="line" type="int"> </argument> + <argument index="1" name="arg1" type="bool"> + </argument> <description> - Set the current line of the text editor. </description> </method> <method name="cursor_get_column" qualifiers="const"> @@ -36252,6 +36337,18 @@ This method controls whether the position between two cached points is interpola <description> </description> </method> + <method name="set_hide_folding"> + <argument index="0" name="hide" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_folding_hidden" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> </methods> <signals> <signal name="item_activated"> @@ -37404,6 +37501,14 @@ This method controls whether the position between two cached points is interpola <description> </description> <methods> + <method name="angle"> + <return type="float"> + </return> + <description> + Returns the result of atan2 when called with the Vector's x and y as parameters (Math::atan2(x,y)). + Be aware that it therefore returns an angle oriented clockwise with regard to the (0, 1) unit vector, and not an angle oriented counter-clockwise with regard to the (1, 0) unit vector (which would be the typical trigonometric representation of the angle when calling Math::atan2(y,x)). + </description> + </method> <method name="angle_to"> <return type="float"> </return> @@ -37422,13 +37527,6 @@ This method controls whether the position between two cached points is interpola Returns the angle in radians between the line connecting the two points and the x coordinate. </description> </method> - <method name="atan2"> - <return type="float"> - </return> - <description> - Returns the result of atan2 when called with the Vector's x and y as parameters. - </description> - </method> <method name="cubic_interpolate"> <return type="Vector2"> </return> @@ -37529,7 +37627,7 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="vec" type="Vector2"> </argument> <description> - Reflects/mirrors the vector around another vector. + Like "slide", but reflects the Vector instead of continuing along the wall. </description> </method> <method name="rotated"> @@ -37593,10 +37691,10 @@ This method controls whether the position between two cached points is interpola </class> <class name="Vector2Array" category="Built-In Types"> <brief_description> - An Array of Vector2's. + An Array of Vector2. </brief_description> <description> - An Array specifically designed to hold Vector2's. + An Array specifically designed to hold Vector2. </description> <methods> <method name="get"> @@ -37605,21 +37703,21 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="idx" type="int"> </argument> <description> - Get the Vector2 at the given index. + Returns the Vector2 at the given index. </description> </method> <method name="push_back"> <argument index="0" name="vector2" type="Vector2"> </argument> <description> - Insert a new Vector2. + Inserts a Vector2 at the end. </description> </method> <method name="resize"> <argument index="0" name="idx" type="int"> </argument> <description> - Set the size of the Vector2Array. If larger than the current size it will reserve some space beforehand, and if it is smaller it will cut off the array. + Sets the size of the Vector2Array. If larger than the current size it will reserve some space beforehand, and if it is smaller it will cut off the array. </description> </method> <method name="set"> @@ -37628,7 +37726,7 @@ This method controls whether the position between two cached points is interpola <argument index="1" name="vector2" type="Vector2"> </argument> <description> - Set the Vector2 at the given index. + Changes the Vector2 at the given index. </description> </method> <method name="size"> @@ -37663,12 +37761,14 @@ This method controls whether the position between two cached points is interpola <return type="Vector3"> </return> <description> + Returns a new vector with all components in absolute values (e.g. positive). </description> </method> <method name="ceil"> <return type="Vector3"> </return> <description> + Returns a new vector with all components rounded up. </description> </method> <method name="cross"> @@ -37692,7 +37792,7 @@ This method controls whether the position between two cached points is interpola <argument index="3" name="t" type="float"> </argument> <description> - Perform a cubic interpolation between vectors a,b,c,d (b is current), by the given amount (i). + Perform a cubic interpolation between vectors pre_a, a, b, post_b (a is current), by the given amount (t). </description> </method> <method name="distance_squared_to"> @@ -37701,7 +37801,7 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="b" type="Vector3"> </argument> <description> - Return the squared distance (distance minus the last square root) to b. + Return the squared distance (distance minus the last square root) to b. Prefer this function over distance_to if you need to sort vectors or need the squared distance for some formula. </description> </method> <method name="distance_to"> @@ -37726,13 +37826,14 @@ This method controls whether the position between two cached points is interpola <return type="Vector3"> </return> <description> + Returns a new vector with all components rounded down. </description> </method> <method name="inverse"> <return type="Vector3"> </return> <description> - Returns the inverse of the vector. this is the same as Vector3( 1.0 / v.x, 1.0 / v.y, 1.0 / v.z ) + Returns the inverse of the vector. This is the same as Vector3( 1.0 / v.x, 1.0 / v.y, 1.0 / v.z ) </description> </method> <method name="length"> @@ -37746,7 +37847,7 @@ This method controls whether the position between two cached points is interpola <return type="float"> </return> <description> - Return the length of the vector, squared. + Return the length of the vector, squared. Prefer this function over "length" if you need to sort vectors or need the squared length for some formula. </description> </method> <method name="linear_interpolate"> @@ -37757,26 +37858,28 @@ This method controls whether the position between two cached points is interpola <argument index="1" name="t" type="float"> </argument> <description> - Linearly interpolates the vector to a given one (b), by the given amount (i). + Linearly interpolates the vector to a given one (b), by the given amount (t). </description> </method> <method name="max_axis"> <return type="int"> </return> <description> + Returns AXIS_X, AXIS_Y or AXIS_Z depending on which axis is the largest. </description> </method> <method name="min_axis"> <return type="int"> </return> <description> + Returns AXIS_X, AXIS_Y or AXIS_Z depending on which axis is the smallest. </description> </method> <method name="normalized"> <return type="Vector3"> </return> <description> - Return a copy of the normalized vector to unit length. This is the same as v / v.length() + Return a copy of the normalized vector to unit length. This is the same as v / v.length(). </description> </method> <method name="reflect"> @@ -37785,6 +37888,7 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="by" type="Vector3"> </argument> <description> + Like "slide", but reflects the Vector instead of continuing along the wall. </description> </method> <method name="rotated"> @@ -37795,6 +37899,7 @@ This method controls whether the position between two cached points is interpola <argument index="1" name="phi" type="float"> </argument> <description> + Rotates the vector around some axis by phi radians. </description> </method> <method name="slide"> @@ -37803,6 +37908,7 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="by" type="Vector3"> </argument> <description> + Slides the vector along a wall. </description> </method> <method name="snapped"> @@ -37824,6 +37930,7 @@ This method controls whether the position between two cached points is interpola <argument index="2" name="z" type="float"> </argument> <description> + Returns a Vector3 with the given components. </description> </method> </methods> @@ -37837,17 +37944,22 @@ This method controls whether the position between two cached points is interpola </members> <constants> <constant name="AXIS_X" value="0"> + Enumerated value for the X axis. Returned by functions like max_axis or min_axis. </constant> <constant name="AXIS_Y" value="1"> + Enumerated value for the Y axis. </constant> <constant name="AXIS_Z" value="2"> + Enumerated value for the Z axis. </constant> </constants> </class> <class name="Vector3Array" category="Built-In Types"> <brief_description> + An Array of Vector3. </brief_description> <description> + An Array specifically designed to hold Vector3. </description> <methods> <method name="get"> @@ -37856,18 +37968,21 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="idx" type="int"> </argument> <description> + Returns the Vector3 at the given index. </description> </method> <method name="push_back"> <argument index="0" name="vector3" type="Vector3"> </argument> <description> + Inserts a Vector3 at the end. </description> </method> <method name="resize"> <argument index="0" name="idx" type="int"> </argument> <description> + Sets the size of the Vector3Array. If larger than the current size it will reserve some space beforehand, and if it is smaller it will cut off the array. </description> </method> <method name="set"> @@ -37876,12 +37991,14 @@ This method controls whether the position between two cached points is interpola <argument index="1" name="vector3" type="Vector3"> </argument> <description> + Changes the Vector3 at the given index. </description> </method> <method name="size"> <return type="int"> </return> <description> + Returns the size of the array. </description> </method> <method name="Vector3Array"> @@ -37890,6 +38007,7 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="from" type="Array"> </argument> <description> + Constructs a new Vector3Array. Optionally, you can pass in an Array that will be converted. </description> </method> </methods> diff --git a/doc/core_classes.xml b/doc/core_classes.xml index 02b46ac4b9..c37b50f122 100644 --- a/doc/core_classes.xml +++ b/doc/core_classes.xml @@ -575,8 +575,8 @@ 3x3 Matrix. </brief_description> <description> - </description> Matrix represent a 3x3 (3 rows by 3 columns) transformation matrix. it is used mainly to represent and accumulate transformations such as rotation or scale when used as an OCS (oriented coordinate system). + </description> <methods> <method name="invert"> <description> @@ -937,8 +937,8 @@ Vector used for 2D Math. </brief_description> <description> - </description> Vector class, which performs basic 2D vector math operations. + </description> <methods> <method name="operator+"> <argument index="0" name="b" type="Vector2"> diff --git a/doc/engine_classes.xml b/doc/engine_classes.xml index af153a16ef..43602e26e9 100644 --- a/doc/engine_classes.xml +++ b/doc/engine_classes.xml @@ -1502,7 +1502,7 @@ <description> </description> </method> - <method name="free"> + <method name="free_rid"> <argument index="0" name="rid" type="RID"> </argument> <description> 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/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index b473e8493f..39b448d6e0 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -4641,6 +4641,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (light_flags.uses_light) { enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); } + if (light_flags.uses_shadow_color) { + enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n"); + } if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { enablers.push_back("#define USE_TIME\n"); uses_time=true; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index c8f59ce22b..f981529ee3 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -221,6 +221,10 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a uses_light=true; } + if (vnode->name==vname_shadow) { + uses_shadow_color=true; + } + } if (type==ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX) { @@ -783,13 +787,14 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { replace_table["texscreen"]= "texscreen"; replace_table["texpos"]= "texpos"; - mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["POSITION"] = "gl_Position"; + mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_VERTEX"] = "vertex_in.xyz"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_NORMAL"] = "normal_in"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_TANGENT"]="tangent_in"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_BINORMALF"]="binormalf"; - + + mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["POSITION"] = "gl_Position"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["VERTEX"]="vertex_interp"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["NORMAL"]="normal_interp"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["TANGENT"]="tangent_interp"; @@ -858,6 +863,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT"]="light"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["POINT_COORD"]="gl_PointCoord"; mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["TIME"]="time"; + mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SHADOW"]="shadow_color"; mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["SRC_VERTEX"]="src_vtx"; mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["VERTEX"]="outvec.xy"; diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index 38fb03ab5c..ccd80bf2f0 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -1175,6 +1175,10 @@ FRAGMENT_SHADER_CODE vec3 mdiffuse = diffuse.rgb; vec3 light; +#if defined(USE_LIGHT_SHADOW_COLOR) + vec3 shadow_color=vec3(0.0,0.0,0.0); +#endif + #if defined(USE_LIGHT_SHADER_CODE) //light is written by the light shader { @@ -1195,6 +1199,10 @@ LIGHT_SHADER_CODE #endif diffuse.rgb = const_light_mult * ambient_light *diffuse.rgb + light * attenuation * shadow_attenuation; +#if defined(USE_LIGHT_SHADOW_COLOR) + diffuse.rgb += light * shadow_color * attenuation * (1.0 - shadow_attenuation); +#endif + #ifdef USE_FOG diffuse.rgb = mix(diffuse.rgb,fog_interp.rgb,fog_interp.a); 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/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/com/android/godot/GodotView.java index ad0354e624..1a84923065 100644 --- a/platform/android/java/src/com/android/godot/GodotView.java +++ b/platform/android/java/src/com/android/godot/GodotView.java @@ -371,8 +371,8 @@ public class GodotView extends GLSurfaceView { if (use_32) { setEGLConfigChooser( translucent ? - new ConfigChooser(8, 8, 8, 8, 24, stencil) : - new ConfigChooser(8, 8, 8, 8, 24, stencil) ); + new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(8, 8, 8, 8, 16, stencil)) : + new FallbackConfigChooser(8, 8, 8, 8, 24, stencil, new ConfigChooser(5, 6, 5, 0, 16, stencil)) ); } else { setEGLConfigChooser( translucent ? @@ -410,6 +410,25 @@ public class GodotView extends GLSurfaceView { Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error)); } } + /* Fallback if 32bit View is not supported*/ + private static class FallbackConfigChooser extends ConfigChooser { + private ConfigChooser fallback; + + public FallbackConfigChooser(int r, int g, int b, int a, int depth, int stencil, ConfigChooser fallback) { + super(r, g, b, a, depth, stencil); + this.fallback = fallback; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { + EGLConfig ec = super.chooseConfig(egl, display, configs); + if (ec == null) { + Log.w(TAG, "Trying ConfigChooser fallback"); + ec = fallback.chooseConfig(egl, display, configs); + } + return ec; + } + } private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser { 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/dialogs.cpp b/scene/gui/dialogs.cpp index 0c0f924f52..efda8a66e1 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -308,7 +308,9 @@ void AcceptDialog::_bind_methods() { ADD_SIGNAL( MethodInfo("confirmed") ); ADD_SIGNAL( MethodInfo("custom_action",PropertyInfo(Variant::STRING,"action")) ); - + ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"dialog/text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_text"),_SCS("get_text")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "dialog/hide_on_ok"),_SCS("set_hide_on_ok"),_SCS("get_hide_on_ok") ); + } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 99663fb2e2..20f28ecf10 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -170,7 +170,14 @@ void PopupMenu::_activate_submenu(int over) { Point2 p = get_global_pos(); Rect2 pr(p,get_size()); Ref<StyleBox> style = get_stylebox("panel"); - pm->set_pos(p+Point2(get_size().width,items[over]._ofs_cache-style->get_offset().y)); + + Point2 pos = p+Point2(get_size().width,items[over]._ofs_cache-style->get_offset().y); + Size2 size = pm->get_size(); + // fix pos + if (pos.x+size.width > get_viewport_rect().size.width) + pos.x=p.x-size.width; + + pm->set_pos(pos); pm->popup(); PopupMenu *pum = pm->cast_to<PopupMenu>(); 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/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index d5204f45d5..7b67eaeda8 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -1435,6 +1435,7 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ {MODE_MATERIAL,SHADER_TYPE_LIGHT,"ShadeParam","SHADE_PARAM","",SLOT_TYPE_SCALAR,SLOT_IN}, //light out {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Light","LIGHT","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Shadow", "SHADOW", "",SLOT_TYPE_VEC, SLOT_OUT }, //canvas item vertex in {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Vertex","vec3(SRC_VERTEX,0)","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"UV","SRC_UV","",SLOT_TYPE_VEC,SLOT_IN}, diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index c155f5204a..6c5a2de97b 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -132,7 +132,7 @@ void AudioServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("voice_stop","voice"), &AudioServer::voice_stop ); - ObjectTypeDB::bind_method(_MD("free","rid"), &AudioServer::free ); + ObjectTypeDB::bind_method(_MD("free_rid","rid"), &AudioServer::free ); ObjectTypeDB::bind_method(_MD("set_stream_global_volume_scale","scale"), &AudioServer::set_stream_global_volume_scale ); ObjectTypeDB::bind_method(_MD("get_stream_global_volume_scale"), &AudioServer::get_stream_global_volume_scale ); diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 6532c3f0ac..6c5f64edd9 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1113,7 +1113,8 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={ { "SPECULAR_EXP", TYPE_FLOAT}, { "SHADE_PARAM", TYPE_FLOAT}, { "LIGHT", TYPE_VEC3}, - { "POINT_COORD", TYPE_VEC2}, + { "SHADOW", TYPE_VEC3 }, + { "POINT_COORD", TYPE_VEC2 }, // { "SCREEN_POS", TYPE_VEC2}, // { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, { "TIME", TYPE_FLOAT}, diff --git a/tools/editor/connections_dialog.cpp b/tools/editor/connections_dialog.cpp index b0bacdae61..d4937d7114 100644 --- a/tools/editor/connections_dialog.cpp +++ b/tools/editor/connections_dialog.cpp @@ -163,6 +163,7 @@ void ConnectDialog::edit(Node *p_node) { dst_path->set_text(""); dst_method->set_text(""); deferred->set_pressed(false); + oneshot->set_pressed(false); cdbinds->params.clear(); cdbinds->notify_changed(); } @@ -196,6 +197,11 @@ bool ConnectDialog::get_deferred() const { return deferred->is_pressed(); } +bool ConnectDialog::get_oneshot() const { + + return oneshot->is_pressed(); +} + StringName ConnectDialog::get_dst_method() const { String txt=dst_method->get_text(); @@ -423,12 +429,13 @@ ConnectDialog::ConnectDialog() { dstm_hb->add_child(make_callback); deferred = memnew( CheckButton ); - deferred->set_toggle_mode(true); - deferred->set_pressed(true); deferred->set_text("Deferred"); dstm_hb->add_child(deferred); - + oneshot = memnew( CheckButton ); + oneshot->set_text("Oneshot"); + dstm_hb->add_child(oneshot); + /* realtime = memnew( CheckButton ); realtime->set_anchor( MARGIN_TOP, ANCHOR_END ); @@ -496,11 +503,13 @@ void ConnectionsDialog::_connect() { StringName dst_method=connect_dialog->get_dst_method(); bool defer=connect_dialog->get_deferred(); + bool oshot=connect_dialog->get_oneshot(); Vector<Variant> binds = connect_dialog->get_binds(); StringArray args = it->get_metadata(0).operator Dictionary()["args"]; + int flags = CONNECT_PERSIST | (defer?CONNECT_DEFERRED:0) | (oshot?CONNECT_ONESHOT:0); undo_redo->create_action("Connect '"+signal+"' to '"+String(dst_method)+"'"); - undo_redo->add_do_method(node,"connect",signal,target,dst_method,binds,CONNECT_PERSIST | (defer?CONNECT_DEFERRED:0)); + undo_redo->add_do_method(node,"connect",signal,target,dst_method,binds,flags); undo_redo->add_undo_method(node,"disconnect",signal,target,dst_method); undo_redo->add_do_method(this,"update_tree"); undo_redo->add_undo_method(this,"update_tree"); @@ -731,6 +740,8 @@ void ConnectionsDialog::update_tree() { String path = String(node->get_path_to(target))+" :: "+c.method+"()"; if (c.flags&CONNECT_DEFERRED) path+=" (deferred)"; + if (c.flags&CONNECT_ONESHOT) + path+=" (oneshot)"; if (c.binds.size()) { path+=" binds( "; diff --git a/tools/editor/connections_dialog.h b/tools/editor/connections_dialog.h index 68b13bf07a..4a1c3f189c 100644 --- a/tools/editor/connections_dialog.h +++ b/tools/editor/connections_dialog.h @@ -58,6 +58,7 @@ class ConnectDialog : public ConfirmationDialog { //MenuButton *dst_method_list; OptionButton *type_list; CheckButton *deferred; + CheckButton *oneshot; CheckButton *make_callback; PropertyEditor *bind_editor; Node *node; @@ -80,6 +81,7 @@ public: NodePath get_dst_path() const; StringName get_dst_method() const; bool get_deferred() const; + bool get_oneshot() const; Vector<Variant> get_binds() const; void set_dst_method(const StringName& p_method); void set_dst_node(Node* p_node); 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 22acfd4d07..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); @@ -2012,6 +2021,11 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } break; + case SCENE_TAB_CLOSE: { + _remove_scene(tab_closing); + _update_scene_tabs(); + current_option = -1; + } break; case FILE_SAVE_SCENE: { @@ -2023,7 +2037,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { return; }; // fallthrough to save_as - }; + } break; case FILE_SAVE_AS_SCENE: { Node *scene = editor_data.get_edited_scene_root(); @@ -2514,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()); } @@ -2957,23 +2971,23 @@ void EditorNode::_remove_edited_scene() { _update_title(); _update_scene_tabs(); - if (editor_data.get_edited_scene_count()==1) { - //make new scene appear saved - set_current_version(editor_data.get_undo_redo().get_version()); - unsaved_cache=false; - } +// if (editor_data.get_edited_scene_count()==1) { +// //make new scene appear saved +// set_current_version(editor_data.get_undo_redo().get_version()); +// unsaved_cache=false; +// } } void EditorNode::_remove_scene(int index) { // printf("Attempting to remove scene %d (current is %d)\n", index, editor_data.get_edited_scene()); + if (editor_data.get_edited_scene() == index) { //Scene to remove is current scene _remove_edited_scene(); } else { - // Scene to remove is not active scene."); + // Scene to remove is not active scene editor_data.remove_scene(index); - editor_data.get_undo_redo().clear_history(); } } @@ -3291,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); } } @@ -3852,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); } @@ -4019,6 +4034,8 @@ void EditorNode::_bind_methods() { ObjectTypeDB::bind_method("_prepare_history",&EditorNode::_prepare_history); ObjectTypeDB::bind_method("_select_history",&EditorNode::_select_history); + ObjectTypeDB::bind_method("_toggle_search_bar",&EditorNode::_toggle_search_bar); + ObjectTypeDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box); ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin); ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin); @@ -4467,8 +4484,19 @@ void EditorNode::_scene_tab_script_edited(int p_tab) { } void EditorNode::_scene_tab_closed(int p_tab) { - _remove_scene(p_tab); - _update_scene_tabs(); + current_option = SCENE_TAB_CLOSE; + tab_closing = p_tab; + if (unsaved_cache) { + confirmation->get_ok()->set_text("Yes"); + //confirmation->get_cancel()->show(); + confirmation->set_text("Close scene? (Unsaved changes will be lost)"); + confirmation->popup_centered_minsize(); + } + else { + _remove_scene(p_tab); + //_update_scene_tabs(); + } + } @@ -4501,6 +4529,30 @@ void EditorNode::_scene_tab_changed(int p_tab) { } +void EditorNode::_toggle_search_bar(bool p_pressed) { + + property_editor->set_use_filter(p_pressed); + + if (p_pressed) { + + search_bar->show(); + search_box->grab_focus(); + search_box->select_all(); + } else { + + search_bar->hide(); + } +} + +void EditorNode::_clear_search_box() { + + if (search_box->get_text()=="") + return; + + search_box->clear(); + property_editor->update_tree(); +} + EditorNode::EditorNode() { EditorHelp::generate_doc(); //before any editor classes are crated @@ -5306,6 +5358,12 @@ EditorNode::EditorNode() { editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); prop_editor_hb->add_child(editor_path); + search_button = memnew( ToolButton ); + search_button->set_toggle_mode(true); + search_button->set_pressed(false); + search_button->set_icon(gui_base->get_icon("Zoom","EditorIcons")); + prop_editor_hb->add_child(search_button); + search_button->connect("toggled",this,"_toggle_search_bar"); object_menu = memnew( MenuButton ); object_menu->set_icon(gui_base->get_icon("Tools","EditorIcons")); @@ -5317,6 +5375,22 @@ EditorNode::EditorNode() { create_dialog->set_base_type("Resource"); create_dialog->connect("create",this,"_resource_created"); + search_bar = memnew( HBoxContainer ); + search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); + prop_editor_base->add_child(search_bar); + search_bar->hide(); + + l = memnew( Label("Search: ") ); + search_bar->add_child(l); + + search_box = memnew( LineEdit ); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + search_bar->add_child(search_box); + + ToolButton *clear_button = memnew( ToolButton ); + clear_button->set_icon(gui_base->get_icon("Close","EditorIcons")); + search_bar->add_child(clear_button); + clear_button->connect("pressed",this,"_clear_search_box"); property_editor = memnew( PropertyEditor ); property_editor->set_autoclear(true); @@ -5325,6 +5399,7 @@ EditorNode::EditorNode() { property_editor->set_use_doc_hints(true); property_editor->hide_top_label(); + property_editor->register_text_enter(search_box); prop_editor_base->add_child( property_editor ); property_editor->set_undo_redo(&editor_data.get_undo_redo()); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index bd88e1a4b9..2b91929b94 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -173,6 +173,7 @@ class EditorNode : public Node { SOURCES_REIMPORT, DEPENDENCY_LOAD_CHANGED_IMAGES, DEPENDENCY_UPDATE_IMPORTED, + SCENE_TAB_CLOSE, IMPORT_PLUGIN_BASE=100, @@ -217,6 +218,7 @@ class EditorNode : public Node { //main tabs Tabs *scene_tabs; + int tab_closing; int old_split_ofs; @@ -248,6 +250,7 @@ class EditorNode : public Node { ToolButton *play_scene_button; ToolButton *play_custom_scene_button; MenuButton *debug_button; + ToolButton *search_button; TextureProgress *audio_vu; //MenuButton *fileserver_menu; @@ -266,6 +269,9 @@ class EditorNode : public Node { ScenesDock *scenes_dock; EditorRunNative *run_native; + HBoxContainer *search_bar; + LineEdit *search_box; + CreateDialog *create_dialog; CallDialog *call_dialog; @@ -515,11 +521,20 @@ class EditorNode : public Node { void _save_docks(); void _load_docks(); + void _toggle_search_bar(bool p_pressed); + void _clear_search_box(); + protected: void _notification(int p_what); 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/project_settings.cpp b/tools/editor/project_settings.cpp index 25a2750166..2fd8b37753 100644 --- a/tools/editor/project_settings.cpp +++ b/tools/editor/project_settings.cpp @@ -59,6 +59,9 @@ void ProjectSettings::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { + search_button->set_icon(get_icon("Zoom","EditorIcons")); + clear_button->set_icon(get_icon("Close","EditorIcons")); + translation_list->connect("button_pressed",this,"_translation_delete"); _update_actions(); popup_add->add_icon_item(get_icon("Keyboard","EditorIcons"),"Key",InputEvent::KEY); @@ -1171,6 +1174,31 @@ void ProjectSettings::_update_autoload() { } +void ProjectSettings::_toggle_search_bar(bool p_pressed) { + + globals_editor->set_use_filter(p_pressed); + + if (p_pressed) { + + search_bar->show(); + add_prop_bar->hide(); + search_box->grab_focus(); + search_box->select_all(); + } else { + + search_bar->hide(); + add_prop_bar->show(); + } +} + +void ProjectSettings::_clear_search_box() { + + if (search_box->get_text()=="") + return; + + search_box->clear(); + globals_editor->update_tree(); +} void ProjectSettings::_bind_methods() { @@ -1212,6 +1240,9 @@ void ProjectSettings::_bind_methods() { ObjectTypeDB::bind_method(_MD("_update_autoload"),&ProjectSettings::_update_autoload); ObjectTypeDB::bind_method(_MD("_autoload_delete"),&ProjectSettings::_autoload_delete); + ObjectTypeDB::bind_method(_MD("_clear_search_box"),&ProjectSettings::_clear_search_box); + ObjectTypeDB::bind_method(_MD("_toggle_search_bar"),&ProjectSettings::_toggle_search_bar); + } ProjectSettings::ProjectSettings(EditorData *p_data) { @@ -1232,87 +1263,93 @@ ProjectSettings::ProjectSettings(EditorData *p_data) { //tab_container->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 15 ); //tab_container->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 ); - Control *props_base = memnew( Control ); + VBoxContainer *props_base = memnew( VBoxContainer ); + props_base->set_alignment(BoxContainer::ALIGN_BEGIN); + props_base->set_v_size_flags(Control::SIZE_EXPAND_FILL); tab_container->add_child(props_base); props_base->set_name("General"); - globals_editor = memnew( PropertyEditor ); - props_base->add_child(globals_editor); - globals_editor->set_area_as_parent_rect(); - globals_editor->hide_top_label(); - globals_editor->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 55 ); - globals_editor->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 ); - globals_editor->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 ); - globals_editor->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 ); - globals_editor->set_capitalize_paths(false); - globals_editor->get_scene_tree()->connect("cell_selected",this,"_item_selected"); - globals_editor->connect("property_toggled",this,"_item_checked"); - globals_editor->connect("property_edited",this,"_settings_prop_edited"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); + props_base->add_child(hbc); - Label *l = memnew( Label ); - props_base->add_child(l); - l->set_pos(Point2(6,5)); - l->set_text("Category:"); + search_button = memnew( ToolButton ); + search_button->set_toggle_mode(true); + search_button->set_pressed(false); + search_button->set_text("Search"); + hbc->add_child(search_button); + search_button->connect("toggled",this,"_toggle_search_bar"); + hbc->add_child( memnew( VSeparator ) ); - l = memnew( Label ); - l->set_anchor(MARGIN_LEFT,ANCHOR_RATIO); - props_base->add_child(l); - l->set_begin(Point2(0.21,5)); - l->set_text("Property:"); + add_prop_bar = memnew( HBoxContainer ); + add_prop_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); + hbc->add_child(add_prop_bar); - l = memnew( Label ); - l->set_anchor(MARGIN_LEFT,ANCHOR_RATIO); - props_base->add_child(l); - l->set_begin(Point2(0.51,5)); - l->set_text("Type:"); + Label *l = memnew( Label ); + add_prop_bar->add_child(l); + l->set_text("Category:"); category = memnew( LineEdit ); - props_base->add_child(category); - category->set_anchor(MARGIN_RIGHT,ANCHOR_RATIO); - category->set_begin( Point2(5,25) ); - category->set_end( Point2(0.20,26) ); + category->set_h_size_flags(Control::SIZE_EXPAND_FILL); + add_prop_bar->add_child(category); category->connect("text_entered",this,"_item_adds"); + l = memnew( Label ); + add_prop_bar->add_child(l); + l->set_text("Property:"); + property = memnew( LineEdit ); - props_base->add_child(property); - property->set_anchor(MARGIN_LEFT,ANCHOR_RATIO); - property->set_anchor(MARGIN_RIGHT,ANCHOR_RATIO); - property->set_begin( Point2(0.21,25) ); - property->set_end( Point2(0.50,26) ); + property->set_h_size_flags(Control::SIZE_EXPAND_FILL); + add_prop_bar->add_child(property); property->connect("text_entered",this,"_item_adds"); + l = memnew( Label ); + add_prop_bar->add_child(l); + l->set_text("Type:"); type = memnew( OptionButton ); - props_base->add_child(type); - type->set_anchor(MARGIN_LEFT,ANCHOR_RATIO); - type->set_anchor(MARGIN_RIGHT,ANCHOR_RATIO); - type->set_begin( Point2(0.51,25) ); - type->set_end( Point2(0.70,26) ); + type->set_h_size_flags(Control::SIZE_EXPAND_FILL); + add_prop_bar->add_child(type); type->add_item("bool"); type->add_item("int"); type->add_item("float"); type->add_item("string"); Button *add = memnew( Button ); - props_base->add_child(add); - add->set_anchor(MARGIN_LEFT,ANCHOR_RATIO); - add->set_anchor(MARGIN_RIGHT,ANCHOR_RATIO); - add->set_begin( Point2(0.71,25) ); - add->set_end( Point2(0.85,26) ); + add_prop_bar->add_child(add); add->set_text("Add"); add->connect("pressed",this,"_item_add"); Button *del = memnew( Button ); - props_base->add_child(del); - del->set_anchor(MARGIN_LEFT,ANCHOR_RATIO); - del->set_anchor(MARGIN_RIGHT,ANCHOR_END); - del->set_begin( Point2(0.86,25) ); - del->set_end( Point2(5,26) ); + add_prop_bar->add_child(del); del->set_text("Del"); del->connect("pressed",this,"_item_del"); - /* + search_bar = memnew( HBoxContainer ); + search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); + hbc->add_child(search_bar); + search_bar->hide(); + + search_box = memnew( LineEdit ); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + search_bar->add_child(search_box); + + clear_button = memnew( ToolButton ); + search_bar->add_child(clear_button); + clear_button->connect("pressed",this,"_clear_search_box"); + + globals_editor = memnew( PropertyEditor ); + props_base->add_child(globals_editor); + globals_editor->hide_top_label(); + globals_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + globals_editor->register_text_enter(search_box); + globals_editor->set_capitalize_paths(false); + globals_editor->get_scene_tree()->connect("cell_selected",this,"_item_selected"); + globals_editor->connect("property_toggled",this,"_item_checked"); + globals_editor->connect("property_edited",this,"_settings_prop_edited"); + +/* Button *save = memnew( Button ); props_base->add_child(save); @@ -1325,17 +1362,16 @@ ProjectSettings::ProjectSettings(EditorData *p_data) { save->set_text("Save"); save->connect("pressed",this,"_save"); */ + + hbc = memnew( HBoxContainer ); + props_base->add_child(hbc); + popup_platform = memnew( MenuButton ); popup_platform->set_text("Copy To Platform.."); popup_platform->set_disabled(true); - props_base->add_child(popup_platform); - - popup_platform->set_anchor(MARGIN_LEFT,ANCHOR_BEGIN); - popup_platform->set_anchor(MARGIN_RIGHT,ANCHOR_BEGIN); - popup_platform->set_anchor(MARGIN_TOP,ANCHOR_END); - popup_platform->set_anchor(MARGIN_BOTTOM,ANCHOR_END); - popup_platform->set_begin( Point2(10,28) ); - popup_platform->set_end( Point2(150,20) ); + hbc->add_child(popup_platform); + + hbc->add_spacer(); List<StringName> ep; EditorImportExport::get_singleton()->get_export_platforms(&ep); diff --git a/tools/editor/project_settings.h b/tools/editor/project_settings.h index 7c91254764..b122609e52 100644 --- a/tools/editor/project_settings.h +++ b/tools/editor/project_settings.h @@ -47,6 +47,12 @@ class ProjectSettings : public AcceptDialog { UndoRedo *undo_redo; PropertyEditor *globals_editor; + HBoxContainer *search_bar; + ToolButton *search_button; + LineEdit *search_box; + ToolButton *clear_button; + + HBoxContainer *add_prop_bar; ConfirmationDialog *message; LineEdit *category; LineEdit *property; @@ -130,6 +136,9 @@ class ProjectSettings : public AcceptDialog { void _translation_res_option_changed(); void _translation_res_option_delete(Object *p_item,int p_column, int p_button); + void _toggle_search_bar(bool p_pressed); + void _clear_search_box(); + ProjectSettings(); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index d6eae51fbd..31393ebcbc 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -2363,6 +2363,8 @@ void PropertyEditor::update_tree() { TreeItem * current_category=NULL; + String filter = search_box ? search_box->get_text() : ""; + for (List<PropertyInfo>::Element *I=plist.front() ; I ; I=I->next()) { PropertyInfo& p = I->get(); @@ -2426,7 +2428,24 @@ void PropertyEditor::update_tree() { } else if ( ! (p.usage&PROPERTY_USAGE_EDITOR ) ) continue; + String name = (p.name.find("/")!=-1)?p.name.right( p.name.find_last("/")+1 ):p.name; + + if (capitalize_paths) + name = name.camelcase_to_underscore().capitalize(); + String path=p.name.left( p.name.find_last("/") ) ; + + if (use_filter && filter!="") { + + String cat = path; + + if (capitalize_paths) + cat = cat.capitalize(); + + if (cat.findn(filter)==-1 && name.findn(filter)==-1) + continue; + } + //printf("property %s\n",p.name.ascii().get_data()); TreeItem * parent = get_parent_node(path,item_path,current_category?current_category:root ); //if (parent->get_parent()==root) @@ -2448,8 +2467,6 @@ void PropertyEditor::update_tree() { TreeItem * item = tree->create_item( parent ); - String name = (p.name.find("/")!=-1)?p.name.right( p.name.find_last("/")+1 ):p.name; - if (level>0) { item->set_custom_bg_color(0,col); //item->set_custom_bg_color(1,col); @@ -2465,11 +2482,7 @@ void PropertyEditor::update_tree() { item->set_checked(0,p.usage&PROPERTY_USAGE_CHECKED); } - if (capitalize_paths) - item->set_text( 0, name.camelcase_to_underscore().capitalize() ); - else - item->set_text( 0, name ); - + item->set_text(0, name); item->set_tooltip(0, p.name); if (use_doc_hints) { @@ -3403,6 +3416,11 @@ void PropertyEditor::_draw_flags(Object *t,const Rect2& p_rect) { } +void PropertyEditor::_filter_changed(const String& p_text) { + + update_tree(); +} + void PropertyEditor::_bind_methods() { ObjectTypeDB::bind_method( "_item_edited",&PropertyEditor::_item_edited); @@ -3415,6 +3433,7 @@ void PropertyEditor::_bind_methods() { ObjectTypeDB::bind_method( "_changed_callback",&PropertyEditor::_changed_callbacks); ObjectTypeDB::bind_method( "_draw_flags",&PropertyEditor::_draw_flags); ObjectTypeDB::bind_method( "_set_range_def",&PropertyEditor::_set_range_def); + ObjectTypeDB::bind_method( "_filter_changed",&PropertyEditor::_filter_changed); ADD_SIGNAL( MethodInfo("property_toggled",PropertyInfo( Variant::STRING, "property"),PropertyInfo( Variant::BOOL, "value"))); ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); @@ -3469,12 +3488,32 @@ void PropertyEditor::set_show_categories(bool p_show) { update_tree(); } +void PropertyEditor::set_use_filter(bool p_use) { + + if (p_use==use_filter) + return; + + use_filter=p_use; + update_tree(); +} + +void PropertyEditor::register_text_enter(Node* p_line_edit) { + + ERR_FAIL_NULL(p_line_edit); + search_box=p_line_edit->cast_to<LineEdit>(); + + if (search_box) + search_box->connect("text_changed",this,"_filter_changed"); + +} + PropertyEditor::PropertyEditor() { _prop_edited="property_edited"; _prop_edited_name.push_back(String()); undo_redo=NULL; obj=NULL; + search_box=NULL; changing=false; update_tree_pending=false; @@ -3527,7 +3566,9 @@ PropertyEditor::PropertyEditor() { show_categories=false; refresh_countdown=0; use_doc_hints=false; - + + use_filter=false; + } diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index dcb7b66abd..5fb8386b1b 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -147,6 +147,7 @@ class PropertyEditor : public Control { Tree *tree; Label *top_label; //Object *object; + LineEdit *search_box; Object* obj; @@ -163,6 +164,8 @@ class PropertyEditor : public Control { float refresh_countdown; bool use_doc_hints; + bool use_filter; + HashMap<String,String> pending; String selected_property; @@ -201,6 +204,8 @@ class PropertyEditor : public Control { void _refresh_item(TreeItem *p_item); void _set_range_def(Object *p_item, String prop, float p_frame); + void _filter_changed(const String& p_text); + UndoRedo *undo_redo; protected: @@ -230,7 +235,10 @@ public: void set_show_categories(bool p_show); void set_use_doc_hints(bool p_enable) { use_doc_hints=p_enable; } - + + void set_use_filter(bool p_use); + void register_text_enter(Node *p_line_edit); + PropertyEditor(); ~PropertyEditor(); 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.. diff --git a/tools/editor/settings_config_dialog.cpp b/tools/editor/settings_config_dialog.cpp index f73de26eec..6d8f849427 100644 --- a/tools/editor/settings_config_dialog.cpp +++ b/tools/editor/settings_config_dialog.cpp @@ -72,6 +72,10 @@ void EditorSettingsDialog::popup_edit_settings() { property_editor->edit(EditorSettings::get_singleton()); property_editor->update_tree(); + + search_box->select_all(); + search_box->grab_focus(); + popup_centered_ratio(0.7); } @@ -244,11 +248,21 @@ void EditorSettingsDialog::_update_plugins() { } +void EditorSettingsDialog::_clear_search_box() { + + if (search_box->get_text()=="") + return; + + search_box->clear(); + property_editor->update_tree(); +} + void EditorSettingsDialog::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { rescan_plugins->set_icon(get_icon("Reload","EditorIcons")); + clear_button->set_icon(get_icon("Close","EditorIcons")); _update_plugins(); } } @@ -261,6 +275,7 @@ void EditorSettingsDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_plugin_settings"),&EditorSettingsDialog::_plugin_settings); ObjectTypeDB::bind_method(_MD("_plugin_edited"),&EditorSettingsDialog::_plugin_edited); ObjectTypeDB::bind_method(_MD("_plugin_install"),&EditorSettingsDialog::_plugin_install); + ObjectTypeDB::bind_method(_MD("_clear_search_box"),&EditorSettingsDialog::_clear_search_box); } EditorSettingsDialog::EditorSettingsDialog() { @@ -271,16 +286,38 @@ EditorSettingsDialog::EditorSettingsDialog() { add_child(tabs); set_child_rect(tabs); + VBoxContainer *vbc = memnew( VBoxContainer ); + tabs->add_child(vbc); + vbc->set_name("General"); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); + vbc->add_child(hbc); + + Label *l = memnew( Label ); + l->set_text("Search: "); + hbc->add_child(l); + + search_box = memnew( LineEdit ); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + hbc->add_child(search_box); + + clear_button = memnew( ToolButton ); + hbc->add_child(clear_button); + clear_button->connect("pressed",this,"_clear_search_box"); + property_editor = memnew( PropertyEditor ); property_editor->hide_top_label(); - tabs->add_child(property_editor); - property_editor->set_name("General"); + property_editor->set_use_filter(true); + property_editor->register_text_enter(search_box); + property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + vbc->add_child(property_editor); - VBoxContainer *vbc = memnew( VBoxContainer ); + vbc = memnew( VBoxContainer ); tabs->add_child(vbc); vbc->set_name("Plugins"); - HBoxContainer *hbc = memnew( HBoxContainer ); + hbc = memnew( HBoxContainer ); vbc->add_child(hbc); hbc->add_child( memnew( Label("Plugin List: "))); hbc->add_spacer(); diff --git a/tools/editor/settings_config_dialog.h b/tools/editor/settings_config_dialog.h index cca1ef33d5..50159cf488 100644 --- a/tools/editor/settings_config_dialog.h +++ b/tools/editor/settings_config_dialog.h @@ -51,6 +51,8 @@ class EditorSettingsDialog : public AcceptDialog { Button *rescan_plugins; Tree *plugins; + LineEdit *search_box; + ToolButton *clear_button; PropertyEditor *property_editor; Timer *timer; @@ -71,6 +73,8 @@ class EditorSettingsDialog : public AcceptDialog { void _rescan_plugins(); void _update_plugins(); + void _clear_search_box(); + protected: static void _bind_methods(); |