diff options
40 files changed, 1257 insertions, 384 deletions
diff --git a/bin/tests/test_gdscript.cpp b/bin/tests/test_gdscript.cpp index 847be39fb4..9670e6af6e 100644 --- a/bin/tests/test_gdscript.cpp +++ b/bin/tests/test_gdscript.cpp @@ -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 bd8e46556c..fc5aecfd99 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -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 8ed49a38e4..7d19c2ebcf 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1365,6 +1365,10 @@ 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(); diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index c10cadf83f..f8717c292f 100644 --- a/modules/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/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index e558ceb416..fb4f56aa8f 100644 --- a/modules/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/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 8011495340..1925808cac 100644 --- a/modules/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/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index 5679e1e066..29857e6be6 100644 --- a/modules/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/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 70dec4e8ee..55bc547e8d 100644 --- a/modules/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/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index f7320799a5..ff9be7926b 100644 --- a/modules/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/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h index 24ee2be7ad..c517e07b89 100644 --- a/modules/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/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index d2d7bf426a..6bcd12857b 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -13,11 +13,60 @@ #include "gd_script.h" #include "io/resource_loader.h" +#include "os/file_access.h" + GDScriptLanguage *script_language_gd=NULL; ResourceFormatLoaderGDScript *resource_loader_gd=NULL; ResourceFormatSaverGDScript *resource_saver_gd=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: + + 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() { @@ -30,6 +79,11 @@ void register_gdscript_types() { resource_saver_gd=memnew( ResourceFormatSaverGDScript ); ResourceSaver::add_resource_format_saver(resource_saver_gd); +#ifdef TOOLS_ENABLED + + EditorNode::add_init_callback(register_editor_plugin); +#endif + } void unregister_gdscript_types() { @@ -43,4 +97,4 @@ void unregister_gdscript_types() { if (resource_saver_gd) memdelete( resource_saver_gd ); -}
\ No newline at end of file +} 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/2d/tile_map.cpp b/scene/2d/tile_map.cpp index a3917f729c..b9e44d5053 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -585,8 +585,8 @@ TileMap::TileMap() { center_x=false; center_y=false; - fp_adjust=0.1; - fp_adjust=0.1; + fp_adjust=0.4; + fp_adjust=0.4; } TileMap::~TileMap() { 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/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 22b611fdcc..1a5dd73040 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -492,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: { @@ -1186,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){ @@ -1336,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(); @@ -1382,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())); } } @@ -1494,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; @@ -1562,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 17f2592ad5..94fbaba842 100644 --- a/tools/editor/editor_import_export.h +++ b/tools/editor/editor_import_export.h @@ -243,6 +243,7 @@ protected: Map<String,int> by_idx; ImageAction image_action; float image_action_compress_quality; + int image_shrink; Set<String> image_formats; ExportFilter export_filter; @@ -288,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 ae350e3b99..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 ); @@ -4155,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_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 067edee5a0..ff4da6af13 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -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 { 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); |