diff options
76 files changed, 2438 insertions, 1095 deletions
diff --git a/.gitignore b/.gitignore index de9eed200a..abe1a234f5 100644 --- a/.gitignore +++ b/.gitignore @@ -233,3 +233,4 @@ Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ +logo.h @@ -15,9 +15,13 @@ Development is sponsored by OKAM Studio (http://www.okamstudio.com). Having been developed as in-house means that the user experience may still not be ideal for everyone. The features needed to make a great game are there, but we really need your help to fix all the rough edges and improve usability (via feedback and/or code contributions). We know we are close to having an awesome, open source, game engine with nothing to envy from the best commercial offerings, but we can't do this alone. This is why Godot is now open source, so everyone can help us reach this goal. -### Binary Downloads, Documentation, Community, etc. +### Documentation -Binary downloads, documentation, community, etc. can be found in Godot homepage: +Documentation has been moved to the [GitHub Wiki](https://github.com/okamstudio/godot/wiki). + +### Binary Downloads, Community, etc. + +Binary downloads, community, etc. can be found in Godot homepage: http://www.godotengine.org diff --git a/SConstruct b/SConstruct index 1fb82bfc33..4df8e0089d 100644 --- a/SConstruct +++ b/SConstruct @@ -88,7 +88,7 @@ if profile: elif os.path.isfile(profile+".py"): customs.append(profile+".py") -opts=Options(customs, ARGUMENTS) +opts=Variables(customs, ARGUMENTS) opts.Add('target', 'Compile Target (debug/profile/release).', "debug") opts.Add('platform','Platform: '+str(platform_list)+'(sfml).',"") opts.Add('python','Build Python Support: (yes/no)','no') @@ -210,18 +210,9 @@ for p in platform_list: if (env["builtin_zlib"]=='yes'): env.Append(CPPPATH=['#drivers/builtin_zlib/zlib']) - if (env['squirrel']=='yes'): - - env.Append(CPPFLAGS=['-DSQUIRREL_ENABLED']) - env.Append(CPPPATH=['#script/squirrel/src']) - # to test 64 bits compiltion # env.Append(CPPFLAGS=['-m64']) - if (env['lua']=='yes'): - - env.Append(CPPFLAGS=['-DLUA_ENABLED']) - env.Append(CPPPATH=['#script/lua/src']) if (env_base['squish']=='yes'): env.Append(CPPFLAGS=['-DSQUISH_ENABLED']); @@ -297,7 +288,6 @@ for p in platform_list: SConscript("servers/SCsub") SConscript("scene/SCsub") SConscript("tools/SCsub") - SConscript("script/SCsub"); SConscript("drivers/SCsub") SConscript("bin/SCsub") diff --git a/bin/tests/test_gdscript.cpp b/bin/tests/test_gdscript.cpp index 48f982425b..9670e6af6e 100644 --- a/bin/tests/test_gdscript.cpp +++ b/bin/tests/test_gdscript.cpp @@ -35,10 +35,10 @@ #ifdef GDSCRIPT_ENABLED -#include "script/gdscript/gd_tokenizer.h" -#include "script/gdscript/gd_parser.h" -#include "script/gdscript/gd_compiler.h" -#include "script/gdscript/gd_script.h" +#include "modules/gdscript/gd_tokenizer.h" +#include "modules/gdscript/gd_parser.h" +#include "modules/gdscript/gd_compiler.h" +#include "modules/gdscript/gd_script.h" namespace TestGDScript { @@ -864,7 +864,7 @@ MainLoop* test(TestType p_test) { if (p_test==TEST_TOKENIZER) { - GDTokenizer tk; + GDTokenizerText tk; tk.set_code(code); int line=-1; while(tk.get_token()!=GDTokenizer::TK_EOF) { @@ -969,8 +969,16 @@ MainLoop* test(TestType p_test) { + } else if (p_test==TEST_BYTECODE) { + + Vector<uint8_t> buf = GDTokenizerBuffer::parse_code_string(code); + String dst = test.basename()+".gdc"; + FileAccess *fw = FileAccess::open(dst,FileAccess::WRITE); + fw->store_buffer(buf.ptr(),buf.size()); + memdelete(fw); } + #if 0 Parser parser; Error err = parser.parse(code); diff --git a/bin/tests/test_gdscript.h b/bin/tests/test_gdscript.h index c3869abb8e..1659880c2a 100644 --- a/bin/tests/test_gdscript.h +++ b/bin/tests/test_gdscript.h @@ -36,7 +36,8 @@ namespace TestGDScript { enum TestType { TEST_TOKENIZER, TEST_PARSER, - TEST_COMPILER + TEST_COMPILER, + TEST_BYTECODE, }; MainLoop* test(TestType p_type); diff --git a/bin/tests/test_main.cpp b/bin/tests/test_main.cpp index eb63a7af84..5d66f35f24 100644 --- a/bin/tests/test_main.cpp +++ b/bin/tests/test_main.cpp @@ -152,6 +152,11 @@ MainLoop* test_main(String p_test,const List<String>& p_args) { return TestGDScript::test(TestGDScript::TEST_COMPILER); } + if (p_test=="gd_bytecode") { + + return TestGDScript::test(TestGDScript::TEST_BYTECODE); + } + if (p_test=="image") { return TestImage::test(); diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 61209ecb90..73f6f753b9 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -413,6 +413,56 @@ void _OS::dump_memory_to_file(const String& p_file) { OS::get_singleton()->dump_memory_to_file(p_file.utf8().get_data()); } +struct _OSCoreBindImg { + + String path; + Size2 size; + int fmt; + ObjectID id; + int vram; + bool operator<(const _OSCoreBindImg& p_img) const { return vram==p_img.vram ? id<p_img.id : vram > p_img.vram; } +}; + +void _OS::print_all_textures_by_size() { + + + List<_OSCoreBindImg> imgs; + int total=0; + { + List<Ref<Resource> > rsrc; + ResourceCache::get_cached_resources(&rsrc); + + for (List<Ref<Resource> >::Element *E=rsrc.front();E;E=E->next()) { + + if (!E->get()->is_type("ImageTexture")) + continue; + + Size2 size = E->get()->call("get_size"); + int fmt = E->get()->call("get_format"); + + _OSCoreBindImg img; + img.size=size; + img.fmt=fmt; + img.path=E->get()->get_path(); + img.vram=Image::get_image_data_size(img.size.width,img.size.height,Image::Format(img.fmt)); + img.id=E->get()->get_instance_ID(); + total+=img.vram; + imgs.push_back(img); + } + } + + imgs.sort(); + + for(List<_OSCoreBindImg>::Element *E=imgs.front();E;E=E->next()) { + + print_line(E->get().path+" - "+String::humanize_size(E->get().vram)+" ("+E->get().size+") - total:"+String::humanize_size(total) ); + total-=E->get().vram; + } + + + +} + void _OS::print_all_resources(const String& p_to_file ) { OS::get_singleton()->print_all_resources(p_to_file); @@ -516,6 +566,8 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_frames_per_second"),&_OS::get_frames_per_second); + ObjectTypeDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size); + BIND_CONSTANT( DAY_SUNDAY ); BIND_CONSTANT( DAY_MONDAY ); BIND_CONSTANT( DAY_TUESDAY ); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index e47c9c434a..9545fc65fb 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -128,6 +128,7 @@ public: void print_resources_in_use(bool p_short=false); void print_all_resources(const String& p_to_file); + void print_all_textures_by_size(); bool has_touchscreen_ui_hint() const; diff --git a/core/image.cpp b/core/image.cpp index a9485feff2..ccabd04d6f 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1260,6 +1260,12 @@ int Image::get_format_pixel_size(Format p_format) { return 1; } break; + case FORMAT_ATC: + case FORMAT_ATC_ALPHA_EXPLICIT: + case FORMAT_ATC_ALPHA_INTERPOLATED: { + + return 1; + } break; case FORMAT_ETC: { return 1; @@ -1323,6 +1329,15 @@ void Image::_get_format_min_data_size(Format p_format,int &r_w, int &r_h) { r_w=8; r_h=8; } break; + case FORMAT_ATC: + case FORMAT_ATC_ALPHA_EXPLICIT: + case FORMAT_ATC_ALPHA_INTERPOLATED: { + + r_w=8; + r_h=8; + + } break; + case FORMAT_ETC: { r_w=4; @@ -1339,7 +1354,7 @@ void Image::_get_format_min_data_size(Format p_format,int &r_w, int &r_h) { int Image::get_format_pixel_rshift(Format p_format) { - if (p_format==FORMAT_BC1 || p_format==FORMAT_BC4 || p_format==FORMAT_PVRTC4 || p_format==FORMAT_PVRTC4_ALPHA || p_format==FORMAT_ETC) + if (p_format==FORMAT_BC1 || p_format==FORMAT_BC4 || p_format==FORMAT_ATC || p_format==FORMAT_PVRTC4 || p_format==FORMAT_PVRTC4_ALPHA || p_format==FORMAT_ETC) return 1; else if (p_format==FORMAT_PVRTC2 || p_format==FORMAT_PVRTC2_ALPHA) return 2; diff --git a/core/image.h b/core/image.h index 4ab2870c23..186aceb1bf 100644 --- a/core/image.h +++ b/core/image.h @@ -70,6 +70,9 @@ public: FORMAT_PVRTC4, FORMAT_PVRTC4_ALPHA, FORMAT_ETC, // regular ETC, no transparency + FORMAT_ATC, + FORMAT_ATC_ALPHA_EXPLICIT, + FORMAT_ATC_ALPHA_INTERPOLATED, /*FORMAT_ETC2_R, for the future.. FORMAT_ETC2_RG, FORMAT_ETC2_RGB, diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index d2461498a6..c54398935e 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -90,6 +90,9 @@ enum { IMAGE_FORMAT_PVRTC4=14, IMAGE_FORMAT_PVRTC4_ALPHA=15, IMAGE_FORMAT_ETC=16, + IMAGE_FORMAT_ATC=17, + IMAGE_FORMAT_ATC_ALPHA_EXPLICIT=18, + IMAGE_FORMAT_ATC_ALPHA_INTERPOLATED=19, IMAGE_FORMAT_CUSTOM=30, @@ -283,6 +286,9 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) { case IMAGE_FORMAT_PVRTC4: { fmt=Image::FORMAT_PVRTC4; } break; case IMAGE_FORMAT_PVRTC4_ALPHA: { fmt=Image::FORMAT_PVRTC4_ALPHA; } break; case IMAGE_FORMAT_ETC: { fmt=Image::FORMAT_ETC; } break; + case IMAGE_FORMAT_ATC: { fmt=Image::FORMAT_ATC; } break; + case IMAGE_FORMAT_ATC_ALPHA_EXPLICIT: { fmt=Image::FORMAT_ATC_ALPHA_EXPLICIT; } break; + case IMAGE_FORMAT_ATC_ALPHA_INTERPOLATED: { fmt=Image::FORMAT_ATC_ALPHA_INTERPOLATED; } break; case IMAGE_FORMAT_CUSTOM: { fmt=Image::FORMAT_CUSTOM; } break; default: { @@ -1335,6 +1341,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property, case Image::FORMAT_PVRTC4: f->store_32(IMAGE_FORMAT_PVRTC4 ); break; case Image::FORMAT_PVRTC4_ALPHA: f->store_32(IMAGE_FORMAT_PVRTC4_ALPHA ); break; case Image::FORMAT_ETC: f->store_32(IMAGE_FORMAT_ETC); break; + case Image::FORMAT_ATC: f->store_32(IMAGE_FORMAT_ATC); break; + case Image::FORMAT_ATC_ALPHA_EXPLICIT: f->store_32(IMAGE_FORMAT_ATC_ALPHA_EXPLICIT); break; + case Image::FORMAT_ATC_ALPHA_INTERPOLATED: f->store_32(IMAGE_FORMAT_ATC_ALPHA_INTERPOLATED); break; case Image::FORMAT_CUSTOM: f->store_32(IMAGE_FORMAT_CUSTOM ); break; default: {} diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index 20a42f25df..fc5aecfd99 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -111,7 +111,7 @@ ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool } break; - } else if ( ((!reading_value && (c<33)) || c=='=' || c=='"') && tag.name.length()) { + } else if ( ((!reading_value && (c<33)) || c=='=' || c=='"' || c=='\'') && tag.name.length()) { if (!reading_value && name.length()) { @@ -551,6 +551,12 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) imgformat=Image::FORMAT_PVRTC4_ALPHA; } else if (format=="etc") { imgformat=Image::FORMAT_ETC; + } else if (format=="atc") { + imgformat=Image::FORMAT_ATC; + } else if (format=="atcai") { + imgformat=Image::FORMAT_ATC_ALPHA_INTERPOLATED; + } else if (format=="atcae") { + imgformat=Image::FORMAT_ATC_ALPHA_EXPLICIT; } else if (format=="custom") { imgformat=Image::FORMAT_CUSTOM; } else { @@ -1937,6 +1943,9 @@ void ResourceFormatSaverXMLInstance::write_property(const String& p_name,const V case Image::FORMAT_PVRTC4: params+=" format=\"pvrtc4\""; break; case Image::FORMAT_PVRTC4_ALPHA: params+=" format=\"pvrtc4a\""; break; case Image::FORMAT_ETC: params+=" format=\"etc\""; break; + case Image::FORMAT_ATC: params+=" format=\"atc\""; break; + case Image::FORMAT_ATC_ALPHA_EXPLICIT: params+=" format=\"atcae\""; break; + case Image::FORMAT_ATC_ALPHA_INTERPOLATED: params+=" format=\"atcai\""; break; case Image::FORMAT_CUSTOM: params+=" format=\"custom\" custom_size=\""+itos(img.get_data().size())+"\""; break; default: {} } diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 3bae6be83c..5ee48bae25 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -192,6 +192,7 @@ RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_n res->set_last_modified_time(mt); } #endif + return res; } @@ -246,7 +247,7 @@ String ResourceLoader::find_complete_path(const String& p_path,const String& p_t String path = local_path+E->get(); - if (FileAccess::exists(path)) { + if (PathRemap::get_singleton()->has_remap(path) || FileAccess::exists(path)) { candidates.push_back(path); } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 846b924a42..be1b0eb3d3 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1487,6 +1487,9 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl _VariantCall::constant_data[Variant::IMAGE].value["FORMAT_PVRTC4"]=Image::FORMAT_PVRTC4; _VariantCall::constant_data[Variant::IMAGE].value["FORMAT_PVRTC4_ALPHA"]=Image::FORMAT_PVRTC4_ALPHA; _VariantCall::constant_data[Variant::IMAGE].value["FORMAT_ETC"]=Image::FORMAT_ETC; + _VariantCall::constant_data[Variant::IMAGE].value["FORMAT_ATC"]=Image::FORMAT_ATC; + _VariantCall::constant_data[Variant::IMAGE].value["FORMAT_ATC_ALPHA_EXPLICIT"]=Image::FORMAT_ATC_ALPHA_EXPLICIT; + _VariantCall::constant_data[Variant::IMAGE].value["FORMAT_ATC_ALPHA_INTERPOLATED"]=Image::FORMAT_ATC_ALPHA_INTERPOLATED; _VariantCall::constant_data[Variant::IMAGE].value["FORMAT_CUSTOM"]=Image::FORMAT_CUSTOM; } diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 109e4ab387..50908bbf94 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1319,7 +1319,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) return; int type=p_value; - if (type<0 || type>=6) + if (type<0 || type>=InputEvent::TYPE_MAX) return; //fail valid=true; ie.type=InputEvent::Type(type); @@ -2765,6 +2765,7 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { InputEvent ie = operator InputEvent(); + p_list->push_back( PropertyInfo(Variant::INT,"type")); p_list->push_back( PropertyInfo(Variant::INT,"device")); p_list->push_back( PropertyInfo(Variant::INT,"ID")); diff --git a/core/vmap.h b/core/vmap.h index c6c3d50bc7..516299280b 100644 --- a/core/vmap.h +++ b/core/vmap.h @@ -142,6 +142,12 @@ public: } + int find_nearest(const T& p_val) const { + + bool exact; + return _find(p_val,exact); + + } _FORCE_INLINE_ int size() const { return _data.size(); } _FORCE_INLINE_ bool empty() const { return _data.empty(); } diff --git a/demos/2d/platformer/engine.cfg b/demos/2d/platformer/engine.cfg index 0ca951ed00..5fc2c3b2ba 100644 --- a/demos/2d/platformer/engine.cfg +++ b/demos/2d/platformer/engine.cfg @@ -26,3 +26,7 @@ default_gravity=700 [render] mipmap_policy=1 + +[texture_import] + +filter=false diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index d29ecd64bb..5be6045d50 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -303,6 +303,11 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c #define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE #define _EXT_ETC1_RGB8_OES 0x8D64 +#define _EXT_ATC_RGB_AMD 0x8C92 +#define _EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 +#define _EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE + + /* TEXTURE API */ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) { @@ -394,6 +399,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } break; case Image::FORMAT_BC5: { + r_gl_format=_EXT_COMPRESSED_RG_RGTC2; r_gl_components=1; //doesn't matter much r_compressed=true; @@ -492,6 +498,63 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } } break; + case Image::FORMAT_ATC: { + + if (!atitc_supported) { + + if (!image.empty()) { + image.decompress(); + } + r_gl_components=3; + r_gl_format=GL_RGB; + + + } else { + + r_gl_format=_EXT_ATC_RGB_AMD; + r_gl_components=1; //doesn't matter much + r_compressed=true; + } + + } break; + case Image::FORMAT_ATC_ALPHA_EXPLICIT: { + + if (!atitc_supported) { + + if (!image.empty()) { + image.decompress(); + } + r_gl_components=4; + r_gl_format=GL_RGBA; + + + } else { + + r_gl_format=_EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD; + r_gl_components=1; //doesn't matter much + r_compressed=true; + } + + } break; + case Image::FORMAT_ATC_ALPHA_INTERPOLATED: { + + if (!atitc_supported) { + + if (!image.empty()) { + image.decompress(); + } + r_gl_components=4; + r_gl_format=GL_RGBA; + + + } else { + + r_gl_format=_EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD; + r_gl_components=1; //doesn't matter much + r_compressed=true; + } + + } break; case Image::FORMAT_YUV_422: case Image::FORMAT_YUV_444: { @@ -557,7 +620,9 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I texture->flags=p_flags; texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; - bool scale_textures = !(p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && (!npo2_textures_available || p_flags&VS::TEXTURE_FLAG_MIPMAPS); + _get_gl_image_and_format(Image(),texture->format,texture->flags,format,components,has_alpha_cache,compressed); + + bool scale_textures = !compressed && !(p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && (!npo2_textures_available || p_flags&VS::TEXTURE_FLAG_MIPMAPS); if (scale_textures) { @@ -570,7 +635,6 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I texture->alloc_height = texture->height; }; - _get_gl_image_and_format(Image(),texture->format,texture->flags,format,components,has_alpha_cache,compressed); texture->gl_components_cache=components; texture->gl_format_cache=format; @@ -584,32 +648,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I glBindTexture(texture->target, texture->tex_id); - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - if (texture->flags&VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // raw Filtering - } - - bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); - - if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT && texture->target != GL_TEXTURE_CUBE_MAP) { - - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } else { - - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - } if (p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) { //prealloc if video @@ -652,6 +691,8 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu texture->has_alpha=true; } + + GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP)?_cube_side_enum[p_cube_side]:GL_TEXTURE_2D; texture->data_size=img.get_data().size(); @@ -660,6 +701,35 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); + texture->ignore_mipmaps = compressed && img.get_mipmaps()==0; + + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); + else + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering + + } else { + + glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // raw Filtering + } + + bool force_clamp_to_edge = !(texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); + + if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT && texture->target != GL_TEXTURE_CUBE_MAP) { + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } else { + + //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); + glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + } + int mipmaps= (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1; @@ -699,7 +769,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu //printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem); - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && mipmaps==1) { + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && mipmaps==1 && !texture->ignore_mipmaps) { //generate mipmaps if they were requested and the image does not contain them glGenerateMipmap(texture->target); } @@ -889,7 +959,7 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; texture->flags=p_flags|cube; // can't remove a cube from being a cube - bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); + bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT && texture->target != GL_TEXTURE_CUBE_MAP) { @@ -903,17 +973,18 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { } + if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); + else + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering } else { - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // nearest + glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // raw Filtering } } uint32_t RasterizerGLES2::texture_get_flags(RID p_texture) const { @@ -7493,6 +7564,7 @@ void RasterizerGLES2::init() { etc_supported=false; use_depth24 =true; s3tc_supported = true; + atitc_supported = false; use_hw_skeleton_xform = false; // use_texture_instancing=false; // use_attribute_instancing=true; @@ -7506,6 +7578,10 @@ void RasterizerGLES2::init() { use_half_float=true; #else + + for (Set<String>::Element *E=extensions.front();E;E=E->next()) { + print_line(E->get()); + } read_depth_supported=extensions.has("GL_OES_depth_texture"); use_rgba_shadowmaps=!read_depth_supported; pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc"); @@ -7513,7 +7589,9 @@ void RasterizerGLES2::init() { use_depth24 = extensions.has("GL_OES_depth24"); s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc"); use_half_float = extensions.has("GL_OES_vertex_half_float"); + atitc_supported=extensions.has("GL_AMD_compressed_ATC_texture"); + print_line("S3TC: "+itos(s3tc_supported)+" ATITC: "+itos(atitc_supported)); GLint vtf; glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,&vtf); @@ -7885,6 +7963,7 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo use_fast_texture_filter=GLOBAL_DEF("rasterizer/trilinear_mipmap_filter",true); skel_default.resize(1024*4); for(int i=0;i<1024/3;i++) { + float * ptr = skel_default.ptr(); ptr+=i*4*4; ptr[0]=1.0; @@ -7901,7 +7980,6 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo ptr[9]=0.0; ptr[10]=1.0; ptr[12]=0.0; - } base_framebuffer=0; diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index bab560dddb..52c4c8d681 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -75,6 +75,7 @@ class RasterizerGLES2 : public Rasterizer { bool pvr_supported; bool s3tc_supported; bool etc_supported; + bool atitc_supported; bool npo2_textures_available; bool read_depth_supported; bool use_framebuffers; @@ -111,6 +112,7 @@ class RasterizerGLES2 : public Rasterizer { bool compressed; bool disallow_mipmaps; int total_data_size; + bool ignore_mipmaps; ObjectID reloader; StringName reloader_func; @@ -123,6 +125,7 @@ class RasterizerGLES2 : public Rasterizer { Texture() { + ignore_mipmaps=false; render_target=NULL; flags=width=height=0; tex_id=0; diff --git a/main/main.cpp b/main/main.cpp index 305cc88be7..7d19c2ebcf 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -33,7 +33,6 @@ #include "core/register_core_types.h" #include "scene/register_scene_types.h" #include "drivers/register_driver_types.h" -#include "script/register_script_types.h" #include "servers/register_server_types.h" #include "modules/register_module_types.h" #include "script_debugger_local.h" @@ -766,7 +765,6 @@ Error Main::setup2() { MAIN_PRINT("Main: Load Scripts, Modules, Drivers"); register_module_types(); - register_script_types(); register_driver_types(); MAIN_PRINT("Main: Load Translations"); @@ -1367,11 +1365,14 @@ void Main::cleanup() { OS::get_singleton()->_execpath=""; OS::get_singleton()->_local_clipboard=""; +#ifdef TOOLS_ENABLED + EditorNode::unregister_editor_types(); +#endif + unregister_driver_types(); unregister_module_types(); unregister_scene_types(); unregister_server_types(); - unregister_script_types(); OS::get_singleton()->finalize(); diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub new file mode 100644 index 0000000000..d20da72b72 --- /dev/null +++ b/modules/gdscript/SCsub @@ -0,0 +1,7 @@ +Import('env') + +env.add_source_files(env.modules_sources,"*.cpp") + +Export('env') + + diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py new file mode 100644 index 0000000000..f9bd7da08d --- /dev/null +++ b/modules/gdscript/config.py @@ -0,0 +1,11 @@ + + +def can_build(platform): + return True + + +def configure(env): + pass + + + diff --git a/script/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index dd2834bf34..dd2834bf34 100644 --- a/script/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp diff --git a/script/gdscript/gd_compiler.h b/modules/gdscript/gd_compiler.h index cda221dab0..cda221dab0 100644 --- a/script/gdscript/gd_compiler.h +++ b/modules/gdscript/gd_compiler.h diff --git a/script/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index c10cadf83f..f8717c292f 100644 --- a/script/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -106,7 +106,7 @@ bool GDScriptLanguage::has_named_classes() const { int GDScriptLanguage::find_function(const String& p_function,const String& p_code) const { - GDTokenizer tokenizer; + GDTokenizerText tokenizer; tokenizer.set_code(p_code); int indent=0; while(tokenizer.get_token()!=GDTokenizer::TK_EOF && tokenizer.get_token()!=GDTokenizer::TK_ERROR) { diff --git a/script/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp index 2930d9322c..2930d9322c 100644 --- a/script/gdscript/gd_functions.cpp +++ b/modules/gdscript/gd_functions.cpp diff --git a/script/gdscript/gd_functions.h b/modules/gdscript/gd_functions.h index 2ab397d18a..2ab397d18a 100644 --- a/script/gdscript/gd_functions.h +++ b/modules/gdscript/gd_functions.h diff --git a/script/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index e558ceb416..fb4f56aa8f 100644 --- a/script/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -54,18 +54,18 @@ T* GDParser::alloc_node() { if (!head) head=t; - t->line=tokenizer.get_token_line(); - t->column=tokenizer.get_token_column(); + t->line=tokenizer->get_token_line(); + t->column=tokenizer->get_token_column(); return t; } bool GDParser::_end_statement() { - if (tokenizer.get_token()==GDTokenizer::TK_SEMICOLON) { - tokenizer.advance(); + if (tokenizer->get_token()==GDTokenizer::TK_SEMICOLON) { + tokenizer->advance(); return true; //handle next - } else if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE || tokenizer.get_token()==GDTokenizer::TK_EOF) { + } else if (tokenizer->get_token()==GDTokenizer::TK_NEWLINE || tokenizer->get_token()==GDTokenizer::TK_EOF) { return true; //will be handled properly } @@ -75,14 +75,14 @@ bool GDParser::_end_statement() { bool GDParser::_enter_indent_block(BlockNode* p_block) { - if (tokenizer.get_token()!=GDTokenizer::TK_COLON) { + if (tokenizer->get_token()!=GDTokenizer::TK_COLON) { _set_error("':' expected at end of line."); return false; } - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_NEWLINE) { + if (tokenizer->get_token()!=GDTokenizer::TK_NEWLINE) { _set_error("newline expected after ':'."); return false; @@ -90,35 +90,35 @@ bool GDParser::_enter_indent_block(BlockNode* p_block) { while(true) { - if (tokenizer.get_token()!=GDTokenizer::TK_NEWLINE) { + if (tokenizer->get_token()!=GDTokenizer::TK_NEWLINE) { return false; //wtf - } else if (tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE) { + } else if (tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE) { - int indent = tokenizer.get_token_line_indent(); + int indent = tokenizer->get_token_line_indent(); int current = tab_level.back()->get(); if (indent<=current) return false; tab_level.push_back(indent); - tokenizer.advance(); + tokenizer->advance(); return true; } else if (p_block) { NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line=tokenizer.get_token_line(); + nl->line=tokenizer->get_token_line(); p_block->statements.push_back(nl); } - tokenizer.advance(); // go to next newline + tokenizer->advance(); // go to next newline } } bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static) { - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { - tokenizer.advance(); + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { + tokenizer->advance(); } else { while(true) { @@ -130,19 +130,19 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat p_args.push_back(arg); - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { - tokenizer.advance(); + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { + tokenizer->advance(); break; - } else if (tokenizer.get_token()==GDTokenizer::TK_COMMA) { + } else if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { - if (tokenizer.get_token(1)==GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token(1)==GDTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expression expected"); return false; } - tokenizer.advance(); + tokenizer->advance(); } else { // something is broken _set_error("Expected ',' or ')'"); @@ -174,45 +174,45 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ /* Parse Operand */ /*****************/ - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) { + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) { //subexpression () - tokenizer.advance(); + tokenizer->advance(); Node* subexpr = _parse_expression(p_parent,p_static); if (!subexpr) return NULL; - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ')' in expression"); return NULL; } - tokenizer.advance(); + tokenizer->advance(); expr=subexpr; - } else if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT) { + } else if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT) { //constant defined by tokenizer ConstantNode *constant = alloc_node<ConstantNode>(); - constant->value=tokenizer.get_token_constant(); - tokenizer.advance(); + constant->value=tokenizer->get_token_constant(); + tokenizer->advance(); expr=constant; - } else if (tokenizer.get_token()==GDTokenizer::TK_PR_PRELOAD) { + } else if (tokenizer->get_token()==GDTokenizer::TK_PR_PRELOAD) { //constant defined by tokenizer - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { _set_error("Expected '(' after 'preload'"); return NULL; } - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type()!=Variant::STRING) { _set_error("Expected string constant as 'preload' argument."); return NULL; } - String path = tokenizer.get_token_constant(); + String path = tokenizer->get_token_constant(); if (!path.is_abs_path() && base_path!="") path=base_path+"/"+path; @@ -222,20 +222,20 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ return NULL; } - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ')' after 'preload' path"); return NULL; } ConstantNode *constant = alloc_node<ConstantNode>(); constant->value=res; - tokenizer.advance(); + tokenizer->advance(); expr=constant; - } else if (tokenizer.get_token()==GDTokenizer::TK_SELF) { + } else if (tokenizer->get_token()==GDTokenizer::TK_SELF) { if (p_static) { _set_error("'self'' not allowed in static function or constant expression"); @@ -243,18 +243,18 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } //constant defined by tokenizer SelfNode *self = alloc_node<SelfNode>(); - tokenizer.advance(); + tokenizer->advance(); expr=self; - } else if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE && tokenizer.get_token(1)==GDTokenizer::TK_PERIOD) { + } else if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token(1)==GDTokenizer::TK_PERIOD) { - Variant::Type bi_type = tokenizer.get_token_type(); - tokenizer.advance(2); - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) { + Variant::Type bi_type = tokenizer->get_token_type(); + tokenizer->advance(2); + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { _set_error("Built-in type constant expected after '.'"); return NULL; } - StringName identifier = tokenizer.get_token_identifier(); + StringName identifier = tokenizer->get_token_identifier(); if (!Variant::has_numeric_constant(bi_type,identifier)) { _set_error("Static constant '"+identifier.operator String()+"' not present in built-in type "+Variant::get_type_name(bi_type)+"."); @@ -264,23 +264,23 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ ConstantNode *cn = alloc_node<ConstantNode>(); cn->value=Variant::get_numeric_constant_value(bi_type,identifier); expr=cn; - tokenizer.advance(); + tokenizer->advance(); - } else if (tokenizer.get_token(1)==GDTokenizer::TK_PARENTHESIS_OPEN && (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE || tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER || tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_FUNC)) { + } else if (tokenizer->get_token(1)==GDTokenizer::TK_PARENTHESIS_OPEN && (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE || tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER || tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC)) { //function or constructor OperatorNode *op = alloc_node<OperatorNode>(); op->op=OperatorNode::OP_CALL; - if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE) { + if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE) { TypeNode *tn = alloc_node<TypeNode>(); - tn->vtype=tokenizer.get_token_type(); + tn->vtype=tokenizer->get_token_type(); op->arguments.push_back(tn); - } else if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_FUNC) { + } else if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC) { BuiltInFunctionNode *bn = alloc_node<BuiltInFunctionNode>(); - bn->function=tokenizer.get_token_built_in_func(); + bn->function=tokenizer->get_token_built_in_func(); op->arguments.push_back(bn); } else { @@ -288,25 +288,25 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ op->arguments.push_back(self); IdentifierNode* id = alloc_node<IdentifierNode>(); - id->name=tokenizer.get_token_identifier(); + id->name=tokenizer->get_token_identifier(); op->arguments.push_back(id); } - tokenizer.advance(2); + tokenizer->advance(2); if (!_parse_arguments(op,op->arguments,p_static)) return NULL; expr=op; - } else if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER) { + } else if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { //identifier (reference) IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name=tokenizer.get_token_identifier(); - tokenizer.advance(); + id->name=tokenizer->get_token_identifier(); + tokenizer->advance(); expr=id; - } else if (/*tokenizer.get_token()==GDTokenizer::TK_OP_ADD ||*/ tokenizer.get_token()==GDTokenizer::TK_OP_SUB || tokenizer.get_token()==GDTokenizer::TK_OP_NOT || tokenizer.get_token()==GDTokenizer::TK_OP_BIT_INVERT) { + } else if (/*tokenizer->get_token()==GDTokenizer::TK_OP_ADD ||*/ tokenizer->get_token()==GDTokenizer::TK_OP_SUB || tokenizer->get_token()==GDTokenizer::TK_OP_NOT || tokenizer->get_token()==GDTokenizer::TK_OP_BIT_INVERT) { //single prefix operators like !expr -expr ++expr --expr OperatorNode *op = alloc_node<OperatorNode>(); @@ -314,7 +314,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ Expression e; e.is_op=true; - switch(tokenizer.get_token()) { + switch(tokenizer->get_token()) { case GDTokenizer::TK_OP_SUB: e.op=OperatorNode::OP_NEG; break; case GDTokenizer::TK_OP_NOT: e.op=OperatorNode::OP_NOT; break; case GDTokenizer::TK_OP_BIT_INVERT: e.op=OperatorNode::OP_BIT_INVERT;; break; @@ -322,9 +322,9 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } - tokenizer.advance(); + tokenizer->advance(); - if (e.op!=OperatorNode::OP_NOT && tokenizer.get_token()==GDTokenizer::TK_OP_NOT) { + if (e.op!=OperatorNode::OP_NOT && tokenizer->get_token()==GDTokenizer::TK_OP_NOT) { _set_error("Misplaced 'not'."); return NULL; } @@ -339,34 +339,34 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ op->arguments.push_back(subexpr); expr=op;*/ - } else if (tokenizer.get_token()==GDTokenizer::TK_BRACKET_OPEN) { + } else if (tokenizer->get_token()==GDTokenizer::TK_BRACKET_OPEN) { // array - tokenizer.advance(); + tokenizer->advance(); ArrayNode *arr = alloc_node<ArrayNode>(); bool expecting_comma=false; while(true) { - if (tokenizer.get_token()==GDTokenizer::TK_EOF) { + if (tokenizer->get_token()==GDTokenizer::TK_EOF) { _set_error("Unterminated array"); return NULL; - } else if (tokenizer.get_token()==GDTokenizer::TK_BRACKET_CLOSE) { - tokenizer.advance(); + } else if (tokenizer->get_token()==GDTokenizer::TK_BRACKET_CLOSE) { + tokenizer->advance(); break; - } else if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) { + } else if (tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { - tokenizer.advance(); //ignore newline - } else if (tokenizer.get_token()==GDTokenizer::TK_COMMA) { + tokenizer->advance(); //ignore newline + } else if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { if (!expecting_comma) { _set_error("expression or ']' expected"); return NULL; } expecting_comma=false; - tokenizer.advance(); //ignore newline + tokenizer->advance(); //ignore newline } else { //parse expression if (expecting_comma) { @@ -382,9 +382,9 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } expr=arr; - } else if (tokenizer.get_token()==GDTokenizer::TK_CURLY_BRACKET_OPEN) { + } else if (tokenizer->get_token()==GDTokenizer::TK_CURLY_BRACKET_OPEN) { // array - tokenizer.advance(); + tokenizer->advance(); DictionaryNode *dict = alloc_node<DictionaryNode>(); @@ -403,12 +403,12 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ while(true) { - if (tokenizer.get_token()==GDTokenizer::TK_EOF) { + if (tokenizer->get_token()==GDTokenizer::TK_EOF) { _set_error("Unterminated dictionary"); return NULL; - } else if (tokenizer.get_token()==GDTokenizer::TK_CURLY_BRACKET_CLOSE) { + } else if (tokenizer->get_token()==GDTokenizer::TK_CURLY_BRACKET_CLOSE) { if (expecting==DICT_EXPECT_COLON) { _set_error("':' expected"); @@ -418,12 +418,12 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ _set_error("value expected"); return NULL; } - tokenizer.advance(); + tokenizer->advance(); break; - } else if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) { + } else if (tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { - tokenizer.advance(); //ignore newline - } else if (tokenizer.get_token()==GDTokenizer::TK_COMMA) { + tokenizer->advance(); //ignore newline + } else if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { if (expecting==DICT_EXPECT_KEY) { _set_error("key or '}' expected"); @@ -439,9 +439,9 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } expecting=DICT_EXPECT_KEY; - tokenizer.advance(); //ignore newline + tokenizer->advance(); //ignore newline - } else if (tokenizer.get_token()==GDTokenizer::TK_COLON) { + } else if (tokenizer->get_token()==GDTokenizer::TK_COLON) { if (expecting==DICT_EXPECT_KEY) { _set_error("key or '}' expected"); @@ -457,7 +457,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } expecting=DICT_EXPECT_VALUE; - tokenizer.advance(); //ignore newline + tokenizer->advance(); //ignore newline } else { if (expecting==DICT_EXPECT_COMMA) { @@ -471,12 +471,12 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ if (expecting==DICT_EXPECT_KEY) { - if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token(1)==GDTokenizer::TK_OP_ASSIGN) { + if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1)==GDTokenizer::TK_OP_ASSIGN) { //lua style identifier, easier to write ConstantNode *cn = alloc_node<ConstantNode>(); - cn->value = tokenizer.get_token_identifier(); + cn->value = tokenizer->get_token_identifier(); key = cn; - tokenizer.advance(2); + tokenizer->advance(2); expecting=DICT_EXPECT_VALUE; } else { //python/js style more flexible @@ -506,10 +506,10 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ expr=dict; - } else if (tokenizer.get_token()==GDTokenizer::TK_PERIOD && tokenizer.get_token(1)==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) { + } else if (tokenizer->get_token()==GDTokenizer::TK_PERIOD && tokenizer->get_token(1)==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) { // parent call - tokenizer.advance(); //goto identifier + tokenizer->advance(); //goto identifier OperatorNode *op = alloc_node<OperatorNode>(); op->op=OperatorNode::OP_PARENT_CALL; @@ -519,10 +519,10 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ forbidden for now */ IdentifierNode* id = alloc_node<IdentifierNode>(); - id->name=tokenizer.get_token_identifier(); + id->name=tokenizer->get_token_identifier(); op->arguments.push_back(id); - tokenizer.advance(2); + tokenizer->advance(2); if (!_parse_arguments(op,op->arguments,p_static)) return NULL; @@ -534,7 +534,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ print_line("found bug?"); - _set_error("Error parsing expression, misplaced: "+String(tokenizer.get_token_name(tokenizer.get_token()))); + _set_error("Error parsing expression, misplaced: "+String(tokenizer->get_token_name(tokenizer->get_token()))); return NULL; //nothing } @@ -553,31 +553,31 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ //expressions can be indexed any number of times - if (tokenizer.get_token()==GDTokenizer::TK_PERIOD) { + if (tokenizer->get_token()==GDTokenizer::TK_PERIOD) { //indexing using "." - if (tokenizer.get_token(1)!=GDTokenizer::TK_IDENTIFIER && tokenizer.get_token(1)!=GDTokenizer::TK_BUILT_IN_FUNC ) { + if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1)!=GDTokenizer::TK_BUILT_IN_FUNC ) { _set_error("Expected identifier as member"); return NULL; - } else if (tokenizer.get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) { + } else if (tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) { //call!! OperatorNode * op = alloc_node<OperatorNode>(); op->op=OperatorNode::OP_CALL; IdentifierNode * id = alloc_node<IdentifierNode>(); - if (tokenizer.get_token(1)==GDTokenizer::TK_BUILT_IN_FUNC ) { + if (tokenizer->get_token(1)==GDTokenizer::TK_BUILT_IN_FUNC ) { //small hack so built in funcs don't obfuscate methods - id->name=GDFunctions::get_func_name(tokenizer.get_token_built_in_func(1)); + id->name=GDFunctions::get_func_name(tokenizer->get_token_built_in_func(1)); } else { - id->name=tokenizer.get_token_identifier(1); + id->name=tokenizer->get_token_identifier(1); } op->arguments.push_back(expr); // call what op->arguments.push_back(id); // call func //get arguments - tokenizer.advance(3); + tokenizer->advance(3); if (!_parse_arguments(op,op->arguments,p_static)) return NULL; expr=op; @@ -588,36 +588,36 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ op->op=OperatorNode::OP_INDEX_NAMED; IdentifierNode * id = alloc_node<IdentifierNode>(); - id->name=tokenizer.get_token_identifier(1); + id->name=tokenizer->get_token_identifier(1); op->arguments.push_back(expr); op->arguments.push_back(id); expr=op; - tokenizer.advance(2); + tokenizer->advance(2); } - } else if (tokenizer.get_token()==GDTokenizer::TK_BRACKET_OPEN) { + } else if (tokenizer->get_token()==GDTokenizer::TK_BRACKET_OPEN) { //indexing using "[]" OperatorNode * op = alloc_node<OperatorNode>(); op->op=OperatorNode::OP_INDEX; - tokenizer.advance(1); + tokenizer->advance(1); Node *subexpr = _parse_expression(op,p_static); if (!subexpr) { return NULL; } - if (tokenizer.get_token()!=GDTokenizer::TK_BRACKET_CLOSE) { + if (tokenizer->get_token()!=GDTokenizer::TK_BRACKET_CLOSE) { _set_error("Expected ']'"); return NULL; } op->arguments.push_back(expr); op->arguments.push_back(subexpr); - tokenizer.advance(1); + tokenizer->advance(1); expr=op; } else @@ -641,7 +641,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ //assign, if allowed is only alowed on the first operator #define _VALIDATE_ASSIGN if (!p_allow_assign) { _set_error("Unexpected assign."); return NULL; } p_allow_assign=false; - switch(tokenizer.get_token()) { //see operator + switch(tokenizer->get_token()) { //see operator case GDTokenizer::TK_OP_IN: op=OperatorNode::OP_IN; break; case GDTokenizer::TK_OP_EQUAL: op=OperatorNode::OP_EQUAL ; break; @@ -682,7 +682,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ e.is_op=true; e.op=op; expression.push_back(e); - tokenizer.advance(); + tokenizer->advance(); } else { break; } @@ -1190,18 +1190,18 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line=tokenizer.get_token_line(); + nl->line=tokenizer->get_token_line(); p_block->statements.push_back(nl); #endif while(true) { - GDTokenizer::Token token = tokenizer.get_token(); + GDTokenizer::Token token = tokenizer->get_token(); if (error_set) return; if (indent_level>tab_level.back()->get()) { - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); return; //go back a level } @@ -1209,7 +1209,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { case GDTokenizer::TK_EOF: - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); case GDTokenizer::TK_ERROR: { return; //go back @@ -1219,38 +1219,38 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { case GDTokenizer::TK_NEWLINE: { NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line=tokenizer.get_token_line(); + nl->line=tokenizer->get_token_line(); p_block->statements.push_back(nl); if (!_parse_newline()) { if (!error_set) { - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); } return; } } break; case GDTokenizer::TK_CF_PASS: { - if (tokenizer.get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE ) { + if (tokenizer->get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE ) { _set_error("Expected ';' or <NewLine>."); return; } - tokenizer.advance(); + tokenizer->advance(); } break; case GDTokenizer::TK_PR_VAR: { //variale declaration and (eventual) initialization - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { _set_error("Expected identifier for local variable name."); return; } - StringName n = tokenizer.get_token_identifier(); - tokenizer.advance(); + StringName n = tokenizer->get_token_identifier(); + tokenizer->advance(); p_block->variables.push_back(n); //line? - p_block->variable_lines.push_back(tokenizer.get_token_line()); + p_block->variable_lines.push_back(tokenizer->get_token_line()); //must know when the local variable is declared @@ -1260,9 +1260,9 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { Node *assigned=NULL; - if (tokenizer.get_token()==GDTokenizer::TK_OP_ASSIGN) { + if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) { - tokenizer.advance(); + tokenizer->advance(); Node *subexpr=NULL; subexpr = _parse_and_reduce_expression(p_block,p_static); @@ -1294,7 +1294,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } break; case GDTokenizer::TK_CF_IF: { - tokenizer.advance(); + tokenizer->advance(); Node *condition = _parse_and_reduce_expression(p_block,p_static); if (!condition) return; @@ -1308,7 +1308,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { p_block->sub_blocks.push_back(cf_if->body); if (!_enter_indent_block(cf_if->body)) { - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); return; } @@ -1319,16 +1319,16 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { while(true) { - while(tokenizer.get_token()==GDTokenizer::TK_NEWLINE) { - tokenizer.advance(); + while(tokenizer->get_token()==GDTokenizer::TK_NEWLINE) { + tokenizer->advance(); } if (tab_level.back()->get() < indent_level) { //not at current indent level - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); return; } - if (tokenizer.get_token()==GDTokenizer::TK_CF_ELIF) { + if (tokenizer->get_token()==GDTokenizer::TK_CF_ELIF) { if (tab_level.back()->get() > indent_level) { @@ -1336,7 +1336,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { return; } - tokenizer.advance(); + tokenizer->advance(); cf_if->body_else=alloc_node<BlockNode>(); p_block->sub_blocks.push_back(cf_if->body_else); @@ -1358,7 +1358,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { if (!_enter_indent_block(cf_if->body)) { - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); return; } @@ -1367,7 +1367,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { return; - } else if (tokenizer.get_token()==GDTokenizer::TK_CF_ELSE) { + } else if (tokenizer->get_token()==GDTokenizer::TK_CF_ELSE) { if (tab_level.back()->get() > indent_level) { @@ -1376,12 +1376,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } - tokenizer.advance(); + tokenizer->advance(); cf_if->body_else=alloc_node<BlockNode>(); p_block->sub_blocks.push_back(cf_if->body_else); if (!_enter_indent_block(cf_if->body_else)) { - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); return; } _parse_block(cf_if->body_else,p_static); @@ -1400,7 +1400,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } break; case GDTokenizer::TK_CF_WHILE: { - tokenizer.advance(); + tokenizer->advance(); Node *condition = _parse_and_reduce_expression(p_block,p_static); if (!condition) return; @@ -1414,7 +1414,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { p_block->sub_blocks.push_back(cf_while->body); if (!_enter_indent_block(cf_while->body)) { - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); return; } @@ -1425,24 +1425,24 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } break; case GDTokenizer::TK_CF_FOR: { - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) { + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { _set_error("identifier expected after 'for'"); } IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name=tokenizer.get_token_identifier(); + id->name=tokenizer->get_token_identifier(); - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_OP_IN) { + if (tokenizer->get_token()!=GDTokenizer::TK_OP_IN) { _set_error("'in' expected after identifier"); return; } - tokenizer.advance(); + tokenizer->advance(); Node *container = _parse_and_reduce_expression(p_block,p_static); if (!container) @@ -1458,7 +1458,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { p_block->sub_blocks.push_back(cf_for->body); if (!_enter_indent_block(cf_for->body)) { - p_block->end_line=tokenizer.get_token_line(); + p_block->end_line=tokenizer->get_token_line(); return; } @@ -1469,7 +1469,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } break; case GDTokenizer::TK_CF_CONTINUE: { - tokenizer.advance(); + tokenizer->advance(); ControlFlowNode *cf_continue = alloc_node<ControlFlowNode>(); cf_continue->cf_type=ControlFlowNode::CF_CONTINUE; p_block->statements.push_back(cf_continue); @@ -1480,7 +1480,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } break; case GDTokenizer::TK_CF_BREAK: { - tokenizer.advance(); + tokenizer->advance(); ControlFlowNode *cf_break = alloc_node<ControlFlowNode>(); cf_break->cf_type=ControlFlowNode::CF_BREAK; p_block->statements.push_back(cf_break); @@ -1491,13 +1491,13 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } break; case GDTokenizer::TK_CF_RETURN: { - tokenizer.advance(); + tokenizer->advance(); ControlFlowNode *cf_return = alloc_node<ControlFlowNode>(); cf_return->cf_type=ControlFlowNode::CF_RETURN; - if (tokenizer.get_token()==GDTokenizer::TK_SEMICOLON || tokenizer.get_token()==GDTokenizer::TK_NEWLINE || tokenizer.get_token()==GDTokenizer::TK_EOF) { + if (tokenizer->get_token()==GDTokenizer::TK_SEMICOLON || tokenizer->get_token()==GDTokenizer::TK_NEWLINE || tokenizer->get_token()==GDTokenizer::TK_EOF) { //expect end of statement p_block->statements.push_back(cf_return); if (!_end_statement()) { @@ -1520,7 +1520,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { } break; case GDTokenizer::TK_PR_ASSERT: { - tokenizer.advance(); + tokenizer->advance(); Node *condition = _parse_and_reduce_expression(p_block,p_static); if (!condition) return; @@ -1548,11 +1548,11 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { /* case GDTokenizer::TK_CF_LOCAL: { - if (tokenizer.get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE ) { + if (tokenizer->get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE ) { _set_error("Expected ';' or <NewLine>."); } - tokenizer.advance(); + tokenizer->advance(); } break; */ @@ -1563,9 +1563,9 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { bool GDParser::_parse_newline() { - if (tokenizer.get_token(1)!=GDTokenizer::TK_EOF && tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE) { + if (tokenizer->get_token(1)!=GDTokenizer::TK_EOF && tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE) { - int indent = tokenizer.get_token_line_indent(); + int indent = tokenizer->get_token_line_indent(); int current_indent = tab_level.back()->get(); if (indent>current_indent) { @@ -1593,12 +1593,12 @@ bool GDParser::_parse_newline() { current_indent = tab_level.back()->get(); } - tokenizer.advance(); + tokenizer->advance(); return false; } } - tokenizer.advance(); + tokenizer->advance(); return true; } @@ -1622,11 +1622,11 @@ void GDParser::_parse_extends(ClassNode *p_class) { p_class->extends_used=true; //see if inheritance happens from a file - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT) { + if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT) { - Variant constant = tokenizer.get_token_constant(); + Variant constant = tokenizer->get_token_constant(); if (constant.get_type()!=Variant::STRING) { _set_error("'extends' constant must be a string."); @@ -1634,27 +1634,27 @@ void GDParser::_parse_extends(ClassNode *p_class) { } p_class->extends_file=constant; - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_PERIOD) { + if (tokenizer->get_token()!=GDTokenizer::TK_PERIOD) { return; } else - tokenizer.advance(); + tokenizer->advance(); } while(true) { - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) { + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { _set_error("Invalid 'extends' syntax, expected string constant (path) and/or identifier (parent class)."); return; } - StringName identifier=tokenizer.get_token_identifier(); + StringName identifier=tokenizer->get_token_identifier(); p_class->extends_class.push_back(identifier); - tokenizer.advance(1); - if (tokenizer.get_token()!=GDTokenizer::TK_PERIOD) + tokenizer->advance(1); + if (tokenizer->get_token()!=GDTokenizer::TK_PERIOD) return; } @@ -1666,19 +1666,19 @@ void GDParser::_parse_class(ClassNode *p_class) { while(true) { - GDTokenizer::Token token = tokenizer.get_token(); + GDTokenizer::Token token = tokenizer->get_token(); if (error_set) return; if (indent_level>tab_level.back()->get()) { - p_class->end_line=tokenizer.get_token_line(); + p_class->end_line=tokenizer->get_token_line(); return; //go back a level } switch(token) { case GDTokenizer::TK_EOF: - p_class->end_line=tokenizer.get_token_line(); + p_class->end_line=tokenizer->get_token_line(); case GDTokenizer::TK_ERROR: { return; //go back //end of file! @@ -1686,7 +1686,7 @@ void GDParser::_parse_class(ClassNode *p_class) { case GDTokenizer::TK_NEWLINE: { if (!_parse_newline()) { if (!error_set) { - p_class->end_line=tokenizer.get_token_line(); + p_class->end_line=tokenizer->get_token_line(); } return; } @@ -1709,7 +1709,7 @@ void GDParser::_parse_class(ClassNode *p_class) { } p_class->tool=true; - tokenizer.advance(); + tokenizer->advance(); } break; case GDTokenizer::TK_PR_CLASS: { @@ -1718,13 +1718,13 @@ void GDParser::_parse_class(ClassNode *p_class) { StringName name; StringName extends; - if (tokenizer.get_token(1)!=GDTokenizer::TK_IDENTIFIER) { + if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER) { _set_error("'class' syntax: 'class <Name>:' or 'class <Name> extends <BaseClass>:'"); return; } - name = tokenizer.get_token_identifier(1); - tokenizer.advance(2); + name = tokenizer->get_token_identifier(1); + tokenizer->advance(2); ClassNode *newclass = alloc_node<ClassNode>(); newclass->initializer = alloc_node<BlockNode>(); @@ -1733,7 +1733,7 @@ void GDParser::_parse_class(ClassNode *p_class) { p_class->subclasses.push_back(newclass); - if (tokenizer.get_token()==GDTokenizer::TK_PR_EXTENDS) { + if (tokenizer->get_token()==GDTokenizer::TK_PR_EXTENDS) { _parse_extends(newclass); if (error_set) @@ -1751,12 +1751,12 @@ void GDParser::_parse_class(ClassNode *p_class) { /* this is for functions.... case GDTokenizer::TK_CF_PASS: { - tokenizer.advance(1); + tokenizer->advance(1); } break; */ case GDTokenizer::TK_PR_STATIC: { - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_PR_FUNCTION) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_PR_FUNCTION) { _set_error("Expected 'func'."); return; @@ -1767,19 +1767,19 @@ void GDParser::_parse_class(ClassNode *p_class) { bool _static=false; - if (tokenizer.get_token(-1)==GDTokenizer::TK_PR_STATIC) { + if (tokenizer->get_token(-1)==GDTokenizer::TK_PR_STATIC) { _static=true; } - if (tokenizer.get_token(1)!=GDTokenizer::TK_IDENTIFIER) { + if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER) { _set_error("Expected identifier after 'func' (syntax: 'func <identifier>([arguments]):' )."); return; } - StringName name = tokenizer.get_token_identifier(1); + StringName name = tokenizer->get_token_identifier(1); for(int i=0;i<p_class->functions.size();i++) { if (p_class->functions[i]->name==name) { @@ -1791,56 +1791,56 @@ void GDParser::_parse_class(ClassNode *p_class) { _set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->static_functions[i]->line)+")."); } } - tokenizer.advance(2); + tokenizer->advance(2); - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { _set_error("Expected '(' after identifier (syntax: 'func <identifier>([arguments]):' )."); return; } - tokenizer.advance(); + tokenizer->advance(); Vector<StringName> arguments; Vector<Node*> default_values; - int fnline = tokenizer.get_token_line(); + int fnline = tokenizer->get_token_line(); - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { //has arguments bool defaulting=false; while(true) { - if (tokenizer.get_token()==GDTokenizer::TK_PR_VAR) { + if (tokenizer->get_token()==GDTokenizer::TK_PR_VAR) { - tokenizer.advance(); //var before the identifier is allowed + tokenizer->advance(); //var before the identifier is allowed } - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) { + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { _set_error("Expected identifier for argument."); return; } - StringName argname=tokenizer.get_token_identifier(); + StringName argname=tokenizer->get_token_identifier(); arguments.push_back(argname); - tokenizer.advance(); + tokenizer->advance(); - if (defaulting && tokenizer.get_token()!=GDTokenizer::TK_OP_ASSIGN) { + if (defaulting && tokenizer->get_token()!=GDTokenizer::TK_OP_ASSIGN) { _set_error("Default parameter expected."); return; } - //tokenizer.advance(); + //tokenizer->advance(); - if (tokenizer.get_token()==GDTokenizer::TK_OP_ASSIGN) { + if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) { defaulting=true; - tokenizer.advance(1); + tokenizer->advance(1); Node *defval=NULL; defval=_parse_and_reduce_expression(p_class,_static); @@ -1864,10 +1864,10 @@ void GDParser::_parse_class(ClassNode *p_class) { default_values.push_back(on); } - if (tokenizer.get_token()==GDTokenizer::TK_COMMA) { - tokenizer.advance(); + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { + tokenizer->advance(); continue; - } else if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + } else if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ',' or ')'."); return; @@ -1879,7 +1879,7 @@ void GDParser::_parse_class(ClassNode *p_class) { } - tokenizer.advance(); + tokenizer->advance(); BlockNode *block = alloc_node<BlockNode>(); @@ -1895,24 +1895,24 @@ void GDParser::_parse_class(ClassNode *p_class) { id->name="_init"; cparent->arguments.push_back(id); - if (tokenizer.get_token()==GDTokenizer::TK_PERIOD) { - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { + if (tokenizer->get_token()==GDTokenizer::TK_PERIOD) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { _set_error("expected '(' for parent constructor arguments."); } - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { //has arguments while(true) { Node *arg = _parse_and_reduce_expression(p_class,_static); cparent->arguments.push_back(arg); - if (tokenizer.get_token()==GDTokenizer::TK_COMMA) { - tokenizer.advance(); + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { + tokenizer->advance(); continue; - } else if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + } else if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ',' or ')'."); return; @@ -1923,12 +1923,12 @@ void GDParser::_parse_class(ClassNode *p_class) { } } - tokenizer.advance(); + tokenizer->advance(); } } else { - if (tokenizer.get_token()==GDTokenizer::TK_PERIOD) { + if (tokenizer->get_token()==GDTokenizer::TK_PERIOD) { _set_error("Parent constructor call found for a class without inheritance."); return; @@ -1963,41 +1963,41 @@ void GDParser::_parse_class(ClassNode *p_class) { } break; case GDTokenizer::TK_PR_EXPORT: { - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) { + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) { - tokenizer.advance(); - if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE) { + tokenizer->advance(); + if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE) { - Variant::Type type = tokenizer.get_token_type(); + Variant::Type type = tokenizer->get_token_type(); if (type==Variant::NIL) { _set_error("Can't export null type."); return; } current_export.type=type; - tokenizer.advance(); - if (tokenizer.get_token()==GDTokenizer::TK_COMMA) { + tokenizer->advance(); + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { // hint expected next! - tokenizer.advance(); + tokenizer->advance(); switch(current_export.type) { case Variant::INT: { - if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT && tokenizer.get_token_constant().get_type()==Variant::STRING) { + if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type()==Variant::STRING) { //enumeration current_export.hint=PROPERTY_HINT_ENUM; bool first=true; while(true) { - if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) { + if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type()!=Variant::STRING) { current_export=PropertyInfo(); _set_error("Expected a string constant in enumeration hint."); } - String c = tokenizer.get_token_constant(); + String c = tokenizer->get_token_constant(); if (!first) current_export.hint_string+=","; else @@ -2005,16 +2005,16 @@ void GDParser::_parse_class(ClassNode *p_class) { current_export.hint_string+=c.xml_escape(); - tokenizer.advance(); - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) + tokenizer->advance(); + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) break; - if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) { + if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { current_export=PropertyInfo(); _set_error("Expected ')' or ',' in enumeration hint."); } - tokenizer.advance(); + tokenizer->advance(); } @@ -2024,7 +2024,7 @@ void GDParser::_parse_class(ClassNode *p_class) { }; case Variant::REAL: { - if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer.get_token_constant().is_num()) { + if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) { current_export=PropertyInfo(); _set_error("Expected a range in numeric hint."); @@ -2033,119 +2033,119 @@ void GDParser::_parse_class(ClassNode *p_class) { //enumeration current_export.hint=PROPERTY_HINT_RANGE; - current_export.hint_string=tokenizer.get_token_constant().operator String(); - tokenizer.advance(); + current_export.hint_string=tokenizer->get_token_constant().operator String(); + tokenizer->advance(); - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { current_export.hint_string="0,"+current_export.hint_string; break; } - if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) { + if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { current_export=PropertyInfo(); _set_error("Expected ',' or ')' in numeric range hint."); } - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer.get_token_constant().is_num()) { + if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) { current_export=PropertyInfo(); _set_error("Expected a number as upper bound in numeric range hint."); } - current_export.hint_string+=","+tokenizer.get_token_constant().operator String(); - tokenizer.advance(); + current_export.hint_string+=","+tokenizer->get_token_constant().operator String(); + tokenizer->advance(); - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) break; - if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) { + if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { current_export=PropertyInfo(); _set_error("Expected ',' or ')' in numeric range hint."); } - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer.get_token_constant().is_num()) { + if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) { current_export=PropertyInfo(); _set_error("Expected a number as step in numeric range hint."); } - current_export.hint_string+=","+tokenizer.get_token_constant().operator String(); - tokenizer.advance(); + current_export.hint_string+=","+tokenizer->get_token_constant().operator String(); + tokenizer->advance(); } break; case Variant::STRING: { - if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT && tokenizer.get_token_constant().get_type()==Variant::STRING) { + if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type()==Variant::STRING) { //enumeration current_export.hint=PROPERTY_HINT_ENUM; bool first=true; while(true) { - if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) { + if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type()!=Variant::STRING) { current_export=PropertyInfo(); _set_error("Expected a string constant in enumeration hint."); } - String c = tokenizer.get_token_constant(); + String c = tokenizer->get_token_constant(); if (!first) current_export.hint_string+=","; else first=false; current_export.hint_string+=c.xml_escape(); - tokenizer.advance(); - if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) + tokenizer->advance(); + if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) break; - if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) { + if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { current_export=PropertyInfo(); _set_error("Expected ')' or ',' in enumeration hint."); return; } - tokenizer.advance(); + tokenizer->advance(); } break; } - if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token_identifier()=="DIR") { + if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="DIR") { current_export.hint=PROPERTY_HINT_DIR; - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ')' in hint."); return; } break; } - if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token_identifier()=="FILE") { + if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="FILE") { current_export.hint=PROPERTY_HINT_FILE; - tokenizer.advance(); + tokenizer->advance(); - if (tokenizer.get_token()==GDTokenizer::TK_COMMA) { + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type()!=Variant::STRING) { _set_error("Expected string constant with filter"); return; } - current_export.hint_string=tokenizer.get_token_constant(); - tokenizer.advance(); + current_export.hint_string=tokenizer->get_token_constant(); + tokenizer->advance(); } - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ')' in hint."); return; } @@ -2154,14 +2154,14 @@ void GDParser::_parse_class(ClassNode *p_class) { } break; case Variant::COLOR: { - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER ) { + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER ) { current_export=PropertyInfo(); _set_error("Color type hint expects RGB or RGBA as hints"); return; } - String identifier = tokenizer.get_token_identifier(); + String identifier = tokenizer->get_token_identifier(); if (identifier=="RGB") { current_export.hint=PROPERTY_HINT_COLOR_NO_ALPHA; } else if (identifier=="RGBA") { @@ -2171,7 +2171,7 @@ void GDParser::_parse_class(ClassNode *p_class) { _set_error("Color type hint expects RGB or RGBA as hints"); return; } - tokenizer.advance(); + tokenizer->advance(); } break; default: { @@ -2184,9 +2184,9 @@ void GDParser::_parse_class(ClassNode *p_class) { } - } else if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER) { + } else if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { - String identifier = tokenizer.get_token_identifier(); + String identifier = tokenizer->get_token_identifier(); if (!ObjectTypeDB::is_type(identifier,"Resource")) { current_export=PropertyInfo(); @@ -2197,10 +2197,10 @@ void GDParser::_parse_class(ClassNode *p_class) { current_export.hint=PROPERTY_HINT_RESOURCE_TYPE; current_export.hint_string=identifier; - tokenizer.advance(); + tokenizer->advance(); } - if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) { current_export=PropertyInfo(); _set_error("Expected ')' or ',' after export hint."); @@ -2208,11 +2208,11 @@ void GDParser::_parse_class(ClassNode *p_class) { } - tokenizer.advance(); + tokenizer->advance(); } - if (tokenizer.get_token()!=GDTokenizer::TK_PR_VAR) { + if (tokenizer->get_token()!=GDTokenizer::TK_PR_VAR) { current_export=PropertyInfo(); _set_error("Expected 'var'."); @@ -2224,26 +2224,26 @@ void GDParser::_parse_class(ClassNode *p_class) { //variale declaration and (eventual) initialization ClassNode::Member member; - bool autoexport = tokenizer.get_token(-1)==GDTokenizer::TK_PR_EXPORT; + bool autoexport = tokenizer->get_token(-1)==GDTokenizer::TK_PR_EXPORT; if (current_export.type!=Variant::NIL) { member._export=current_export; current_export=PropertyInfo(); } - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { _set_error("Expected identifier for member variable name."); return; } - member.identifier=tokenizer.get_token_identifier(); + member.identifier=tokenizer->get_token_identifier(); member._export.name=member.identifier; - tokenizer.advance(); + tokenizer->advance(); p_class->variables.push_back(member); - if (tokenizer.get_token()!=GDTokenizer::TK_OP_ASSIGN) { + if (tokenizer->get_token()!=GDTokenizer::TK_OP_ASSIGN) { if (autoexport) { @@ -2253,9 +2253,9 @@ void GDParser::_parse_class(ClassNode *p_class) { break; } #ifdef DEBUG_ENABLED - int line = tokenizer.get_token_line(); + int line = tokenizer->get_token_line(); #endif - tokenizer.advance(); + tokenizer->advance(); Node *subexpr=NULL; @@ -2324,22 +2324,22 @@ void GDParser::_parse_class(ClassNode *p_class) { ClassNode::Constant constant; - tokenizer.advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) { + tokenizer->advance(); + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { _set_error("Expected name (identifier) for constant."); return; } - constant.identifier=tokenizer.get_token_identifier(); - tokenizer.advance(); + constant.identifier=tokenizer->get_token_identifier(); + tokenizer->advance(); - if (tokenizer.get_token()!=GDTokenizer::TK_OP_ASSIGN) { + if (tokenizer->get_token()!=GDTokenizer::TK_OP_ASSIGN) { _set_error("Constant expects assignment."); return; } - tokenizer.advance(); + tokenizer->advance(); Node *subexpr=NULL; @@ -2362,7 +2362,7 @@ void GDParser::_parse_class(ClassNode *p_class) { default: { - _set_error(String()+"Unexpected token: "+tokenizer.get_token_name(tokenizer.get_token())+":"+tokenizer.get_token_identifier()); + _set_error(String()+"Unexpected token: "+tokenizer->get_token_name(tokenizer->get_token())+":"+tokenizer->get_token_identifier()); return; } break; @@ -2382,8 +2382,8 @@ void GDParser::_set_error(const String& p_error, int p_line, int p_column) { return; //allow no further errors error=p_error; - error_line=p_line<0?tokenizer.get_token_line():p_line; - error_column=p_column<0?tokenizer.get_token_column():p_column; + error_line=p_line<0?tokenizer->get_token_line():p_line; + error_column=p_column<0?tokenizer->get_token_column():p_column; error_set=true; } @@ -2402,11 +2402,10 @@ int GDParser::get_error_column() const { } -Error GDParser::parse(const String& p_code,const String& p_base_path) { +Error GDParser::_parse(const String& p_base_path) { - base_path=p_base_path; - tokenizer.set_code(p_code); + base_path=p_base_path; clear(); @@ -2416,9 +2415,9 @@ Error GDParser::parse(const String& p_code,const String& p_base_path) { _parse_class(main_class); - if (tokenizer.get_token()==GDTokenizer::TK_ERROR) { + if (tokenizer->get_token()==GDTokenizer::TK_ERROR) { error_set=false; - _set_error("Parse Error: "+tokenizer.get_token_error()); + _set_error("Parse Error: "+tokenizer->get_token_error()); } if (error_set) { @@ -2428,6 +2427,31 @@ Error GDParser::parse(const String& p_code,const String& p_base_path) { return OK; } +Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path) { + + GDTokenizerBuffer *tb = memnew( GDTokenizerBuffer ); + tb->set_code_buffer(p_bytecode); + tokenizer=tb; + Error ret = _parse(p_base_path); + memdelete(tb); + tokenizer=NULL; + return ret; +} + + +Error GDParser::parse(const String& p_code,const String& p_base_path) { + + + GDTokenizerText *tt = memnew( GDTokenizerText ); + tt->set_code(p_code); + + tokenizer=tt; + Error ret = _parse(p_base_path); + memdelete(tt); + tokenizer=NULL; + return ret; +} + const GDParser::Node *GDParser::get_parse_tree() const { return head; @@ -2459,6 +2483,7 @@ GDParser::GDParser() { head=NULL; list=NULL; + tokenizer=NULL; clear(); } diff --git a/script/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 8011495340..1925808cac 100644 --- a/script/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -343,10 +343,12 @@ public: ProgramNode() { type=TYPE_PROGRAM; } }; */ + + private: - GDTokenizer tokenizer; + GDTokenizer *tokenizer; Node *head; @@ -380,12 +382,15 @@ private: void _parse_class(ClassNode *p_class); bool _end_statement(); + Error _parse(const String& p_base_path); + public: String get_error() const; int get_error_line() const; int get_error_column() const; Error parse(const String& p_code,const String& p_base_path=""); + Error parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path=""); const Node *get_parse_tree() const; diff --git a/script/gdscript/gd_pretty_print.cpp b/modules/gdscript/gd_pretty_print.cpp index a5a993bb3a..a5a993bb3a 100644 --- a/script/gdscript/gd_pretty_print.cpp +++ b/modules/gdscript/gd_pretty_print.cpp diff --git a/script/gdscript/gd_pretty_print.h b/modules/gdscript/gd_pretty_print.h index fbf002295b..fbf002295b 100644 --- a/script/gdscript/gd_pretty_print.h +++ b/modules/gdscript/gd_pretty_print.h diff --git a/script/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index 5679e1e066..29857e6be6 100644 --- a/script/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -1416,7 +1416,7 @@ Error GDScript::reload() { String basedir=path; if (basedir=="") - basedir==get_path(); + basedir=get_path(); if (basedir!="") basedir=basedir.get_base_dir(); @@ -1560,6 +1560,49 @@ void GDScript::_bind_methods() { } + + +Error GDScript::load_byte_code(const String& p_path) { + + Vector<uint8_t> bytecode = FileAccess::get_file_as_array(p_path); + ERR_FAIL_COND_V(bytecode.size()==0,ERR_PARSE_ERROR); + path=p_path; + + String basedir=path; + + if (basedir=="") + basedir=get_path(); + + if (basedir!="") + basedir=basedir.get_base_dir(); + + valid=false; + GDParser parser; + Error err = parser.parse_bytecode(bytecode,basedir); + if (err) { + _err_print_error("GDScript::load_byte_code",path.empty()?"built-in":(const char*)path.utf8().get_data(),parser.get_error_line(),("Parse Error: "+parser.get_error()).utf8().get_data()); + ERR_FAIL_V(ERR_PARSE_ERROR); + } + + GDCompiler compiler; + err = compiler.compile(&parser,this); + + if (err) { + _err_print_error("GDScript::load_byte_code",path.empty()?"built-in":(const char*)path.utf8().get_data(),compiler.get_error_line(),("Compile Error: "+compiler.get_error()).utf8().get_data()); + ERR_FAIL_V(ERR_COMPILATION_FAILED); + } + + valid=true; + + for(Map<StringName,Ref<GDScript> >::Element *E=subclasses.front();E;E=E->next()) { + + _set_subclass_path(E->get(),path); + } + + return OK; +} + + Error GDScript::load_source_code(const String& p_path) { @@ -2153,24 +2196,39 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_orig Ref<GDScript> scriptres(script); - Error err = script->load_source_code(p_path); + if (p_path.ends_with(".gdc")) { - if (err!=OK) { + script->set_script_path(p_original_path); // script needs this. + script->set_path(p_original_path); + Error err = script->load_byte_code(p_path); - ERR_FAIL_COND_V(err!=OK, RES()); - } - script->set_script_path(p_original_path); // script needs this. - script->set_path(p_original_path); - //script->set_name(p_path.get_file()); + if (err!=OK) { + + ERR_FAIL_COND_V(err!=OK, RES()); + } + + } else { + Error err = script->load_source_code(p_path); - script->reload(); + if (err!=OK) { + + ERR_FAIL_COND_V(err!=OK, RES()); + } + + script->set_script_path(p_original_path); // script needs this. + script->set_path(p_original_path); + //script->set_name(p_path.get_file()); + + script->reload(); + } return scriptres; } void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("gd"); + p_extensions->push_back("gdc"); } bool ResourceFormatLoaderGDScript::handles_type(const String& p_type) const { @@ -2180,7 +2238,8 @@ bool ResourceFormatLoaderGDScript::handles_type(const String& p_type) const { String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const { - if (p_path.extension().to_lower()=="gd") + String el = p_path.extension().to_lower(); + if (el=="gd" || el=="gdc") return "GDScript"; return ""; } diff --git a/script/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 70dec4e8ee..55bc547e8d 100644 --- a/script/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -261,6 +261,7 @@ public: virtual String get_node_type() const; void set_script_path(const String& p_path) { path=p_path; } //because subclasses need a path too... Error load_source_code(const String& p_path); + Error load_byte_code(const String& p_path); virtual ScriptLanguage *get_language() const; diff --git a/script/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index f7320799a5..ff9be7926b 100644 --- a/script/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -29,6 +29,9 @@ #include "gd_tokenizer.h" #include "print_string.h" #include "gd_functions.h" +#include "io/marshalls.h" +#include "map.h" + const char* GDTokenizer::token_names[TK_MAX]={ "Empty", "Identifier", @@ -128,7 +131,7 @@ static bool _is_hex(CharType c) { return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'); } -void GDTokenizer::_make_token(Token p_type) { +void GDTokenizerText::_make_token(Token p_type) { TokenData &tk=tk_rb[tk_rb_pos]; @@ -138,7 +141,7 @@ void GDTokenizer::_make_token(Token p_type) { tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE; } -void GDTokenizer::_make_identifier(const StringName& p_identifier) { +void GDTokenizerText::_make_identifier(const StringName& p_identifier) { TokenData &tk=tk_rb[tk_rb_pos]; @@ -151,7 +154,7 @@ void GDTokenizer::_make_identifier(const StringName& p_identifier) { } -void GDTokenizer::_make_built_in_func(GDFunctions::Function p_func) { +void GDTokenizerText::_make_built_in_func(GDFunctions::Function p_func) { TokenData &tk=tk_rb[tk_rb_pos]; @@ -163,7 +166,7 @@ void GDTokenizer::_make_built_in_func(GDFunctions::Function p_func) { tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE; } -void GDTokenizer::_make_constant(const Variant& p_constant) { +void GDTokenizerText::_make_constant(const Variant& p_constant) { TokenData &tk=tk_rb[tk_rb_pos]; @@ -176,7 +179,7 @@ void GDTokenizer::_make_constant(const Variant& p_constant) { } -void GDTokenizer::_make_type(const Variant::Type& p_type) { +void GDTokenizerText::_make_type(const Variant::Type& p_type) { TokenData &tk=tk_rb[tk_rb_pos]; @@ -191,7 +194,7 @@ void GDTokenizer::_make_type(const Variant::Type& p_type) { } -void GDTokenizer::_make_error(const String& p_error) { +void GDTokenizerText::_make_error(const String& p_error) { error_flag=true; last_error=p_error; @@ -206,7 +209,7 @@ void GDTokenizer::_make_error(const String& p_error) { } -void GDTokenizer::_make_newline(int p_spaces) { +void GDTokenizerText::_make_newline(int p_spaces) { TokenData &tk=tk_rb[tk_rb_pos]; tk.type=TK_NEWLINE; @@ -216,7 +219,7 @@ void GDTokenizer::_make_newline(int p_spaces) { tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE; } -void GDTokenizer::_advance() { +void GDTokenizerText::_advance() { if (error_flag) { //parser broke @@ -859,7 +862,7 @@ void GDTokenizer::_advance() { } -void GDTokenizer::set_code(const String& p_code) { +void GDTokenizerText::set_code(const String& p_code) { code=p_code; len = p_code.length(); @@ -878,7 +881,7 @@ void GDTokenizer::set_code(const String& p_code) { _advance(); } -GDTokenizer::Token GDTokenizer::get_token(int p_offset) const { +GDTokenizerText::Token GDTokenizerText::get_token(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, TK_ERROR); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, TK_ERROR); @@ -886,7 +889,7 @@ GDTokenizer::Token GDTokenizer::get_token(int p_offset) const { return tk_rb[ofs].type; } -int GDTokenizer::get_token_line(int p_offset) const { +int GDTokenizerText::get_token_line(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, -1); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, -1); @@ -894,7 +897,7 @@ int GDTokenizer::get_token_line(int p_offset) const { return tk_rb[ofs].line; } -int GDTokenizer::get_token_column(int p_offset) const { +int GDTokenizerText::get_token_column(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, -1); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, -1); @@ -902,7 +905,7 @@ int GDTokenizer::get_token_column(int p_offset) const { return tk_rb[ofs].col; } -const Variant& GDTokenizer::get_token_constant(int p_offset) const { +const Variant& GDTokenizerText::get_token_constant(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, tk_rb[0].constant); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, tk_rb[0].constant); @@ -910,7 +913,7 @@ const Variant& GDTokenizer::get_token_constant(int p_offset) const { ERR_FAIL_COND_V(tk_rb[ofs].type!=TK_CONSTANT,tk_rb[0].constant); return tk_rb[ofs].constant; } -StringName GDTokenizer::get_token_identifier(int p_offset) const { +StringName GDTokenizerText::get_token_identifier(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, StringName()); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, StringName()); @@ -921,7 +924,7 @@ StringName GDTokenizer::get_token_identifier(int p_offset) const { } -GDFunctions::Function GDTokenizer::get_token_built_in_func(int p_offset) const { +GDFunctions::Function GDTokenizerText::get_token_built_in_func(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, GDFunctions::FUNC_MAX); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, GDFunctions::FUNC_MAX); @@ -932,7 +935,7 @@ GDFunctions::Function GDTokenizer::get_token_built_in_func(int p_offset) const { } -Variant::Type GDTokenizer::get_token_type(int p_offset) const { +Variant::Type GDTokenizerText::get_token_type(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, Variant::NIL); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, Variant::NIL); @@ -944,7 +947,7 @@ Variant::Type GDTokenizer::get_token_type(int p_offset) const { } -int GDTokenizer::get_token_line_indent(int p_offset) const { +int GDTokenizerText::get_token_line_indent(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, 0); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, 0); @@ -955,7 +958,7 @@ int GDTokenizer::get_token_line_indent(int p_offset) const { } -String GDTokenizer::get_token_error(int p_offset) const { +String GDTokenizerText::get_token_error(int p_offset) const { ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, String()); ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, String()); @@ -965,9 +968,377 @@ String GDTokenizer::get_token_error(int p_offset) const { return tk_rb[ofs].constant; } -void GDTokenizer::advance(int p_amount) { +void GDTokenizerText::advance(int p_amount) { ERR_FAIL_COND( p_amount <=0 ); for(int i=0;i<p_amount;i++) _advance(); } + + + + + + + + + + + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define BYTECODE_VERSION 1 + +Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> & p_buffer) { + + + const uint8_t *buf=p_buffer.ptr(); + int total_len=p_buffer.size(); + ERR_FAIL_COND_V( p_buffer.size()<24 || p_buffer[0]!='G' || p_buffer[1]!='D' || p_buffer[2]!='S' || p_buffer[3]!='C',ERR_INVALID_DATA); + + int version = decode_uint32(&buf[4]); + if (version>1) { + ERR_EXPLAIN("Bytecode is too New!"); + ERR_FAIL_COND_V(version>BYTECODE_VERSION,ERR_INVALID_DATA); + } + int identifier_count = decode_uint32(&buf[8]); + int constant_count = decode_uint32(&buf[12]); + int line_count = decode_uint32(&buf[16]); + int token_count = decode_uint32(&buf[20]); + + const uint8_t *b=buf; + + b=&buf[24]; + total_len-=24; + + identifiers.resize(identifier_count); + for(int i=0;i<identifier_count;i++) { + + int len = decode_uint32(b); + ERR_FAIL_COND_V(len>total_len,ERR_INVALID_DATA); + b+=4; + Vector<uint8_t> cs; + cs.resize(len); + for(int j=0;j<len;j++) { + cs[j]=b[j]^0xb6; + } + + cs[cs.size()-1]=0; + String s; + s.parse_utf8((const char*)cs.ptr()); + b+=len; + total_len-=len+4; + identifiers[i]=s; + } + + constants.resize(constant_count); + for(int i=0;i<constant_count;i++) { + + Variant v; + int len; + Error err = decode_variant(v,b,total_len,&len); + if (err) + return err; + b+=len; + total_len-=len; + constants[i]=v; + + } + + ERR_FAIL_COND_V(line_count*8>total_len,ERR_INVALID_DATA); + + for(int i=0;i<line_count;i++) { + + uint32_t token=decode_uint32(b); + b+=4; + uint32_t linecol=decode_uint32(b); + b+=4; + + lines.insert(token,linecol); + total_len-=8; + } + + tokens.resize(token_count); + + for(int i=0;i<token_count;i++) { + + ERR_FAIL_COND_V( total_len < 1, ERR_INVALID_DATA); + + if ((*b)&TOKEN_BYTE_MASK) { //little endian always + ERR_FAIL_COND_V( total_len < 4, ERR_INVALID_DATA); + + tokens[i]=decode_uint32(b)&~TOKEN_BYTE_MASK; + b+=4; + } else { + tokens[i]=*b; + b+=1; + total_len--; + } + } + + token=0; + + return OK; + +} + + +Vector<uint8_t> GDTokenizerBuffer::parse_code_string(const String& p_code) { + + Vector<uint8_t> buf; + + + Map<StringName,int> identifier_map; + HashMap<Variant,int,VariantHasher> constant_map; + Map<uint32_t,int> line_map; + Vector<uint32_t> token_array; + + GDTokenizerText tt; + tt.set_code(p_code); + int line=-1; + int col=0; + + while(true) { + + if (tt.get_token_line()!=line) { + + line=tt.get_token_line(); + line_map[line]=token_array.size(); + } + + uint32_t token=tt.get_token(); + switch(tt.get_token()) { + + case TK_IDENTIFIER: { + StringName id = tt.get_token_identifier(); + if (!identifier_map.has(id)) { + int idx = identifier_map.size(); + identifier_map[id]=idx; + } + token|=identifier_map[id]<<TOKEN_BITS; + } break; + case TK_CONSTANT: { + + Variant c = tt.get_token_constant(); + if (!constant_map.has(c)) { + int idx = constant_map.size(); + constant_map[c]=idx; + } + token|=constant_map[c]<<TOKEN_BITS; + } break; + case TK_BUILT_IN_TYPE: { + + token|=tt.get_token_type()<<TOKEN_BITS; + } break; + case TK_BUILT_IN_FUNC: { + + token|=tt.get_token_built_in_func()<<TOKEN_BITS; + + } break; + case TK_NEWLINE: { + + token|=tt.get_token_line_indent()<<TOKEN_BITS; + } break; + case TK_ERROR: { + + ERR_FAIL_V(Vector<uint8_t>()); + } break; + default: {} + + }; + + token_array.push_back(token); + + if (tt.get_token()==TK_EOF) + break; + tt.advance(); + + } + + //reverse maps + + Map<int,StringName> rev_identifier_map; + for(Map<StringName,int>::Element *E=identifier_map.front();E;E=E->next()) { + rev_identifier_map[E->get()]=E->key(); + } + + Map<int,Variant> rev_constant_map; + const Variant *K =NULL; + while((K=constant_map.next(K))) { + rev_constant_map[constant_map[*K]]=*K; + } + + Map<int,uint32_t> rev_line_map; + for(Map<uint32_t,int>::Element *E=line_map.front();E;E=E->next()) { + rev_line_map[E->get()]=E->key(); + } + + //save header + buf.resize(24); + buf[0]='G'; + buf[1]='D'; + buf[2]='S'; + buf[3]='C'; + encode_uint32(BYTECODE_VERSION,&buf[4]); + encode_uint32(identifier_map.size(),&buf[8]); + encode_uint32(constant_map.size(),&buf[12]); + encode_uint32(line_map.size(),&buf[16]); + encode_uint32(token_array.size(),&buf[20]); + + //save identifiers + + for(Map<int,StringName>::Element *E=rev_identifier_map.front();E;E=E->next()) { + + CharString cs = String(E->get()).utf8(); + int len = cs.length()+1; + int extra = 4-(len%4); + if (extra==4) + extra=0; + + uint8_t ibuf[4]; + encode_uint32(len+extra,ibuf); + for(int i=0;i<4;i++) { + buf.push_back(ibuf[i]); + } + for(int i=0;i<len;i++) { + buf.push_back(cs[i]^0xb6); + } + for(int i=0;i<extra;i++) { + buf.push_back(0^0xb6); + } + } + + for(Map<int,Variant>::Element *E=rev_constant_map.front();E;E=E->next()) { + + int len; + Error err = encode_variant(E->get(),NULL,len); + ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>()); + int pos=buf.size(); + buf.resize(pos+len); + encode_variant(E->get(),&buf[pos],len); + } + + for(Map<int,uint32_t>::Element *E=rev_line_map.front();E;E=E->next()) { + + uint8_t ibuf[8]; + encode_uint32(E->key(),&ibuf[0]); + encode_uint32(E->get(),&ibuf[4]); + for(int i=0;i<8;i++) + buf.push_back(ibuf[i]); + } + + for(int i=0;i<token_array.size();i++) { + + uint32_t token = token_array[i]; + + if (token&~TOKEN_MASK) { + uint8_t buf4[4]; + encode_uint32(token_array[i]|TOKEN_BYTE_MASK,&buf4[0]); + for(int j=0;j<4;j++) { + buf.push_back(buf4[j]); + } + } else { + buf.push_back(token); + } + } + + return buf; + +} + +GDTokenizerBuffer::Token GDTokenizerBuffer::get_token(int p_offset) const { + + int offset = token+p_offset; + + if (offset<0 || offset>=tokens.size()) + return TK_EOF; + + return GDTokenizerBuffer::Token(tokens[offset]&TOKEN_MASK); +} + + +StringName GDTokenizerBuffer::get_token_identifier(int p_offset) const{ + + int offset = token+p_offset; + + ERR_FAIL_INDEX_V(offset,tokens.size(),StringName()); + uint32_t identifier = tokens[offset]>>TOKEN_BITS; + ERR_FAIL_INDEX_V(identifier,identifiers.size(),StringName()); + + return identifiers[identifier]; +} + +GDFunctions::Function GDTokenizerBuffer::get_token_built_in_func(int p_offset) const{ + + int offset = token+p_offset; + ERR_FAIL_INDEX_V(offset,tokens.size(),GDFunctions::FUNC_MAX); + return GDFunctions::Function(tokens[offset]>>TOKEN_BITS); +} + +Variant::Type GDTokenizerBuffer::get_token_type(int p_offset) const{ + + int offset = token+p_offset; + ERR_FAIL_INDEX_V(offset,tokens.size(),Variant::NIL); + + return Variant::Type(tokens[offset]>>TOKEN_BITS); +} + +int GDTokenizerBuffer::get_token_line(int p_offset) const{ + + int offset = token+p_offset; + int pos = lines.find_nearest(offset); + + if (pos<0) + return -1; + if (pos>=lines.size()) + pos=lines.size()-1; + + uint32_t l = lines.getv(pos); + return l&TOKEN_LINE_MASK; + +} +int GDTokenizerBuffer::get_token_column(int p_offset) const{ + + int offset = token+p_offset; + int pos = lines.find_nearest(offset); + if (pos<0) + return -1; + if (pos>=lines.size()) + pos=lines.size()-1; + + uint32_t l = lines.getv(pos); + return l>>TOKEN_LINE_BITS; + +} +int GDTokenizerBuffer::get_token_line_indent(int p_offset) const{ + + int offset = token+p_offset; + ERR_FAIL_INDEX_V(offset,tokens.size(),0); + return tokens[offset]>>TOKEN_BITS; +} +const Variant& GDTokenizerBuffer::get_token_constant(int p_offset) const{ + + + int offset = token+p_offset; + ERR_FAIL_INDEX_V(offset,tokens.size(),nil); + uint32_t constant = tokens[offset]>>TOKEN_BITS; + ERR_FAIL_INDEX_V(constant,constants.size(),nil); + return constants[constant]; + +} +String GDTokenizerBuffer::get_token_error(int p_offset) const{ + + ERR_FAIL_V(String()); +} + +void GDTokenizerBuffer::advance(int p_amount){ + + ERR_FAIL_INDEX(p_amount+token,tokens.size()); + token+=p_amount; +} +GDTokenizerBuffer::GDTokenizerBuffer(){ + + token=0; + +} + diff --git a/script/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h index 24ee2be7ad..c517e07b89 100644 --- a/script/gdscript/gd_tokenizer.h +++ b/modules/gdscript/gd_tokenizer.h @@ -33,6 +33,8 @@ #include "variant.h" #include "string_db.h" #include "gd_functions.h" +#include "vmap.h" + class GDTokenizer { public: @@ -117,11 +119,28 @@ public: TK_MAX }; +protected: + static const char* token_names[TK_MAX]; +public: + static const char *get_token_name(Token p_token); + virtual const Variant& get_token_constant(int p_offset=0) const=0; + virtual Token get_token(int p_offset=0) const=0; + virtual StringName get_token_identifier(int p_offset=0) const=0; + virtual GDFunctions::Function get_token_built_in_func(int p_offset=0) const=0; + virtual Variant::Type get_token_type(int p_offset=0) const=0; + virtual int get_token_line(int p_offset=0) const=0; + virtual int get_token_column(int p_offset=0) const=0; + virtual int get_token_line_indent(int p_offset=0) const=0; + virtual String get_token_error(int p_offset=0) const=0; + virtual void advance(int p_amount=1)=0; -private: + virtual ~GDTokenizer(){}; + +}; + +class GDTokenizerText : public GDTokenizer { - static const char* token_names[TK_MAX]; enum { MAX_LOOKAHEAD=4, TK_RB_SIZE=MAX_LOOKAHEAD*2+1 @@ -162,20 +181,59 @@ private: void _advance(); public: - static const char *get_token_name(Token p_token); void set_code(const String& p_code); - Token get_token(int p_offset=0) const; - const Variant& get_token_constant(int p_offset=0) const; - StringName get_token_identifier(int p_offset=0) const; - GDFunctions::Function get_token_built_in_func(int p_offset=0) const; - Variant::Type get_token_type(int p_offset=0) const; - int get_token_line(int p_offset=0) const; - int get_token_column(int p_offset=0) const; - int get_token_line_indent(int p_offset=0) const; - - String get_token_error(int p_offset=0) const; - void advance(int p_amount=1); + virtual Token get_token(int p_offset=0) const; + virtual StringName get_token_identifier(int p_offset=0) const; + virtual GDFunctions::Function get_token_built_in_func(int p_offset=0) const; + virtual Variant::Type get_token_type(int p_offset=0) const; + virtual int get_token_line(int p_offset=0) const; + virtual int get_token_column(int p_offset=0) const; + virtual int get_token_line_indent(int p_offset=0) const; + virtual const Variant& get_token_constant(int p_offset=0) const; + virtual String get_token_error(int p_offset=0) const; + virtual void advance(int p_amount=1); +}; + + + + +class GDTokenizerBuffer : public GDTokenizer { + + + enum { + + TOKEN_BYTE_MASK=0x80, + TOKEN_BITS=8, + TOKEN_MASK=(1<<TOKEN_BITS)-1, + TOKEN_LINE_BITS=24, + TOKEN_LINE_MASK=(1<<TOKEN_LINE_BITS)-1, + }; + + + Vector<StringName> identifiers; + Vector<Variant> constants; + VMap<uint32_t,uint32_t> lines; + Vector<uint32_t> tokens; + Variant nil; + int token; + +public: + + + Error set_code_buffer(const Vector<uint8_t> & p_buffer); + static Vector<uint8_t> parse_code_string(const String& p_code); + virtual Token get_token(int p_offset=0) const; + virtual StringName get_token_identifier(int p_offset=0) const; + virtual GDFunctions::Function get_token_built_in_func(int p_offset=0) const; + virtual Variant::Type get_token_type(int p_offset=0) const; + virtual int get_token_line(int p_offset=0) const; + virtual int get_token_column(int p_offset=0) const; + virtual int get_token_line_indent(int p_offset=0) const; + virtual const Variant& get_token_constant(int p_offset=0) const; + virtual String get_token_error(int p_offset=0) const; + virtual void advance(int p_amount=1); + GDTokenizerBuffer(); }; #endif // TOKENIZER_H diff --git a/script/register_script_types.cpp b/modules/gdscript/register_types.cpp index 1927cd5c1f..6bcd12857b 100644 --- a/script/register_script_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -9,25 +9,66 @@ /* All Rights Reserved. */ /*************************************************/ -#include "register_script_types.h" +#include "register_types.h" -#include "script/gdscript/gd_script.h" -#include "script/multiscript/multi_script.h" +#include "gd_script.h" #include "io/resource_loader.h" +#include "os/file_access.h" - -#ifdef GDSCRIPT_ENABLED GDScriptLanguage *script_language_gd=NULL; ResourceFormatLoaderGDScript *resource_loader_gd=NULL; ResourceFormatSaverGDScript *resource_saver_gd=NULL; -#endif -static MultiScriptLanguage *script_multi_script=NULL; +#ifdef TOOLS_ENABLED + +#include "tools/editor/editor_import_export.h" +#include "gd_tokenizer.h" +#include "tools/editor/editor_node.h" + +class EditorExportGDScript : public EditorExportPlugin { + + OBJ_TYPE(EditorExportGDScript,EditorExportPlugin); + +public: -void register_script_types() { + virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) { + //compile gdscript to bytecode + if (p_path.ends_with(".gd")) { + Vector<uint8_t> file = FileAccess::get_file_as_array(p_path); + if (file.empty()) + return file; + String txt; + txt.parse_utf8((const char*)file.ptr(),file.size()); + file = GDTokenizerBuffer::parse_code_string(txt); + if (!file.empty()) { + print_line("PREV: "+p_path); + p_path=p_path.basename()+".gdc"; + print_line("NOW: "+p_path); + return file; + } + + } + + return Vector<uint8_t>(); + } + + + EditorExportGDScript(){} + +}; + +static void register_editor_plugin() { + + Ref<EditorExportGDScript> egd = memnew( EditorExportGDScript ); + EditorImportExport::get_singleton()->add_export_plugin(egd); +} + + +#endif + +void register_gdscript_types() { -#ifdef GDSCRIPT_ENABLED script_language_gd=memnew( GDScriptLanguage ); script_language_gd->init(); @@ -37,21 +78,18 @@ void register_script_types() { ResourceLoader::add_resource_format_loader(resource_loader_gd); resource_saver_gd=memnew( ResourceFormatSaverGDScript ); ResourceSaver::add_resource_format_saver(resource_saver_gd); -#endif - - script_multi_script = memnew( MultiScriptLanguage ); - ScriptServer::register_language(script_multi_script); - ObjectTypeDB::register_type<MultiScript>(); +#ifdef TOOLS_ENABLED + EditorNode::add_init_callback(register_editor_plugin); +#endif } -void unregister_script_types() { +void unregister_gdscript_types() { -#ifdef GDSCRIPT_ENABLED if (script_language_gd) memdelete( script_language_gd ); if (resource_loader_gd) @@ -59,8 +97,4 @@ void unregister_script_types() { if (resource_saver_gd) memdelete( resource_saver_gd ); -#endif - - if (script_multi_script); - memdelete(script_multi_script); } diff --git a/script/register_script_types.h b/modules/gdscript/register_types.h index eec0cfe539..ff7c2734df 100644 --- a/script/register_script_types.h +++ b/modules/gdscript/register_types.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* register_script_types.h */ +/* register_types.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -26,13 +26,5 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef REGISTER_SCRIPT_TYPES_H -#define REGISTER_SCRIPT_TYPES_H - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -void register_script_types(); -void unregister_script_types(); - -#endif +void register_gdscript_types(); +void unregister_gdscript_types(); diff --git a/modules/multiscript/SCsub b/modules/multiscript/SCsub new file mode 100644 index 0000000000..d20da72b72 --- /dev/null +++ b/modules/multiscript/SCsub @@ -0,0 +1,7 @@ +Import('env') + +env.add_source_files(env.modules_sources,"*.cpp") + +Export('env') + + diff --git a/modules/multiscript/config.py b/modules/multiscript/config.py new file mode 100644 index 0000000000..f9bd7da08d --- /dev/null +++ b/modules/multiscript/config.py @@ -0,0 +1,11 @@ + + +def can_build(platform): + return True + + +def configure(env): + pass + + + diff --git a/script/multiscript/multi_script.cpp b/modules/multiscript/multi_script.cpp index 1924cf2a6e..1924cf2a6e 100644 --- a/script/multiscript/multi_script.cpp +++ b/modules/multiscript/multi_script.cpp diff --git a/script/multiscript/multi_script.h b/modules/multiscript/multi_script.h index 87d4b4e4c8..87d4b4e4c8 100644 --- a/script/multiscript/multi_script.h +++ b/modules/multiscript/multi_script.h diff --git a/modules/multiscript/register_types.cpp b/modules/multiscript/register_types.cpp new file mode 100644 index 0000000000..4b25656723 --- /dev/null +++ b/modules/multiscript/register_types.cpp @@ -0,0 +1,32 @@ +/*************************************************/ +/* register_script_types.cpp */ +/*************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/*************************************************/ +/* Source code within this file is: */ +/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */ +/* All Rights Reserved. */ +/*************************************************/ + +#include "register_types.h" + +#include "multi_script.h" +#include "io/resource_loader.h" + +static MultiScriptLanguage *script_multi_script=NULL; + +void register_multiscript_types() { + + + script_multi_script = memnew( MultiScriptLanguage ); + ScriptServer::register_language(script_multi_script); + ObjectTypeDB::register_type<MultiScript>(); + + +} +void unregister_multiscript_types() { + + if (script_multi_script); + memdelete(script_multi_script); +} diff --git a/modules/multiscript/register_types.h b/modules/multiscript/register_types.h new file mode 100644 index 0000000000..d137b1c63f --- /dev/null +++ b/modules/multiscript/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_multiscript_types(); +void unregister_multiscript_types(); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index d95818b4a1..a09575bad5 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -45,7 +45,10 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> + +#ifdef __linux__ #include <linux/joystick.h> +#endif //stupid linux.h #ifdef KEY_TAB @@ -1031,7 +1034,7 @@ void OS_X11::close_joystick(int p_id) { }; void OS_X11::probe_joystick(int p_id) { - + #ifndef __FreeBSD__ if (p_id == -1) { for (int i=0; i<JOYSTICKS_MAX; i++) { @@ -1065,6 +1068,7 @@ void OS_X11::probe_joystick(int p_id) { ++i; }; + #endif }; void OS_X11::move_window_to_foreground() { @@ -1073,7 +1077,7 @@ void OS_X11::move_window_to_foreground() { } void OS_X11::process_joysticks() { - + #ifndef __FreeBSD__ int bytes; js_event events[32]; InputEvent ievent; @@ -1172,6 +1176,7 @@ void OS_X11::process_joysticks() { }; }; }; + #endif }; void OS_X11::set_cursor_shape(CursorShape p_shape) { diff --git a/platform/x11/platform_config.h b/platform/x11/platform_config.h index d14f3e3f9a..21703969cc 100644 --- a/platform/x11/platform_config.h +++ b/platform/x11/platform_config.h @@ -26,7 +26,13 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifdef __linux__ #include <alloca.h> +#endif +#ifdef __FreeBSD__ +#include <stdlib.h> +#endif + #define GLES2_INCLUDE_H "gl_context/glew.h" #define GLES1_INCLUDE_H "gl_context/glew.h" diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 9b2994ef84..a2bee43e58 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -162,6 +162,10 @@ void Node2D::set_scale(const Size2& p_scale) { if (_xform_dirty) ((Node2D*)this)->_update_xform_values(); scale=p_scale; + if (scale.x==0) + scale.x=CMP_EPSILON; + if (scale.y==0) + scale.y=CMP_EPSILON; _update_transform(); _change_notify("transform/scale"); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 6ec23f96fb..b77a4e0fe3 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -43,7 +43,8 @@ bool Skeleton::_set(const StringName& p_path, const Variant& p_value) { int which=path.get_slice("/",1).to_int(); String what=path.get_slice("/",2); - + + if (which==bones.size() && what=="name") { add_bone(p_value); @@ -94,7 +95,7 @@ bool Skeleton::_get(const StringName& p_name,Variant &r_ret) const { if (what=="name") r_ret=get_bone_name(which); - if (what=="parent") + else if (what=="parent") r_ret=get_bone_parent(which); else if (what=="rest") r_ret=get_bone_rest(which); @@ -250,7 +251,7 @@ void Skeleton::add_bone(const String& p_name) { ERR_FAIL_COND( bones[i].name=="p_name"); } - + Bone b; b.name=p_name; bones.push_back(b); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 9be3c97901..fb85f0c6b7 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1591,7 +1591,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ case TreeItem::CELL_MODE_CUSTOM: { edited_item=p_item; edited_col=col; - custom_popup_rect=Rect2i(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs+item_h-v_scroll->get_val()), Size2(get_column_width(col),item_h)); + custom_popup_rect=Rect2i(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs+item_h-cache.offset.y), Size2(get_column_width(col),item_h)); emit_signal("custom_popup_edited",((bool)(x >= (col_width-item_h/2)))); bring_up_editor=false; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 5ac09e837f..9b592a77d5 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -552,6 +552,8 @@ void Node::_validate_child_name(Node *p_child) { int cc = data.children.size(); for(int i=0;i<cc;i++) { + if (childs[i]==p_child) + continue; if (childs[i]->data.name==p_child->data.name) { unique=false; break; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index ae2b925008..4aed217cef 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -782,16 +782,41 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_as_render_target","enable"), &Viewport::set_as_render_target); ObjectTypeDB::bind_method(_MD("is_set_as_render_target"), &Viewport::is_set_as_render_target); + ObjectTypeDB::bind_method(_MD("set_render_target_update_mode","mode"), &Viewport::set_render_target_update_mode); + ObjectTypeDB::bind_method(_MD("get_render_target_update_mode"), &Viewport::get_render_target_update_mode); + + ObjectTypeDB::bind_method(_MD("get_render_target_texture:RenderTargetTexture"), &Viewport::get_render_target_texture); + + ObjectTypeDB::bind_method(_MD("get_viewport"), &Viewport::get_viewport); + ObjectTypeDB::bind_method(_MD("update_worlds"), &Viewport::update_worlds); + + ObjectTypeDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener); + ObjectTypeDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener); + + ObjectTypeDB::bind_method(_MD("set_as_audio_listener_2d","enable"), &Viewport::set_as_audio_listener_2d); + ObjectTypeDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d); + + + ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") ); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world",PROPERTY_HINT_RESOURCE_TYPE,"World"), _SCS("set_world"), _SCS("get_world") ); // ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world_2d",PROPERTY_HINT_RESOURCE_TYPE,"World2D"), _SCS("set_world_2d"), _SCS("get_world_2d") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") ); - ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/enabled"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") ); + ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_2d"), _SCS("set_as_audio_listener_2d"), _SCS("is_audio_listener_2d") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_3d"), _SCS("set_as_audio_listener"), _SCS("is_audio_listener") ); ADD_SIGNAL(MethodInfo("size_changed")); + + BIND_CONSTANT( RENDER_TARGET_UPDATE_DISABLED ); + BIND_CONSTANT( RENDER_TARGET_UPDATE_ONCE ); + BIND_CONSTANT( RENDER_TARGET_UPDATE_WHEN_VISIBLE ); + BIND_CONSTANT( RENDER_TARGET_UPDATE_ALWAYS ); + } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index a35bc51e1e..7fbae20f7d 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -154,11 +154,9 @@ public: Camera* get_camera() const; - void set_listener_transform(const Transform& p_xform); void set_as_audio_listener(bool p_enable); bool is_audio_listener() const; - void set_listener_2d_transform(const Matrix32& p_xform); void set_as_audio_listener_2d(bool p_enable); bool is_audio_listener_2d() const; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index ac1826a0b8..3bd7314778 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -26,564 +26,564 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "packed_scene.h"
-#include "globals.h"
-#include "io/resource_loader.h"
-
-bool PackedScene::can_instance() const {
-
- return nodes.size()>0;
-}
-
-Node *PackedScene::instance(bool p_gen_edit_state) const {
-
- int nc = nodes.size();
- ERR_FAIL_COND_V(nc==0,NULL);
-
- const StringName*snames=NULL;
- int sname_count=names.size();
- if (sname_count)
- snames=&names[0];
-
- const Variant*props=NULL;
- int prop_count=variants.size();
- if (prop_count)
- props=&variants[0];
-
- Vector<Variant> properties;
-
- const NodeData *nd = &nodes[0];
-
- Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc );
-
-
- for(int i=0;i<nc;i++) {
-
- const NodeData &n=nd[i];
-
- if (!ObjectTypeDB::is_type_enabled(snames[n.type])) {
- ret_nodes[i]=NULL;
- continue;
- }
-
- Node *node=NULL;
-
- if (n.instance>=0) {
- //instance existing
- Ref<PackedScene> sdata = props[ n.instance ];
- ERR_FAIL_COND_V( !sdata.is_valid(), NULL);
- node = sdata->instance();
- ERR_FAIL_COND_V(!node,NULL);
- if (p_gen_edit_state)
- node->generate_instance_state();
-
- } else {
- //create anew
- Object * obj = ObjectTypeDB::instance(snames[ n.type ]);
- ERR_FAIL_COND_V(!obj,NULL);
- node = obj->cast_to<Node>();
- ERR_FAIL_COND_V(!node,NULL);
-
- }
-
-
- //properties
- int nprop_count=n.properties.size();
- if (nprop_count) {
-
- const NodeData::Property* nprops=&n.properties[0];
-
- for(int j=0;j<nprop_count;j++) {
-
- bool valid;
- ERR_FAIL_INDEX_V( nprops[j].name, sname_count, NULL );
- ERR_FAIL_INDEX_V( nprops[j].value, prop_count, NULL );
-
- node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid);
- }
- }
-
- //name
-
- //groups
- for(int j=0;j<n.groups.size();j++) {
-
- ERR_FAIL_INDEX_V( n.groups[j], sname_count, NULL );
- node->add_to_group( snames[ n.groups[j] ], true );
- }
-
-
- ret_nodes[i]=node;
-
- if (i>0) {
- ERR_FAIL_INDEX_V(n.parent,i,NULL);
- ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL);
- ret_nodes[n.parent]->_add_child_nocheck(node,snames[n.name]);
- } else {
- node->_set_name_nocheck( snames[ n.name ] );
- }
-
-
- if (n.owner>=0) {
-
- ERR_FAIL_INDEX_V(n.owner,i,NULL);
- node->_set_owner_nocheck(ret_nodes[n.owner]);
- }
-
- }
-
-
- //do connections
-
- int cc = connections.size();
- const ConnectionData *cdata = connections.ptr();
-
- for(int i=0;i<cc;i++) {
-
- const ConnectionData &c=cdata[i];
- ERR_FAIL_INDEX_V( c.from, nc, NULL );
- ERR_FAIL_INDEX_V( c.to, nc, NULL );
-
- Vector<Variant> binds;
- if (c.binds.size()) {
- binds.resize(c.binds.size());
- for(int j=0;j<c.binds.size();j++)
- binds[j]=props[ c.binds[j] ];
- }
-
- if (!ret_nodes[c.from] || !ret_nodes[c.to])
- continue;
- ret_nodes[c.from]->connect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST|c.flags );
- }
-
- Node *s = ret_nodes[0];
-
- if (get_path()!="" && get_path().find("::")==-1)
- s->set_filename(get_path());
- return ret_nodes[0];
-
-}
-
-
-static int _nm_get_string(const String& p_string, Map<StringName,int> &name_map) {
-
- if (name_map.has(p_string))
- return name_map[p_string];
-
- int idx = name_map.size();
- name_map[p_string]=idx;
- return idx;
-}
-
-static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher> &variant_map) {
-
- if (variant_map.has(p_variant))
- return variant_map[p_variant];
-
- int idx = variant_map.size();
- variant_map[p_variant]=idx;
- return idx;
-}
-
-Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) {
-
- if (p_node!=p_owner && (p_node->get_owner()!=p_owner))
- return OK; //nothing to do with this node, may either belong to another scene or be onowned
-
- NodeData nd;
-
- nd.name=_nm_get_string(p_node->get_name(),name_map);
- nd.type=_nm_get_string(p_node->get_type(),name_map);
- nd.parent=p_parent_idx;
-
-
- Dictionary instance_state;
- Set<StringName> instance_groups;
-
-
- if (p_node!=p_owner && p_node->get_filename()!="") {
- //instanced
- Ref<PackedScene> instance = ResourceLoader::load(p_node->get_filename());
- if (!instance.is_valid()) {
- return ERR_CANT_OPEN;
- }
-
- nd.instance=_vm_get_variant(instance,variant_map);
- instance_state = p_node->get_instance_state();
- Vector<StringName> ig = p_node->get_instance_groups();
- for(int i=0;i<ig.size();i++)
- instance_groups.insert(ig[i]);
- } else {
-
- nd.instance=-1;
- }
-
-
- //instance state makes sure that only changes to instance are saved
-
- List<PropertyInfo> plist;
- p_node->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
-
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
- continue;
-
- String name = E->get().name;
- Variant value = p_node->get( E->get().name );
-
- if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())
- continue;
-
-
- if (nd.instance>=0) {
- //only save changed properties in instance
- if (!instance_state.has(name))
- continue;
- if (instance_state[name]==value)
- continue;
-
- }
-
- NodeData::Property prop;
- prop.name=_nm_get_string( name,name_map);
- prop.value=_vm_get_variant( value, variant_map);
- nd.properties.push_back(prop);
-
- }
-
-
- List<Node::GroupInfo> groups;
- p_node->get_groups(&groups);
- for(List<Node::GroupInfo>::Element *E=groups.front();E;E=E->next()) {
- Node::GroupInfo &gi=E->get();
-
- if (!gi.persistent)
- continue;
- if (nd.instance>=0 && instance_groups.has(gi.name))
- continue; //group was instanced, don't add here
-
- nd.groups.push_back(_nm_get_string(gi.name,name_map));
- }
-
- if (node_map.has(p_node->get_owner()))
- nd.owner=node_map[p_node->get_owner()];
- else
- nd.owner=-1;
-
- int idx = nodes.size();
- node_map[p_node]=idx;
- nodes.push_back(nd);
-
-
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- Node *c=p_node->get_child(i);
- Error err = _parse_node(p_owner,c,idx,name_map,variant_map,node_map);
- if (err)
- return err;
- }
-
- return OK;
-
-}
-
-Error PackedScene::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) {
-
- if (p_node!=p_owner && (p_node->get_owner()!=p_owner))
- return OK; //nothing to do with this node, may either belong to another scene or be onowned
-
- List<MethodInfo> signals;
- p_node->get_signal_list(&signals);
-
- ERR_FAIL_COND_V( !node_map.has(p_node), ERR_BUG);
- NodeData &nd = nodes[node_map[p_node]];
- Set<Connection> instance_connections;
-
- if (nd.instance>=0) {
-
- Vector<Connection> iconns = p_node->get_instance_connections();
- for(int i=0;i<iconns.size();i++) {
-
- instance_connections.insert(iconns[i]);
- }
- }
-
-
- for(List<MethodInfo>::Element *E=signals.front();E;E=E->next()) {
-
- List<Node::Connection> conns;
- p_node->get_signal_connection_list(E->get().name,&conns);
- for(List<Node::Connection>::Element *F=conns.front();F;F=F->next()) {
-
- const Node::Connection &c = F->get();
- if (!(c.flags&CONNECT_PERSIST))
- continue;
-
- if (nd.instance>=0 && instance_connections.has(c))
- continue; //came from instance, don't save!
-
- Node *n=c.target->cast_to<Node>();
- if (!n)
- continue;
-
- if (!node_map.has(n)) {
- WARN_PRINT("Connection to node outside scene??")
- continue;
- }
-
- ConnectionData cd;
- cd.from=node_map[p_node];
- cd.to=node_map[n];
- cd.method=_nm_get_string(c.method,name_map);
- cd.signal=_nm_get_string(c.signal,name_map);
- cd.flags=c.flags;
- for(int i=0;i<c.binds.size();i++) {
-
- cd.binds.push_back( _vm_get_variant(c.binds[i],variant_map));
- }
- connections.push_back(cd);
- }
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- Node *c=p_node->get_child(i);
- Error err = _parse_connections(p_owner,c,name_map,variant_map,node_map);
- if (err)
- return err;
- }
-
- return OK;
-}
-
-
-Error PackedScene::pack(Node *p_scene) {
- ERR_FAIL_NULL_V( p_scene, ERR_INVALID_PARAMETER );
-
-
- clear();
-
- Node *scene = p_scene;
-
- Map<StringName,int> name_map;
- HashMap<Variant,int,VariantHasher> variant_map;
- Map<Node*,int> node_map;
-
- Error err = _parse_node(scene,scene,-1,name_map,variant_map,node_map);
- if (err) {
- clear();
- ERR_FAIL_V(err);
- }
-
- err = _parse_connections(scene,scene,name_map,variant_map,node_map);
- if (err) {
- clear();
- ERR_FAIL_V(err);
- }
-
- names.resize(name_map.size());
-
- for(Map<StringName,int>::Element *E=name_map.front();E;E=E->next()) {
-
- names[E->get()]=E->key();
- }
-
- variants.resize(variant_map.size());
- const Variant *K=NULL;
- while((K=variant_map.next(K))) {
-
- int idx = variant_map[*K];
- variants[idx]=*K;
- }
-
- return OK;
-}
-
-void PackedScene::clear() {
-
- names.clear();
- variants.clear();
- nodes.clear();
- connections.clear();
-
-}
-
-void PackedScene::_set_bundled_scene(const Dictionary& d) {
-
-
- ERR_FAIL_COND( !d.has("names"));
- ERR_FAIL_COND( !d.has("variants"));
- ERR_FAIL_COND( !d.has("node_count"));
- ERR_FAIL_COND( !d.has("nodes"));
- ERR_FAIL_COND( !d.has("conn_count"));
- ERR_FAIL_COND( !d.has("conns"));
-// ERR_FAIL_COND( !d.has("path"));
-
- DVector<String> snames = d["names"];
- if (snames.size()) {
-
- int namecount = snames.size();
- names.resize(namecount);
- DVector<String>::Read r =snames.read();
- for(int i=0;i<names.size();i++)
- names[i]=r[i];
- }
-
- Array svariants = d["variants"];
-
- if (svariants.size()) {
- int varcount=svariants.size();
- variants.resize(varcount);
- for(int i=0;i<varcount;i++) {
-
- variants[i]=svariants[i];
- }
-
- } else {
- variants.clear();
- }
-
- nodes.resize(d["node_count"]);
- int nc=nodes.size();
- if (nc) {
- DVector<int> snodes = d["nodes"];
- DVector<int>::Read r = snodes.read();
- int idx=0;
- for(int i=0;i<nc;i++) {
- NodeData &nd = nodes[i];
- nd.parent=r[idx++];
- nd.owner=r[idx++];
- nd.type=r[idx++];
- nd.name=r[idx++];
- nd.instance=r[idx++];
- nd.properties.resize(r[idx++]);
- for(int j=0;j<nd.properties.size();j++) {
-
- nd.properties[j].name=r[idx++];
- nd.properties[j].value=r[idx++];
- }
- nd.groups.resize(r[idx++]);
- for(int j=0;j<nd.groups.size();j++) {
-
- nd.groups[j]=r[idx++];
- }
- }
-
- }
-
- connections.resize(d["conn_count"]);
- int cc=connections.size();
-
- if (cc) {
-
- DVector<int> sconns = d["conns"];
- DVector<int>::Read r = sconns.read();
- int idx=0;
- for(int i=0;i<cc;i++) {
- ConnectionData &cd = connections[i];
- cd.from=r[idx++];
- cd.to=r[idx++];
- cd.signal=r[idx++];
- cd.method=r[idx++];
- cd.flags=r[idx++];
- cd.binds.resize(r[idx++]);
-
- for(int j=0;j<cd.binds.size();j++) {
-
- cd.binds[j]=r[idx++];
- }
- }
-
- }
-
-// path=d["path"];
-
-}
-
-Dictionary PackedScene::_get_bundled_scene() const {
-
- DVector<String> rnames;
- rnames.resize(names.size());
-
- if (names.size()) {
-
- DVector<String>::Write r=rnames.write();
-
- for(int i=0;i<names.size();i++)
- r[i]=names[i];
- }
-
- Dictionary d;
- d["names"]=rnames;
- d["variants"]=variants;
-
- Vector<int> rnodes;
- d["node_count"]=nodes.size();
-
- for(int i=0;i<nodes.size();i++) {
-
- const NodeData &nd=nodes[i];
- rnodes.push_back(nd.parent);
- rnodes.push_back(nd.owner);
- rnodes.push_back(nd.type);
- rnodes.push_back(nd.name);
- rnodes.push_back(nd.instance);
- rnodes.push_back(nd.properties.size());
- for(int j=0;j<nd.properties.size();j++) {
-
- rnodes.push_back(nd.properties[j].name);
- rnodes.push_back(nd.properties[j].value);
- }
- rnodes.push_back(nd.groups.size());
- for(int j=0;j<nd.groups.size();j++) {
-
- rnodes.push_back(nd.groups[j]);
- }
- }
-
- d["nodes"]=rnodes;
-
- Vector<int> rconns;
- d["conn_count"]=connections.size();
-
- for(int i=0;i<connections.size();i++) {
-
- const ConnectionData &cd=connections[i];
- rconns.push_back(cd.from);
- rconns.push_back(cd.to);
- rconns.push_back(cd.signal);
- rconns.push_back(cd.method);
- rconns.push_back(cd.flags);
- rconns.push_back(cd.binds.size());
- for(int j=0;j<cd.binds.size();j++)
- rconns.push_back(cd.binds[j]);
-
- }
-
- d["conns"]=rconns;
- d["version"]=1;
-
-// d["path"]=path;
-
- return d;
-
-
-}
-
-void PackedScene::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("pack","path:Node"),&PackedScene::pack);
- ObjectTypeDB::bind_method(_MD("instance:Node"),&PackedScene::instance,DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("can_instance"),&PackedScene::can_instance);
- ObjectTypeDB::bind_method(_MD("_set_bundled_scene"),&PackedScene::_set_bundled_scene);
- ObjectTypeDB::bind_method(_MD("_get_bundled_scene"),&PackedScene::_get_bundled_scene);
-
- ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled"),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene"));
-
-}
-
-PackedScene::PackedScene() {
-
-
-}
+#include "packed_scene.h" +#include "globals.h" +#include "io/resource_loader.h" + +bool PackedScene::can_instance() const { + + return nodes.size()>0; +} + +Node *PackedScene::instance(bool p_gen_edit_state) const { + + int nc = nodes.size(); + ERR_FAIL_COND_V(nc==0,NULL); + + const StringName*snames=NULL; + int sname_count=names.size(); + if (sname_count) + snames=&names[0]; + + const Variant*props=NULL; + int prop_count=variants.size(); + if (prop_count) + props=&variants[0]; + + Vector<Variant> properties; + + const NodeData *nd = &nodes[0]; + + Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc ); + + + for(int i=0;i<nc;i++) { + + const NodeData &n=nd[i]; + + if (!ObjectTypeDB::is_type_enabled(snames[n.type])) { + ret_nodes[i]=NULL; + continue; + } + + Node *node=NULL; + + if (n.instance>=0) { + //instance existing + Ref<PackedScene> sdata = props[ n.instance ]; + ERR_FAIL_COND_V( !sdata.is_valid(), NULL); + node = sdata->instance(); + ERR_FAIL_COND_V(!node,NULL); + if (p_gen_edit_state) + node->generate_instance_state(); + + } else { + //create anew + Object * obj = ObjectTypeDB::instance(snames[ n.type ]); + ERR_FAIL_COND_V(!obj,NULL); + node = obj->cast_to<Node>(); + ERR_FAIL_COND_V(!node,NULL); + + } + + + //properties + int nprop_count=n.properties.size(); + if (nprop_count) { + + const NodeData::Property* nprops=&n.properties[0]; + + for(int j=0;j<nprop_count;j++) { + + bool valid; + ERR_FAIL_INDEX_V( nprops[j].name, sname_count, NULL ); + ERR_FAIL_INDEX_V( nprops[j].value, prop_count, NULL ); + + node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid); + } + } + + //name + + //groups + for(int j=0;j<n.groups.size();j++) { + + ERR_FAIL_INDEX_V( n.groups[j], sname_count, NULL ); + node->add_to_group( snames[ n.groups[j] ], true ); + } + + + ret_nodes[i]=node; + + if (i>0) { + ERR_FAIL_INDEX_V(n.parent,i,NULL); + ERR_FAIL_COND_V(!ret_nodes[n.parent],NULL); + ret_nodes[n.parent]->_add_child_nocheck(node,snames[n.name]); + } else { + node->_set_name_nocheck( snames[ n.name ] ); + } + + + if (n.owner>=0) { + + ERR_FAIL_INDEX_V(n.owner,i,NULL); + node->_set_owner_nocheck(ret_nodes[n.owner]); + } + + } + + + //do connections + + int cc = connections.size(); + const ConnectionData *cdata = connections.ptr(); + + for(int i=0;i<cc;i++) { + + const ConnectionData &c=cdata[i]; + ERR_FAIL_INDEX_V( c.from, nc, NULL ); + ERR_FAIL_INDEX_V( c.to, nc, NULL ); + + Vector<Variant> binds; + if (c.binds.size()) { + binds.resize(c.binds.size()); + for(int j=0;j<c.binds.size();j++) + binds[j]=props[ c.binds[j] ]; + } + + if (!ret_nodes[c.from] || !ret_nodes[c.to]) + continue; + ret_nodes[c.from]->connect( snames[ c.signal], ret_nodes[ c.to ], snames[ c.method], binds,CONNECT_PERSIST|c.flags ); + } + + Node *s = ret_nodes[0]; + + if (get_path()!="" && get_path().find("::")==-1) + s->set_filename(get_path()); + return ret_nodes[0]; + +} + + +static int _nm_get_string(const String& p_string, Map<StringName,int> &name_map) { + + if (name_map.has(p_string)) + return name_map[p_string]; + + int idx = name_map.size(); + name_map[p_string]=idx; + return idx; +} + +static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher> &variant_map) { + + if (variant_map.has(p_variant)) + return variant_map[p_variant]; + + int idx = variant_map.size(); + variant_map[p_variant]=idx; + return idx; +} + +Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) { + + if (p_node!=p_owner && (p_node->get_owner()!=p_owner)) + return OK; //nothing to do with this node, may either belong to another scene or be onowned + + NodeData nd; + + nd.name=_nm_get_string(p_node->get_name(),name_map); + nd.type=_nm_get_string(p_node->get_type(),name_map); + nd.parent=p_parent_idx; + + + Dictionary instance_state; + Set<StringName> instance_groups; + + + if (p_node!=p_owner && p_node->get_filename()!="") { + //instanced + Ref<PackedScene> instance = ResourceLoader::load(p_node->get_filename()); + if (!instance.is_valid()) { + return ERR_CANT_OPEN; + } + + nd.instance=_vm_get_variant(instance,variant_map); + instance_state = p_node->get_instance_state(); + Vector<StringName> ig = p_node->get_instance_groups(); + for(int i=0;i<ig.size();i++) + instance_groups.insert(ig[i]); + } else { + + nd.instance=-1; + } + + + //instance state makes sure that only changes to instance are saved + + List<PropertyInfo> plist; + p_node->get_property_list(&plist); + for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { + + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + continue; + + String name = E->get().name; + Variant value = p_node->get( E->get().name ); + + if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) + continue; + + + if (nd.instance>=0) { + //only save changed properties in instance + if (!instance_state.has(name)) + continue; + if (instance_state[name]==value) + continue; + + } + + NodeData::Property prop; + prop.name=_nm_get_string( name,name_map); + prop.value=_vm_get_variant( value, variant_map); + nd.properties.push_back(prop); + + } + + + List<Node::GroupInfo> groups; + p_node->get_groups(&groups); + for(List<Node::GroupInfo>::Element *E=groups.front();E;E=E->next()) { + Node::GroupInfo &gi=E->get(); + + if (!gi.persistent) + continue; + if (nd.instance>=0 && instance_groups.has(gi.name)) + continue; //group was instanced, don't add here + + nd.groups.push_back(_nm_get_string(gi.name,name_map)); + } + + if (node_map.has(p_node->get_owner())) + nd.owner=node_map[p_node->get_owner()]; + else + nd.owner=-1; + + int idx = nodes.size(); + node_map[p_node]=idx; + nodes.push_back(nd); + + + + for(int i=0;i<p_node->get_child_count();i++) { + + Node *c=p_node->get_child(i); + Error err = _parse_node(p_owner,c,idx,name_map,variant_map,node_map); + if (err) + return err; + } + + return OK; + +} + +Error PackedScene::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map) { + + if (p_node!=p_owner && (p_node->get_owner()!=p_owner)) + return OK; //nothing to do with this node, may either belong to another scene or be onowned + + List<MethodInfo> signals; + p_node->get_signal_list(&signals); + + ERR_FAIL_COND_V( !node_map.has(p_node), ERR_BUG); + NodeData &nd = nodes[node_map[p_node]]; + Set<Connection> instance_connections; + + if (nd.instance>=0) { + + Vector<Connection> iconns = p_node->get_instance_connections(); + for(int i=0;i<iconns.size();i++) { + + instance_connections.insert(iconns[i]); + } + } + + + for(List<MethodInfo>::Element *E=signals.front();E;E=E->next()) { + + List<Node::Connection> conns; + p_node->get_signal_connection_list(E->get().name,&conns); + for(List<Node::Connection>::Element *F=conns.front();F;F=F->next()) { + + const Node::Connection &c = F->get(); + if (!(c.flags&CONNECT_PERSIST)) + continue; + + if (nd.instance>=0 && instance_connections.has(c)) + continue; //came from instance, don't save! + + Node *n=c.target->cast_to<Node>(); + if (!n) + continue; + + if (!node_map.has(n)) { + WARN_PRINT("Connection to node outside scene??") + continue; + } + + ConnectionData cd; + cd.from=node_map[p_node]; + cd.to=node_map[n]; + cd.method=_nm_get_string(c.method,name_map); + cd.signal=_nm_get_string(c.signal,name_map); + cd.flags=c.flags; + for(int i=0;i<c.binds.size();i++) { + + cd.binds.push_back( _vm_get_variant(c.binds[i],variant_map)); + } + connections.push_back(cd); + } + } + + for(int i=0;i<p_node->get_child_count();i++) { + + Node *c=p_node->get_child(i); + Error err = _parse_connections(p_owner,c,name_map,variant_map,node_map); + if (err) + return err; + } + + return OK; +} + + +Error PackedScene::pack(Node *p_scene) { + ERR_FAIL_NULL_V( p_scene, ERR_INVALID_PARAMETER ); + + + clear(); + + Node *scene = p_scene; + + Map<StringName,int> name_map; + HashMap<Variant,int,VariantHasher> variant_map; + Map<Node*,int> node_map; + + Error err = _parse_node(scene,scene,-1,name_map,variant_map,node_map); + if (err) { + clear(); + ERR_FAIL_V(err); + } + + err = _parse_connections(scene,scene,name_map,variant_map,node_map); + if (err) { + clear(); + ERR_FAIL_V(err); + } + + names.resize(name_map.size()); + + for(Map<StringName,int>::Element *E=name_map.front();E;E=E->next()) { + + names[E->get()]=E->key(); + } + + variants.resize(variant_map.size()); + const Variant *K=NULL; + while((K=variant_map.next(K))) { + + int idx = variant_map[*K]; + variants[idx]=*K; + } + + return OK; +} + +void PackedScene::clear() { + + names.clear(); + variants.clear(); + nodes.clear(); + connections.clear(); + +} + +void PackedScene::_set_bundled_scene(const Dictionary& d) { + + + ERR_FAIL_COND( !d.has("names")); + ERR_FAIL_COND( !d.has("variants")); + ERR_FAIL_COND( !d.has("node_count")); + ERR_FAIL_COND( !d.has("nodes")); + ERR_FAIL_COND( !d.has("conn_count")); + ERR_FAIL_COND( !d.has("conns")); +// ERR_FAIL_COND( !d.has("path")); + + DVector<String> snames = d["names"]; + if (snames.size()) { + + int namecount = snames.size(); + names.resize(namecount); + DVector<String>::Read r =snames.read(); + for(int i=0;i<names.size();i++) + names[i]=r[i]; + } + + Array svariants = d["variants"]; + + if (svariants.size()) { + int varcount=svariants.size(); + variants.resize(varcount); + for(int i=0;i<varcount;i++) { + + variants[i]=svariants[i]; + } + + } else { + variants.clear(); + } + + nodes.resize(d["node_count"]); + int nc=nodes.size(); + if (nc) { + DVector<int> snodes = d["nodes"]; + DVector<int>::Read r = snodes.read(); + int idx=0; + for(int i=0;i<nc;i++) { + NodeData &nd = nodes[i]; + nd.parent=r[idx++]; + nd.owner=r[idx++]; + nd.type=r[idx++]; + nd.name=r[idx++]; + nd.instance=r[idx++]; + nd.properties.resize(r[idx++]); + for(int j=0;j<nd.properties.size();j++) { + + nd.properties[j].name=r[idx++]; + nd.properties[j].value=r[idx++]; + } + nd.groups.resize(r[idx++]); + for(int j=0;j<nd.groups.size();j++) { + + nd.groups[j]=r[idx++]; + } + } + + } + + connections.resize(d["conn_count"]); + int cc=connections.size(); + + if (cc) { + + DVector<int> sconns = d["conns"]; + DVector<int>::Read r = sconns.read(); + int idx=0; + for(int i=0;i<cc;i++) { + ConnectionData &cd = connections[i]; + cd.from=r[idx++]; + cd.to=r[idx++]; + cd.signal=r[idx++]; + cd.method=r[idx++]; + cd.flags=r[idx++]; + cd.binds.resize(r[idx++]); + + for(int j=0;j<cd.binds.size();j++) { + + cd.binds[j]=r[idx++]; + } + } + + } + +// path=d["path"]; + +} + +Dictionary PackedScene::_get_bundled_scene() const { + + DVector<String> rnames; + rnames.resize(names.size()); + + if (names.size()) { + + DVector<String>::Write r=rnames.write(); + + for(int i=0;i<names.size();i++) + r[i]=names[i]; + } + + Dictionary d; + d["names"]=rnames; + d["variants"]=variants; + + Vector<int> rnodes; + d["node_count"]=nodes.size(); + + for(int i=0;i<nodes.size();i++) { + + const NodeData &nd=nodes[i]; + rnodes.push_back(nd.parent); + rnodes.push_back(nd.owner); + rnodes.push_back(nd.type); + rnodes.push_back(nd.name); + rnodes.push_back(nd.instance); + rnodes.push_back(nd.properties.size()); + for(int j=0;j<nd.properties.size();j++) { + + rnodes.push_back(nd.properties[j].name); + rnodes.push_back(nd.properties[j].value); + } + rnodes.push_back(nd.groups.size()); + for(int j=0;j<nd.groups.size();j++) { + + rnodes.push_back(nd.groups[j]); + } + } + + d["nodes"]=rnodes; + + Vector<int> rconns; + d["conn_count"]=connections.size(); + + for(int i=0;i<connections.size();i++) { + + const ConnectionData &cd=connections[i]; + rconns.push_back(cd.from); + rconns.push_back(cd.to); + rconns.push_back(cd.signal); + rconns.push_back(cd.method); + rconns.push_back(cd.flags); + rconns.push_back(cd.binds.size()); + for(int j=0;j<cd.binds.size();j++) + rconns.push_back(cd.binds[j]); + + } + + d["conns"]=rconns; + d["version"]=1; + +// d["path"]=path; + + return d; + + +} + +void PackedScene::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("pack","path:Node"),&PackedScene::pack); + ObjectTypeDB::bind_method(_MD("instance:Node"),&PackedScene::instance,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("can_instance"),&PackedScene::can_instance); + ObjectTypeDB::bind_method(_MD("_set_bundled_scene"),&PackedScene::_set_bundled_scene); + ObjectTypeDB::bind_method(_MD("_get_bundled_scene"),&PackedScene::_get_bundled_scene); + + ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled"),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene")); + +} + +PackedScene::PackedScene() { + + +} diff --git a/script/SCsub b/script/SCsub deleted file mode 100644 index 7093dee36d..0000000000 --- a/script/SCsub +++ /dev/null @@ -1,16 +0,0 @@ -Import('env') - -env.script_sources=[] -env.add_source_files(env.script_sources,"*.cpp") - -Export('env') - -if (env["gdscript"]=="yes"): - SConscript('gdscript/SCsub'); -SConscript('multiscript/SCsub'); - -lib = env.Library("script",env.script_sources, LIBSUFFIX=env['platform_libsuffix']) - -env.Prepend(LIBS=[lib]) - - diff --git a/script/gdscript/SCsub b/script/gdscript/SCsub deleted file mode 100644 index dd812edec5..0000000000 --- a/script/gdscript/SCsub +++ /dev/null @@ -1,7 +0,0 @@ -Import('env') - -env.add_source_files(env.script_sources,"*.cpp") - -Export('env') - - diff --git a/script/multiscript/SCsub b/script/multiscript/SCsub deleted file mode 100644 index dd812edec5..0000000000 --- a/script/multiscript/SCsub +++ /dev/null @@ -1,7 +0,0 @@ -Import('env') - -env.add_source_files(env.script_sources,"*.cpp") - -Export('env') - - diff --git a/script/script_binder.cpp b/script/script_binder.cpp deleted file mode 100644 index 63c6d1d050..0000000000 --- a/script/script_binder.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/*************************************************/ -/* script_binder.cpp */ -/*************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/*************************************************/ -/* Source code within this file is: */ -/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */ -/* All Rights Reserved. */ -/*************************************************/ - -#include "script_binder.h" - diff --git a/script/script_binder.h b/script/script_binder.h deleted file mode 100644 index c3167a901d..0000000000 --- a/script/script_binder.h +++ /dev/null @@ -1,15 +0,0 @@ -/*************************************************/ -/* script_binder.h */ -/*************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/*************************************************/ -/* Source code within this file is: */ -/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */ -/* All Rights Reserved. */ -/*************************************************/ - -#ifndef SCRIPT_BINDER_H -#define SCRIPT_BINDER_H - -#endif // SCRIPT_BINDER_H diff --git a/tools/docdump/makemd.py b/tools/docdump/makemd.py new file mode 100644 index 0000000000..7cc2e9dc4b --- /dev/null +++ b/tools/docdump/makemd.py @@ -0,0 +1,345 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import sys +import xml.etree.ElementTree as ET + +input_list = [] + +for arg in sys.argv[1:]: + input_list.append(arg) + +if len(input_list) < 1: + print 'usage: makedoku.py <class_list.xml>' + sys.exit(0) + + +def validate_tag(elem, tag): + if elem.tag != tag: + print "Tag mismatch, expected '" + tag + "', got " + elem.tag + sys.exit(255) + + +class_names = [] +classes = {} + + +def make_class_list(class_list, columns): + + f = open('class_list.md', 'wb') + prev = 0 + col_max = len(class_list) / columns + 1 + print ('col max is ', col_max) + col_count = 0 + row_count = 0 + last_initial = '' + fit_columns = [] + + for n in range(0, columns): + fit_columns += [[]] + + indexers = [] + last_initial = '' + + idx = 0 + for n in class_list: + col = idx / col_max + if col >= columns: + col = columns - 1 + fit_columns[col] += [n] + idx += 1 + if n[:1] != last_initial: + indexers += [n] + last_initial = n[:1] + + row_max = 0 + f.write("\n") + + for n in range(0, columns): + if len(fit_columns[n]) > row_max: + row_max = len(fit_columns[n]) + + f.write("| ") + for n in range(0, columns): + f.write(" | |") + + f.write("\n") + f.write("| ") + for n in range(0, columns): + f.write(" --- | ------- |") + f.write("\n") + + for r in range(0, row_max): + s = '| ' + for c in range(0, columns): + if r >= len(fit_columns[c]): + continue + + classname = fit_columns[c][r] + initial = classname[0] + if classname in indexers: + s += '**' + initial + '** | ' + else: + s += ' | ' + + s += '[' + classname + '](class_'+ classname.lower()+') | ' + + s += '\n' + f.write(s) + + +def dokuize_text(txt): + + return txt + + +def dokuize_text(text): + pos = 0 + while True: + pos = text.find('[', pos) + if pos == -1: + break + + endq_pos = text.find(']', pos + 1) + if endq_pos == -1: + break + + pre_text = text[:pos] + post_text = text[endq_pos + 1:] + tag_text = text[pos + 1:endq_pos] + + if tag_text in class_names: + tag_text = make_type(tag_text) + else: + + # command + + cmd = tag_text + space_pos = tag_text.find(' ') + if cmd.find('html') == 0: + cmd = tag_text[:space_pos] + param = tag_text[space_pos + 1:] + tag_text = '<' + param + '>' + elif cmd.find('method') == 0: + cmd = tag_text[:space_pos] + param = tag_text[space_pos + 1:] + + if param.find('.') != -1: + (class_param, method_param) = param.split('.') + tag_text = '['+class_param+'.'+method_param.replace("_","_")+'](' + class_param.lower() + '#' \ + + method_param + ')' + else: + tag_text = '[' + param.replace("_","_") + '](#' + param + ')' + elif cmd.find('image=') == 0: + tag_text = '' + elif cmd.find('url=') == 0: + tag_text = '[' + cmd[4:] + ']('+cmd[4:] + elif cmd == '/url': + tag_text = ')' + elif cmd == 'center': + tag_text = '' + elif cmd == '/center': + tag_text = '' + elif cmd == 'br': + tag_text = '\n' + elif cmd == 'i' or cmd == '/i': + tag_text = '_' + elif cmd == 'b' or cmd == '/b': + tag_text = '**' + elif cmd == 'u' or cmd == '/u': + tag_text = '__' + else: + tag_text = '[' + tag_text + ']' + + text = pre_text + tag_text + post_text + pos = len(pre_text) + len(tag_text) + + # tnode = ET.SubElement(parent,"div") + # tnode.text=text + + return text + + +def make_type(t): + global class_names + if t in class_names: + return '[' + t + '](class_' + t.lower() + ')' + return t + + +def make_method( + f, + name, + m, + declare, + event=False, + ): + + s = ' * ' + ret_type = 'void' + args = list(m) + mdata = {} + mdata['argidx'] = [] + for a in args: + if a.tag == 'return': + idx = -1 + elif a.tag == 'argument': + idx = int(a.attrib['index']) + else: + continue + + mdata['argidx'].append(idx) + mdata[idx] = a + + if not event: + if -1 in mdata['argidx']: + s += make_type(mdata[-1].attrib['type']) + else: + s += 'void' + s += ' ' + + if declare: + + # span.attrib["class"]="funcdecl" + # a=ET.SubElement(span,"a") + # a.attrib["name"]=name+"_"+m.attrib["name"] + # a.text=name+"::"+m.attrib["name"] + + s += ' **'+m.attrib['name'].replace("_","_")+'** ' + else: + s += ' **['+ m.attrib['name'].replace("_","_")+'](#' + m.attrib['name'] + ')** ' + + s += ' **(**' + argfound = False + for a in mdata['argidx']: + arg = mdata[a] + if a < 0: + continue + if a > 0: + s += ', ' + else: + s += ' ' + + s += make_type(arg.attrib['type']) + if 'name' in arg.attrib: + s += ' ' + arg.attrib['name'] + else: + s += ' arg' + str(a) + + if 'default' in arg.attrib: + s += '=' + arg.attrib['default'] + + argfound = True + + if argfound: + s += ' ' + s += ' **)**' + + if 'qualifiers' in m.attrib: + s += ' ' + m.attrib['qualifiers'] + + f.write(s + '\n') + + +def make_doku_class(node): + + name = node.attrib['name'] + + f = open("class_"+name.lower() + '.md', 'wb') + + f.write('# ' + name + ' \n') + + if 'inherits' in node.attrib: + inh = node.attrib['inherits'].strip() + f.write('####**Inherits:** '+make_type(inh)+'\n') + if 'category' in node.attrib: + f.write('####**Category:** ' + node.attrib['category'].strip() + + '\n') + + briefd = node.find('brief_description') + if briefd != None: + f.write('\n### Brief Description \n') + f.write(dokuize_text(briefd.text.strip()) + '\n') + + methods = node.find('methods') + + if methods != None and len(list(methods)) > 0: + f.write('\n### Member Functions \n') + for m in list(methods): + make_method(f, node.attrib['name'], m, False) + + events = node.find('signals') + if events != None and len(list(events)) > 0: + f.write('\n### Signals \n') + for m in list(events): + make_method(f, node.attrib['name'], m, True, True) + + members = node.find('members') + + if members != None and len(list(members)) > 0: + f.write('\n### Member Variables \n') + + for c in list(members): + s = ' * ' + s += make_type(c.attrib['type']) + ' ' + s += '**' + c.attrib['name'] + '**' + if c.text.strip() != '': + s += ' - ' + c.text.strip() + f.write(s + '\n') + + constants = node.find('constants') + if constants != None and len(list(constants)) > 0: + f.write('\n### Numeric Constants \n') + for c in list(constants): + s = ' * ' + s += '**' + c.attrib['name'] + '**' + if 'value' in c.attrib: + s += ' = **' + c.attrib['value'] + '**' + if c.text.strip() != '': + s += ' - ' + c.text.strip() + f.write(s + '\n') + + descr = node.find('description') + if descr != None and descr.text.strip() != '': + f.write('\n### Description \n') + f.write(dokuize_text(descr.text.strip()) + '\n') + + methods = node.find('methods') + + if methods != None and len(list(methods)) > 0: + f.write('\n### Member Function Description \n') + for m in list(methods): + + d = m.find('description') + if d == None or d.text.strip() == '': + continue + f.write('\n#### <a name="'+m.attrib['name']+'">' + m.attrib['name'] + '</a>\n') + make_method(f, node.attrib['name'], m, True) + f.write('\n') + f.write(dokuize_text(d.text.strip())) + f.write('\n') + + +for file in input_list: + tree = ET.parse(file) + doc = tree.getroot() + + if 'version' not in doc.attrib: + print "Version missing from 'doc'" + sys.exit(255) + + version = doc.attrib['version'] + + for c in list(doc): + if c.attrib['name'] in class_names: + continue + class_names.append(c.attrib['name']) + classes[c.attrib['name']] = c + +class_names.sort() + +make_class_list(class_names, 3) + +for cn in class_names: + c = classes[cn] + make_doku_class(c) + diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 87d3e17694..1a5dd73040 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -124,6 +124,40 @@ EditorImportPlugin::EditorImportPlugin() { ///////////////////////////////////////////////////////////////////////////////////////////////////// +void EditorExportPlugin::_bind_methods() { + + BIND_VMETHOD( MethodInfo("custom_export:Dictionary",PropertyInfo(Variant::STRING,"name",PROPERTY_HINT_RESOURCE_TYPE,"EditorExportPlatformPC")) ); +} + + +Vector<uint8_t> EditorExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) { + + if (get_script_instance()) { + + Variant d = get_script_instance()->call("custom_export",p_path,p_platform); + if (d.get_type()==Variant::NIL) + return Vector<uint8_t>(); + ERR_FAIL_COND_V(d.get_type()!=Variant::DICTIONARY,Vector<uint8_t>()); + Dictionary dict=d; + ERR_FAIL_COND_V(!dict.has("name"),Vector<uint8_t>()); + ERR_FAIL_COND_V(!dict.has("data"),Vector<uint8_t>()); + p_path=dict["name"]; + return dict["data"]; + } + + return Vector<uint8_t>(); + +} + + +EditorExportPlugin::EditorExportPlugin() { + + +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + static void _add_to_list(EditorFileSystemDirectory *p_efsd,Set<StringName>& r_list) { for(int i=0;i<p_efsd->get_subdir_count();i++) { @@ -223,48 +257,17 @@ static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) Vector<uint8_t> EditorExportPlatform::get_exported_file(String& p_fname) const { + Ref<EditorExportPlatform> ep=EditorImportExport::get_singleton()->get_export_platform(get_name()); - Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_fname); - - if (rimd.is_valid()) { - - if (rimd->get_editor()!="") { - Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name(rimd->get_editor()); - if (pl.is_valid()) { - Vector<uint8_t> ce = pl->custom_export(p_fname,EditorImportExport::get_singleton()->get_export_platform(get_name())); - if (ce.size()) - return ce; - } - } - } else if (EditorImportExport::get_singleton()->image_get_export_group(p_fname)) { - - - Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture_2d"); - if (pl.is_valid()) { - Vector<uint8_t> ce = pl->custom_export(p_fname,EditorImportExport::get_singleton()->get_export_platform(get_name())); - if (ce.size()) { - p_fname=p_fname.basename()+".tex"; - return ce; - } - } - - } else if (EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE){ + for(int i=0;i<EditorImportExport::get_singleton()->get_export_plugin_count();i++) { - String xt = p_fname.extension().to_lower(); - print_line("TRY FOR: "+p_fname); - if (EditorImportExport::get_singleton()->get_image_formats().has(xt)) { //should check for more I guess? + Vector<uint8_t> data = EditorImportExport::get_singleton()->get_export_plugin(i)->custom_export(p_fname,ep); + if (data.size()) + return data; - Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture_2d"); - if (pl.is_valid()) { - Vector<uint8_t> ce = pl->custom_export(p_fname,EditorImportExport::get_singleton()->get_export_platform(get_name())); - if (ce.size()) { - p_fname=p_fname.basename()+".tex"; - return ce; - } - } - } } + FileAccess *f = FileAccess::open(p_fname,FileAccess::READ); ERR_FAIL_COND_V(!f,Vector<uint8_t>()); Vector<uint8_t> ret; @@ -489,6 +492,7 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func int group_format=0; float group_lossy_quality=EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(E->get()); int group_shrink=EditorImportExport::get_singleton()->image_export_group_get_shrink(E->get()); + group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink(); switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(E->get())) { case EditorImportExport::IMAGE_ACTION_NONE: { @@ -1061,12 +1065,29 @@ Ref<EditorImportPlugin> EditorImportExport::get_import_plugin(int p_idx) const{ return plugins[p_idx]; } + + + Ref<EditorImportPlugin> EditorImportExport::get_import_plugin_by_name(const String& p_string) const{ ERR_FAIL_COND_V( !by_idx.has(p_string), Ref<EditorImportPlugin>()); return plugins[ by_idx[p_string] ]; } +void EditorImportExport::add_export_plugin(const Ref<EditorExportPlugin>& p_plugin) { + + export_plugins.push_back(p_plugin); +} + +int EditorImportExport::get_export_plugin_count() const{ + + return export_plugins.size(); +} +Ref<EditorExportPlugin> EditorImportExport::get_export_plugin(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,export_plugins.size(),Ref<EditorExportPlugin>()); + return export_plugins[p_idx]; +} void EditorImportExport::set_export_file_action(const StringName& p_file, FileAction p_action) { @@ -1166,6 +1187,16 @@ EditorImportExport::ImageAction EditorImportExport::get_export_image_action() co return image_action; } +void EditorImportExport::set_export_image_shrink(int p_shrink) { + + image_shrink=p_shrink; +} + +int EditorImportExport::get_export_image_shrink() const{ + + return image_shrink; +} + void EditorImportExport::set_export_image_quality(float p_quality){ @@ -1316,6 +1347,10 @@ void EditorImportExport::load_config() { image_action=IMAGE_ACTION_COMPRESS_DISK; image_action_compress_quality = cf->get_value(ci,"compress_quality"); + if (cf->has_section_key(ci,"shrink")) + image_shrink = cf->get_value(ci,"shrink"); + else + image_shrink=1; String formats=cf->get_value(ci,"formats"); Vector<String> f = formats.split(","); image_formats.clear(); @@ -1362,8 +1397,6 @@ void EditorImportExport::load_config() { List<String> keys; cf->get_section_keys(s,&keys); for(List<String>::Element *F=keys.front();F;F=F->next()) { - print_line("sk: "+F->get()); - ep->set(F->get(),cf->get_value(s,F->get())); } } @@ -1474,6 +1507,7 @@ void EditorImportExport::save_config() { case IMAGE_ACTION_COMPRESS_DISK: cf->set_value("convert_images","action","compress_disk"); break; } + cf->set_value("convert_images","shrink",image_shrink); cf->set_value("convert_images","compress_quality",image_action_compress_quality); String formats; @@ -1542,9 +1576,7 @@ EditorImportExport::EditorImportExport() { image_action=IMAGE_ACTION_NONE; image_action_compress_quality=0.7; image_formats.insert("png"); - - - + image_shrink=1; } diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h index 1e5e733921..94fbaba842 100644 --- a/tools/editor/editor_import_export.h +++ b/tools/editor/editor_import_export.h @@ -36,6 +36,7 @@ class EditorExportPlatform; class FileAccess; class EditorProgress; + class EditorImportPlugin : public Reference { OBJ_TYPE( EditorImportPlugin, Reference); @@ -59,6 +60,20 @@ public: EditorImportPlugin(); }; +class EditorExportPlugin : public Reference { + + OBJ_TYPE( EditorExportPlugin, Reference); + +protected: + static void _bind_methods(); + +public: + + virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform); + + EditorExportPlugin(); +}; + class EditorExportPlatform : public Reference { OBJ_TYPE( EditorExportPlatform,Reference ); @@ -223,10 +238,12 @@ protected: int shrink; }; + Vector<Ref<EditorExportPlugin> > export_plugins; Vector<Ref<EditorImportPlugin> > plugins; Map<String,int> by_idx; ImageAction image_action; float image_action_compress_quality; + int image_shrink; Set<String> image_formats; ExportFilter export_filter; @@ -249,6 +266,10 @@ public: Ref<EditorImportPlugin> get_import_plugin(int p_idx) const; Ref<EditorImportPlugin> get_import_plugin_by_name(const String& p_string) const; + void add_export_plugin(const Ref<EditorExportPlugin>& p_plugin); + int get_export_plugin_count() const; + Ref<EditorExportPlugin> get_export_plugin(int p_idx) const; + bool poll_export_platforms(); void set_export_file_action(const StringName& p_export_file, FileAction p_action); @@ -268,6 +289,9 @@ public: void set_export_image_action(ImageAction p_action); ImageAction get_export_image_action() const; + void set_export_image_shrink(int p_shrink); + int get_export_image_shrink() const; + void set_export_image_quality(float p_quality); float get_export_image_quality() const; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 33b2e72d62..d8f9dcc947 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -3058,6 +3058,12 @@ void EditorNode::register_editor_types() { // ObjectTypeDB::register_type<EditorPostImport>(); } +void EditorNode::unregister_editor_types() { + + _init_callbacks.clear(); +} + + void EditorNode::stop_child_process() { _menu_option_confirm(RUN_STOP,false); @@ -3193,6 +3199,7 @@ void EditorNode::_file_dialog_unregister(FileDialog *p_dialog){ singleton->file_dialogs.erase(p_dialog); } +Vector<EditorNodeInitCallback> EditorNode::_init_callbacks; Error EditorNode::export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after) { @@ -3451,8 +3458,8 @@ EditorNode::EditorNode() { p->add_item("Run Script",FILE_RUN_SCRIPT,KEY_MASK_CMD+KEY_R); p->add_separator(); p->add_item("Project Settings",RUN_SETTINGS); - p->add_item("Project Manager",RUN_PROJECT_MANAGER); p->add_separator(); + p->add_item("Quit to Project List",RUN_PROJECT_MANAGER); p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q); recent_scenes = memnew( PopupMenu ); @@ -4006,10 +4013,12 @@ EditorNode::EditorNode() { editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( memnew(EditorTranslationImportPlugin(this)))); + for(int i=0;i<editor_import_export->get_import_plugin_count();i++) { import_menu->get_popup()->add_item(editor_import_export->get_import_plugin(i)->get_visible_name(),IMPORT_PLUGIN_BASE+i); } + editor_import_export->add_export_plugin( Ref<EditorTextureExportPlugin>( memnew(EditorTextureExportPlugin))); add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) ); add_editor_plugin( memnew( SpatialEditorPlugin(this) ) ); @@ -4153,6 +4162,8 @@ EditorNode::EditorNode() { // Ref<ImageTexture> it = gui_base->get_icon("logo","Icons"); // OS::get_singleton()->set_icon( it->get_data() ); + for(int i=0;i<_init_callbacks.size();i++) + _init_callbacks[i](); } diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 30504aa08e..87f17247c3 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -91,6 +91,9 @@ + +typedef void (*EditorNodeInitCallback)(); + class EditorNode : public Node { OBJ_TYPE( EditorNode, Node ); @@ -393,6 +396,8 @@ class EditorNode : public Node { static EditorNode *singleton; + static Vector<EditorNodeInitCallback> _init_callbacks; + protected: void _notification(int p_what); static void _bind_methods(); @@ -463,6 +468,7 @@ public: Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false); static void register_editor_types(); + static void unregister_editor_types(); Control *get_gui_base() { return gui_base; } @@ -481,6 +487,8 @@ public: ~EditorNode(); void get_singleton(const char* arg1, bool arg2); + static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); } + }; diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 53b5a8a47d..09d55650c8 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -413,7 +413,7 @@ void EditorSettings::_load_defaults() { set("on_save/compress_binary_resources",true); set("on_save/save_modified_external_resources",true); set("on_save/save_paths_as_relative",false); - set("on_save/save_paths_without_extension",true); + set("on_save/save_paths_without_extension",false); set("text_editor/create_signal_callbacks",true); diff --git a/tools/editor/io_plugins/editor_font_import_plugin.cpp b/tools/editor/io_plugins/editor_font_import_plugin.cpp index 7c38b105fd..4de68c7f4c 100644 --- a/tools/editor/io_plugins/editor_font_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -884,15 +884,20 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata ++missing; }; }; - printf("total %i/%i\n", missing, import_chars.size()); + print_line("total_chars: "+itos(font_data_list.size())); /* KERNING */ for(int i=0;i<font_data_list.size();i++) { + if (font_data_list[i]->character>512) + continue; for(int j=0;j<font_data_list.size();j++) { + if (font_data_list[j]->character>512) + continue; + FT_Vector delta; FT_Get_Kerning( face, font_data_list[i]->glyph,font_data_list[j]->glyph, FT_KERNING_DEFAULT, &delta ); diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp index ffb68dff83..5fce4233e1 100644 --- a/tools/editor/io_plugins/editor_import_collada.cpp +++ b/tools/editor/io_plugins/editor_import_collada.cpp @@ -108,6 +108,7 @@ Error ColladaImport::_populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_no Collada::NodeJoint *joint = static_cast<Collada::NodeJoint*>(p_node); + p_skeleton->add_bone(p_node->name); if (p_parent>=0) p_skeleton->set_bone_parent(r_bone,p_parent); diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 2e6e755136..90dcbb97e0 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -610,7 +610,7 @@ String EditorTextureImportPlugin::get_visible_name() const { } break; case MODE_ATLAS: { - return "Atlas Teture"; + return "Atlas Texture"; } break; } @@ -899,6 +899,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc } } + if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) { Image image=texture->get_data(); @@ -952,6 +953,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc } else { + print_line("compress..."); Image image=texture->get_data(); ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA); @@ -988,13 +990,17 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc } + print_line("COMPRESSED TO: "+itos(image.get_format())); texture->create_from_image(image,tex_flags); + if (shrink>1) { texture->set_size_override(Size2(orig_w,orig_h)); } - Error err = ResourceSaver::save(p_path,texture); + uint32_t save_flags=ResourceSaver::FLAG_COMPRESS; + + Error err = ResourceSaver::save(p_path,texture,save_flags); if (err!=OK) { EditorNode::add_io_error("Couldn't save converted texture: "+p_path); return err; @@ -1021,6 +1027,7 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c int group_format=0; float group_lossy_quality=EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(group); int group_shrink=EditorImportExport::get_singleton()->image_export_group_get_shrink(group); + group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink(); switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(group)) { case EditorImportExport::IMAGE_ACTION_NONE: { @@ -1062,6 +1069,7 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c flags|=IMAGE_FLAG_FIX_BORDER_ALPHA; + print_line("group format"+itos(group_format)); rimd->set_option("format",group_format); rimd->set_option("flags",flags); rimd->set_option("quality",group_lossy_quality); @@ -1090,6 +1098,7 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c flags|=IMAGE_FLAG_FIX_BORDER_ALPHA; + rimd->set_option("shrink",EditorImportExport::get_singleton()->get_export_image_shrink()); rimd->set_option("flags",flags); rimd->set_option("quality",EditorImportExport::get_singleton()->get_export_image_quality()); rimd->set_option("atlas",false); @@ -1108,18 +1117,21 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c } uint32_t flags = rimd->get_option("flags"); + uint8_t shrink = rimd->has_option("shrink") ? rimd->get_option("shrink"): Variant(1); + uint8_t format = rimd->get_option("format"); + uint8_t comp = (format==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM)?uint8_t(p_platform->get_image_compression()):uint8_t(255); MD5_CTX ctx; uint8_t f4[4]; encode_uint32(flags,&f4[0]); - uint8_t ic = p_platform->get_image_compression(); MD5Init(&ctx); String gp = Globals::get_singleton()->globalize_path(p_path); CharString cs = gp.utf8(); MD5Update(&ctx,(unsigned char*)cs.get_data(),cs.length()); MD5Update(&ctx,f4,4); - MD5Update(&ctx,&ic,1); - + MD5Update(&ctx,&format,1); + MD5Update(&ctx,&comp,1); + MD5Update(&ctx,&shrink,1); MD5Final(&ctx); uint64_t sd=0; @@ -1137,6 +1149,7 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c uint64_t d = f->get_line().strip_edges().to_int64(); sd = FileAccess::get_modified_time(p_path); + if (d==sd) { valid=true; } else { @@ -1190,3 +1203,56 @@ EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode editor->get_gui_base()->add_child(dialog); } + +//////////////////////////// + + + Vector<uint8_t> EditorTextureExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) { + + Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path); + + if (rimd.is_valid()) { + + if (rimd->get_editor()!="") { + Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name(rimd->get_editor()); + if (pl.is_valid()) { + Vector<uint8_t> ce = pl->custom_export(p_path,p_platform); + if (ce.size()) + return ce; + } + } + } else if (EditorImportExport::get_singleton()->image_get_export_group(p_path)) { + + + Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture_2d"); + if (pl.is_valid()) { + Vector<uint8_t> ce = pl->custom_export(p_path,p_platform); + if (ce.size()) { + p_path=p_path.basename()+".tex"; + return ce; + } + } + + } else if (EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE){ + + String xt = p_path.extension().to_lower(); + if (EditorImportExport::get_singleton()->get_image_formats().has(xt)) { //should check for more I guess? + + Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture_2d"); + if (pl.is_valid()) { + Vector<uint8_t> ce = pl->custom_export(p_path,p_platform); + if (ce.size()) { + p_path=p_path.basename()+".tex"; + return ce; + } + } + } + } + + return Vector<uint8_t>(); +} + +EditorTextureExportPlugin::EditorTextureExportPlugin() { + + +} diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h index 4a9dd6ae9d..b2950a889c 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.h +++ b/tools/editor/io_plugins/editor_texture_import_plugin.h @@ -106,6 +106,16 @@ public: }; +class EditorTextureExportPlugin : public EditorExportPlugin { + + OBJ_TYPE( EditorTextureExportPlugin, EditorExportPlugin); + + +public: + + virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform); + EditorTextureExportPlugin(); +}; class EditorImportTextureOptions : public VBoxContainer { OBJ_TYPE( EditorImportTextureOptions, VBoxContainer ); diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index be7214aaa7..0014c5a68a 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -1407,6 +1407,9 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { } break; + case KEY_F: { + _menu_option(VIEW_CENTER_TO_SELECTION); + } break; } diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index 192fcaa908..eae5dacb27 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -207,6 +207,12 @@ void ProjectExportDialog::_quality_edited(float what) { _save_export_cfg(); } +void ProjectExportDialog::_shrink_edited(float what) { + + EditorImportExport::get_singleton()->set_export_image_shrink(what); + _save_export_cfg(); +} + void ProjectExportDialog::_image_export_edited(int what) { EditorImportExport::get_singleton()->set_export_image_action(EditorImportExport::ImageAction(what)); @@ -270,7 +276,9 @@ void ProjectExportDialog::_notification(int p_what) { image_action->select(EditorImportExport::get_singleton()->get_export_image_action()); image_quality->set_val(EditorImportExport::get_singleton()->get_export_image_quality()); + image_shrink->set_val(EditorImportExport::get_singleton()->get_export_image_quality()); image_quality->connect("value_changed",this,"_quality_edited"); + image_shrink->connect("value_changed",this,"_shrink_edited"); image_action->connect("item_selected",this,"_image_export_edited"); for(int i=0;i<formats.size();i++) { @@ -966,6 +974,7 @@ void ProjectExportDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_export_action"),&ProjectExportDialog::_export_action); ObjectTypeDB::bind_method(_MD("_export_action_pck"),&ProjectExportDialog::_export_action_pck); ObjectTypeDB::bind_method(_MD("_quality_edited"),&ProjectExportDialog::_quality_edited); + ObjectTypeDB::bind_method(_MD("_shrink_edited"),&ProjectExportDialog::_shrink_edited); ObjectTypeDB::bind_method(_MD("_image_export_edited"),&ProjectExportDialog::_image_export_edited); ObjectTypeDB::bind_method(_MD("_format_toggled"),&ProjectExportDialog::_format_toggled); ObjectTypeDB::bind_method(_MD("_group_changed"),&ProjectExportDialog::_group_changed); @@ -1090,6 +1099,11 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { image_quality->set_max(1); image_quality->set_step(0.01); image_vb->add_margin_child("Compress for Disk (Lossy) Quality:",qhb); + image_shrink = memnew( SpinBox ); + image_shrink->set_min(1); + image_shrink->set_max(8); + image_shrink->set_step(1); + image_vb->add_margin_child("Shrink All Images:",image_shrink); sections->add_child(image_vb); image_formats=memnew(Tree); diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h index 25709babb9..6ceffadc62 100644 --- a/tools/editor/project_export.h +++ b/tools/editor/project_export.h @@ -110,6 +110,7 @@ private: VBoxContainer *image_vb; OptionButton *image_action; HSlider *image_quality; + SpinBox *image_shrink; Tree *image_formats; Vector<TreeItem*> formats; @@ -150,6 +151,8 @@ private: void _quality_edited(float what); void _image_export_edited(int what); + void _shrink_edited(float what); + void _update_group_list(); void _select_group(const String& p_by_name); diff --git a/plugins/terrain/plugin.cfg b/tools/script_plugins/terrain/plugin.cfg index d2f2917420..d2f2917420 100644 --- a/plugins/terrain/plugin.cfg +++ b/tools/script_plugins/terrain/plugin.cfg diff --git a/plugins/terrain/terrain.gd b/tools/script_plugins/terrain/terrain.gd index b3e3121e7a..b3e3121e7a 100644 --- a/plugins/terrain/terrain.gd +++ b/tools/script_plugins/terrain/terrain.gd diff --git a/plugins/terrain/terrain.png b/tools/script_plugins/terrain/terrain.png Binary files differindex 7c1c3d70d6..7c1c3d70d6 100644 --- a/plugins/terrain/terrain.png +++ b/tools/script_plugins/terrain/terrain.png diff --git a/plugins/terrain/terrain_node.gd b/tools/script_plugins/terrain/terrain_node.gd index 91cf3fcb2b..91cf3fcb2b 100644 --- a/plugins/terrain/terrain_node.gd +++ b/tools/script_plugins/terrain/terrain_node.gd diff --git a/plugins/time/plugin.cfg b/tools/script_plugins/time/plugin.cfg index 5430306a79..5430306a79 100644 --- a/plugins/time/plugin.cfg +++ b/tools/script_plugins/time/plugin.cfg diff --git a/plugins/time/time.gd b/tools/script_plugins/time/time.gd index 66b3e9ed04..66b3e9ed04 100644 --- a/plugins/time/time.gd +++ b/tools/script_plugins/time/time.gd |