summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/tests/test_gdscript.cpp10
-rw-r--r--bin/tests/test_gdscript.h3
-rw-r--r--bin/tests/test_main.cpp5
-rw-r--r--core/bind/core_bind.cpp52
-rw-r--r--core/bind/core_bind.h1
-rw-r--r--core/image.cpp17
-rw-r--r--core/image.h3
-rw-r--r--core/io/resource_format_binary.cpp9
-rw-r--r--core/io/resource_format_xml.cpp9
-rw-r--r--core/io/resource_loader.cpp3
-rw-r--r--core/variant_call.cpp3
-rw-r--r--core/variant_op.cpp3
-rw-r--r--core/vmap.h6
-rw-r--r--demos/2d/platformer/engine.cfg4
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp148
-rw-r--r--drivers/gles2/rasterizer_gles2.h3
-rw-r--r--main/main.cpp4
-rw-r--r--modules/gdscript/gd_editor.cpp2
-rw-r--r--modules/gdscript/gd_parser.cpp585
-rw-r--r--modules/gdscript/gd_parser.h7
-rw-r--r--modules/gdscript/gd_script.cpp79
-rw-r--r--modules/gdscript/gd_script.h1
-rw-r--r--modules/gdscript/gd_tokenizer.cpp409
-rw-r--r--modules/gdscript/gd_tokenizer.h86
-rw-r--r--modules/gdscript/register_types.cpp56
-rw-r--r--scene/2d/node_2d.cpp4
-rw-r--r--scene/2d/tile_map.cpp4
-rw-r--r--scene/gui/tree.cpp2
-rw-r--r--scene/main/node.cpp2
-rw-r--r--scene/main/viewport.cpp27
-rw-r--r--scene/main/viewport.h2
-rw-r--r--tools/editor/editor_import_export.cpp22
-rw-r--r--tools/editor/editor_import_export.h4
-rw-r--r--tools/editor/editor_node.cpp11
-rw-r--r--tools/editor/editor_node.h8
-rw-r--r--tools/editor/editor_settings.cpp2
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.cpp7
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp21
-rw-r--r--tools/editor/project_export.cpp14
-rw-r--r--tools/editor/project_export.h3
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);