diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/color.h | 34 | ||||
-rw-r--r-- | core/image.cpp | 482 | ||||
-rw-r--r-- | core/image.h | 44 | ||||
-rw-r--r-- | core/io/image_loader.cpp | 4 | ||||
-rw-r--r-- | core/io/image_loader.h | 4 | ||||
-rw-r--r-- | core/math/math_funcs.h | 8 | ||||
-rw-r--r-- | core/method_ptrcall.h | 1 | ||||
-rw-r--r-- | core/os/file_access.cpp | 21 | ||||
-rw-r--r-- | core/os/file_access.h | 1 | ||||
-rw-r--r-- | core/os/input_event.cpp | 64 | ||||
-rw-r--r-- | core/os/input_event.h | 16 | ||||
-rw-r--r-- | core/os/os.h | 2 | ||||
-rw-r--r-- | core/ustring.cpp | 12 | ||||
-rw-r--r-- | core/variant_parser.cpp | 159 |
14 files changed, 743 insertions, 109 deletions
diff --git a/core/color.h b/core/color.h index 46386fac64..c83dcda4b4 100644 --- a/core/color.h +++ b/core/color.h @@ -83,6 +83,40 @@ struct Color { return res; } + _FORCE_INLINE_ uint32_t to_rgbe9995() const { + + const float pow2to9 = 512.0f; + const float B = 15.0f; + //const float Emax = 31.0f; + const float N = 9.0f; + + float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f); + + float cRed = MAX(0.0f, MIN(sharedexp, r)); + float cGreen = MAX(0.0f, MIN(sharedexp, g)); + float cBlue = MAX(0.0f, MIN(sharedexp, b)); + + float cMax = MAX(cRed, MAX(cGreen, cBlue)); + + // expp = MAX(-B - 1, log2(maxc)) + 1 + B + + float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B; + + float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f); + + float exps = expp + 1.0f; + + if (0.0 <= sMax && sMax < pow2to9) { + exps = expp; + } + + float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f); + float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f); + float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f); + + return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27); + } + _FORCE_INLINE_ Color blend(const Color &p_over) const { Color res; diff --git a/core/image.cpp b/core/image.cpp index 316faf954e..2640c6be2a 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -45,7 +45,6 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "RedGreen", "RGB8", "RGBA8", - "RGB565", //16 bit "RGBA4444", "RGBA5551", "RFloat", //float @@ -56,11 +55,12 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "RGHalf", "RGBHalf", "RGBAHalf", - "DXT1", //s3tc - "DXT3", - "DXT5", - "ATI1", - "ATI2", + "RGBE9995", + "DXT1 RGB8", //s3tc + "DXT3 RGBA8", + "DXT5 RGBA8", + "RGTC Red8", + "RGTC RedGreen8", "BPTC_RGBA", "BPTC_RGBF", "BPTC_RGBFU", @@ -110,8 +110,6 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RG8: return 2; case FORMAT_RGB8: return 3; case FORMAT_RGBA8: return 4; - case FORMAT_RGB565: - return 2; //16 bit case FORMAT_RGBA4444: return 2; case FORMAT_RGBA5551: return 2; case FORMAT_RF: @@ -122,17 +120,18 @@ int Image::get_format_pixel_size(Format p_format) { case FORMAT_RH: return 2; //half float case FORMAT_RGH: return 4; - case FORMAT_RGBH: return 8; - case FORMAT_RGBAH: return 12; + case FORMAT_RGBH: return 6; + case FORMAT_RGBAH: return 8; + case FORMAT_RGBE9995: return 4; case FORMAT_DXT1: return 1; //s3tc bc1 case FORMAT_DXT3: return 1; //bc2 case FORMAT_DXT5: return 1; //bc3 - case FORMAT_ATI1: + case FORMAT_RGTC_R: return 1; //bc4 - case FORMAT_ATI2: + case FORMAT_RGTC_RG: return 1; //bc5 case FORMAT_BPTC_RGBA: return 1; //btpc bc6h @@ -168,8 +167,8 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { case FORMAT_DXT1: //s3tc bc1 case FORMAT_DXT3: //bc2 case FORMAT_DXT5: //bc3 - case FORMAT_ATI1: //bc4 - case FORMAT_ATI2: { //bc5 case case FORMAT_DXT1: + case FORMAT_RGTC_R: //bc4 + case FORMAT_RGTC_RG: { //bc5 case case FORMAT_DXT1: r_w = 4; r_h = 4; @@ -220,7 +219,7 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { int Image::get_format_pixel_rshift(Format p_format) { - if (p_format == FORMAT_DXT1 || p_format == FORMAT_ATI1 || p_format == FORMAT_PVRTC4 || p_format == FORMAT_PVRTC4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) + if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC4 || p_format == FORMAT_PVRTC4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) return 1; else if (p_format == FORMAT_PVRTC2 || p_format == FORMAT_PVRTC2A) return 2; @@ -228,6 +227,54 @@ int Image::get_format_pixel_rshift(Format p_format) { return 0; } +int Image::get_format_block_size(Format p_format) { + + switch (p_format) { + case FORMAT_DXT1: //s3tc bc1 + case FORMAT_DXT3: //bc2 + case FORMAT_DXT5: //bc3 + case FORMAT_RGTC_R: //bc4 + case FORMAT_RGTC_RG: { //bc5 case case FORMAT_DXT1: + + return 4; + } break; + case FORMAT_PVRTC2: + case FORMAT_PVRTC2A: { + + return 4; + } break; + case FORMAT_PVRTC4A: + case FORMAT_PVRTC4: { + + return 4; + } break; + case FORMAT_ETC: { + + return 4; + } break; + case FORMAT_BPTC_RGBA: + case FORMAT_BPTC_RGBF: + case FORMAT_BPTC_RGBFU: { + + return 4; + } break; + case FORMAT_ETC2_R11: //etc2 + case FORMAT_ETC2_R11S: //signed: NOT srgb. + case FORMAT_ETC2_RG11: + case FORMAT_ETC2_RG11S: + case FORMAT_ETC2_RGB8: + case FORMAT_ETC2_RGBA8: + case FORMAT_ETC2_RGB8A1: { + + return 4; + } break; + default: { + } + } + + return 1; +} + void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const { int w = width; @@ -236,11 +283,16 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_widt int pixel_size = get_format_pixel_size(format); int pixel_rshift = get_format_pixel_rshift(format); + int block = get_format_block_size(format); int minw, minh; get_format_min_pixel_size(format, minw, minh); for (int i = 0; i < p_mipmap; i++) { - int s = w * h; + int bw = w % block != 0 ? w + (block - w % block) : w; + int bh = h % block != 0 ? h + (block - h % block) : h; + + int s = bw * bh; + s *= pixel_size; s >>= pixel_rshift; ofs += s; @@ -356,10 +408,35 @@ void Image::convert(Format p_new_format) { if (p_new_format == format) return; - if (format >= FORMAT_RGB565 || p_new_format >= FORMAT_RGB565) { + if (format > FORMAT_RGBE9995 || p_new_format > FORMAT_RGBE9995) { - ERR_EXPLAIN("Cannot convert to <-> from non byte formats."); + ERR_EXPLAIN("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); ERR_FAIL(); + + } else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) { + + //use put/set pixel which is slower but works with non byte formats + Image new_img(width, height, 0, p_new_format); + lock(); + new_img.lock(); + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + + new_img.put_pixel(i, j, get_pixel(i, j)); + } + } + + unlock(); + new_img.unlock(); + + if (has_mipmaps()) { + new_img.generate_mipmaps(); + } + + _copy_internals_from(new_img); + + return; } Image new_img(width, height, 0, p_new_format); @@ -801,12 +878,17 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & int pixsize = get_format_pixel_size(p_format); int pixshift = get_format_pixel_rshift(p_format); + int block = get_format_block_size(p_format); int minw, minh; get_format_min_pixel_size(p_format, minw, minh); while (true) { - int s = w * h; + int bw = w % block != 0 ? w + (block - w % block) : w; + int bh = h % block != 0 ? h + (block - h % block) : h; + + int s = bw * bh; + s *= pixsize; s >>= pixshift; @@ -834,7 +916,7 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & bool Image::_can_modify(Format p_format) const { - return p_format < FORMAT_RGB565; + return p_format <= FORMAT_RGBE9995; } template <int CC> @@ -1392,12 +1474,12 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format } bool Image::is_compressed() const { - return format >= FORMAT_RGB565; + return format > FORMAT_RGBE9995; } Error Image::decompress() { - if (format >= FORMAT_DXT1 && format <= FORMAT_ATI2 && _image_decompress_bc) + if (format >= FORMAT_DXT1 && format <= FORMAT_BPTC_RGBFU && _image_decompress_bc) _image_decompress_bc(this); else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc) _image_decompress_pvrtc(this); @@ -1410,19 +1492,14 @@ Error Image::decompress() { return OK; } -Error Image::compress(CompressMode p_mode) { +Error Image::compress(CompressMode p_mode, bool p_for_srgb) { switch (p_mode) { - case COMPRESS_16BIT: { - - //ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); - //_image_compress_bc_func(this); - } break; case COMPRESS_S3TC: { ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); - _image_compress_bc_func(this); + _image_compress_bc_func(this, p_for_srgb); } break; case COMPRESS_PVRTC2: { @@ -1572,7 +1649,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po Ref<Image> (*Image::_png_mem_loader_func)(const uint8_t *, int) = NULL; Ref<Image> (*Image::_jpg_mem_loader_func)(const uint8_t *, int) = NULL; -void (*Image::_image_compress_bc_func)(Image *) = NULL; +void (*Image::_image_compress_bc_func)(Image *, bool) = NULL; void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL; void (*Image::_image_compress_pvrtc4_func)(Image *) = NULL; void (*Image::_image_compress_etc_func)(Image *) = NULL; @@ -1624,6 +1701,333 @@ Dictionary Image::_get_data() const { return d; } +void Image::lock() { + + ERR_FAIL_COND(data.size() == 0); + write_lock = data.write(); +} + +void Image::unlock() { + + write_lock = PoolVector<uint8_t>::Write(); +} + +Color Image::get_pixel(int p_x, int p_y) { + + uint8_t *ptr = write_lock.ptr(); +#ifdef DEBUG_ENABLED + if (!ptr) { + ERR_EXPLAIN("Image must be locked with 'lock()' before using get_pixel()"); + ERR_FAIL_COND_V(!ptr, Color()); + } + + ERR_FAIL_INDEX_V(p_x, width, Color()); + ERR_FAIL_INDEX_V(p_y, height, Color()); + +#endif + + uint32_t ofs = p_y * width + p_x; + + switch (format) { + case FORMAT_L8: { + float l = ptr[ofs] / 255.0; + return Color(l, l, l, 1); + } break; + case FORMAT_LA8: { + float l = ptr[ofs * 2 + 0] / 255.0; + float a = ptr[ofs * 2 + 1] / 255.0; + return Color(l, l, l, a); + } break; + case FORMAT_R8: { + + float r = ptr[ofs] / 255.0; + return Color(r, 0, 0, 1); + } break; + case FORMAT_RG8: { + + float r = ptr[ofs * 2 + 0] / 255.0; + float g = ptr[ofs * 2 + 1] / 255.0; + return Color(r, g, 0, 1); + } break; + case FORMAT_RGB8: { + float r = ptr[ofs * 3 + 0] / 255.0; + float g = ptr[ofs * 3 + 1] / 255.0; + float b = ptr[ofs * 3 + 2] / 255.0; + return Color(r, g, b, 1); + + } break; + case FORMAT_RGBA8: { + float r = ptr[ofs * 4 + 0] / 255.0; + float g = ptr[ofs * 4 + 1] / 255.0; + float b = ptr[ofs * 4 + 2] / 255.0; + float a = ptr[ofs * 4 + 3] / 255.0; + return Color(r, g, b, a); + + } break; + case FORMAT_RGBA4444: { + uint16_t u = ((uint16_t *)ptr)[ofs]; + float r = (u & 0xF) / 15.0; + float g = ((u >> 4) & 0xF) / 15.0; + float b = ((u >> 8) & 0xF) / 15.0; + float a = ((u >> 12) & 0xF) / 15.0; + return Color(r, g, b, a); + + } break; + case FORMAT_RGBA5551: { + + uint16_t u = ((uint16_t *)ptr)[ofs]; + float r = (u & 0x1F) / 15.0; + float g = ((u >> 5) & 0x1F) / 15.0; + float b = ((u >> 10) & 0x1F) / 15.0; + float a = ((u >> 15) & 0x1) / 1.0; + return Color(r, g, b, a); + } break; + case FORMAT_RF: { + + float r = ((float *)ptr)[ofs]; + return Color(r, 0, 0, 1); + } break; + case FORMAT_RGF: { + + float r = ((float *)ptr)[ofs * 2 + 0]; + float g = ((float *)ptr)[ofs * 2 + 1]; + return Color(r, g, 0, 1); + } break; + case FORMAT_RGBF: { + + float r = ((float *)ptr)[ofs * 3 + 0]; + float g = ((float *)ptr)[ofs * 3 + 1]; + float b = ((float *)ptr)[ofs * 3 + 2]; + return Color(r, g, b, 1); + } break; + case FORMAT_RGBAF: { + + float r = ((float *)ptr)[ofs * 4 + 0]; + float g = ((float *)ptr)[ofs * 4 + 1]; + float b = ((float *)ptr)[ofs * 4 + 2]; + float a = ((float *)ptr)[ofs * 4 + 3]; + return Color(r, g, b, a); + } break; + case FORMAT_RH: { + + uint16_t r = ((uint16_t *)ptr)[ofs]; + return Color(Math::half_to_float(r), 0, 0, 1); + } break; + case FORMAT_RGH: { + + uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0]; + uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1]; + return Color(Math::half_to_float(r), Math::half_to_float(g), 0, 1); + } break; + case FORMAT_RGBH: { + + uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0]; + uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1]; + uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2]; + return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), 1); + } break; + case FORMAT_RGBAH: { + + uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0]; + uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1]; + uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2]; + uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3]; + return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), Math::half_to_float(a)); + } break; + case FORMAT_RGBE9995: { + uint32_t rgbe = ((uint32_t *)ptr)[ofs]; + float r = rgbe & 0x1ff; + float g = (rgbe >> 9) & 0x1ff; + float b = (rgbe >> 18) & 0x1ff; + float e = (rgbe >> 27); + float m = Math::pow(2, e - 15.0 - 9.0); + ; + float rd = r * m; + float gd = g * m; + float bd = b * m; + + return Color(rd, gd, bd, 1.0); + + } break; + default: { + ERR_EXPLAIN("Can't get_pixel() on compressed image, sorry."); + ERR_FAIL_V(Color()); + } + } + + return Color(); +} + +void Image::put_pixel(int p_x, int p_y, const Color &p_color) { + + uint8_t *ptr = write_lock.ptr(); +#ifdef DEBUG_ENABLED + if (!ptr) { + ERR_EXPLAIN("Image must be locked with 'lock()' before using put_pixel()"); + ERR_FAIL_COND(!ptr); + } + + ERR_FAIL_INDEX(p_x, width); + ERR_FAIL_INDEX(p_y, height); + +#endif + + uint32_t ofs = p_y * width + p_x; + + switch (format) { + case FORMAT_L8: { + ptr[ofs] = uint8_t(CLAMP(p_color.gray() * 255.0, 0, 255)); + } break; + case FORMAT_LA8: { + ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.gray() * 255.0, 0, 255)); + ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255)); + } break; + case FORMAT_R8: { + + ptr[ofs] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255)); + } break; + case FORMAT_RG8: { + + ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255)); + ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255)); + } break; + case FORMAT_RGB8: { + ptr[ofs * 3 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255)); + ptr[ofs * 3 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255)); + ptr[ofs * 3 + 2] = uint8_t(CLAMP(p_color.b * 255.0, 0, 255)); + } break; + case FORMAT_RGBA8: { + ptr[ofs * 4 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255)); + ptr[ofs * 4 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255)); + ptr[ofs * 4 + 2] = uint8_t(CLAMP(p_color.b * 255.0, 0, 255)); + ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255)); + + } break; + case FORMAT_RGBA4444: { + + uint16_t rgba = 0; + + rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15)); + rgba |= uint16_t(CLAMP(p_color.g * 15.0, 0, 15)) << 4; + rgba |= uint16_t(CLAMP(p_color.b * 15.0, 0, 15)) << 8; + rgba |= uint16_t(CLAMP(p_color.a * 15.0, 0, 15)) << 12; + + ((uint16_t *)ptr)[ofs] = rgba; + + } break; + case FORMAT_RGBA5551: { + + uint16_t rgba = 0; + + rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)); + rgba |= uint16_t(CLAMP(p_color.g * 31.0, 0, 31)) << 5; + rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 10; + rgba |= uint16_t(p_color.a > 0.5 ? 1 : 0) << 15; + + ((uint16_t *)ptr)[ofs] = rgba; + + } break; + case FORMAT_RF: { + + ((float *)ptr)[ofs] = p_color.r; + } break; + case FORMAT_RGF: { + + ((float *)ptr)[ofs * 2 + 0] = p_color.r; + ((float *)ptr)[ofs * 2 + 1] = p_color.g; + } break; + case FORMAT_RGBF: { + + ((float *)ptr)[ofs * 3 + 0] = p_color.r; + ((float *)ptr)[ofs * 3 + 1] = p_color.g; + ((float *)ptr)[ofs * 3 + 2] = p_color.b; + } break; + case FORMAT_RGBAF: { + + ((float *)ptr)[ofs * 4 + 0] = p_color.r; + ((float *)ptr)[ofs * 4 + 1] = p_color.g; + ((float *)ptr)[ofs * 4 + 2] = p_color.b; + ((float *)ptr)[ofs * 4 + 3] = p_color.a; + } break; + case FORMAT_RH: { + + ((uint16_t *)ptr)[ofs] = Math::make_half_float(p_color.r); + } break; + case FORMAT_RGH: { + + ((uint16_t *)ptr)[ofs * 2 + 0] = Math::make_half_float(p_color.r); + ((uint16_t *)ptr)[ofs * 2 + 1] = Math::make_half_float(p_color.g); + } break; + case FORMAT_RGBH: { + + ((uint16_t *)ptr)[ofs * 3 + 0] = Math::make_half_float(p_color.r); + ((uint16_t *)ptr)[ofs * 3 + 1] = Math::make_half_float(p_color.g); + ((uint16_t *)ptr)[ofs * 3 + 2] = Math::make_half_float(p_color.b); + } break; + case FORMAT_RGBAH: { + + ((uint16_t *)ptr)[ofs * 4 + 0] = Math::make_half_float(p_color.r); + ((uint16_t *)ptr)[ofs * 4 + 1] = Math::make_half_float(p_color.g); + ((uint16_t *)ptr)[ofs * 4 + 2] = Math::make_half_float(p_color.b); + ((uint16_t *)ptr)[ofs * 4 + 3] = Math::make_half_float(p_color.a); + } break; + case FORMAT_RGBE9995: { + + ((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995(); + + } break; + default: { + ERR_EXPLAIN("Can't put_pixel() on compressed image, sorry."); + ERR_FAIL(); + } + } +} + +Image::DetectChannels Image::get_detected_channels() { + + ERR_FAIL_COND_V(data.size() == 0, DETECTED_RGBA); + ERR_FAIL_COND_V(is_compressed(), DETECTED_RGBA); + bool r = false, g = false, b = false, a = false, c = false; + lock(); + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + + Color col = get_pixel(i, j); + + if (col.r > 0.001) + r = true; + if (col.g > 0.001) + g = true; + if (col.b > 0.001) + b = true; + if (col.a < 0.999) + a = true; + + if (col.r != col.b || col.r != col.g || col.b != col.g) { + c = true; + } + } + } + + unlock(); + + if (!c && !a) + return DETECTED_L; + if (!c && a) + return DETECTED_LA; + + if (r && !g && !b && !a) + return DETECTED_R; + + if (r && g && !b && !a) + return DETECTED_RG; + + if (r && g && b && !a) + return DETECTED_RGB; + + return DETECTED_RGBA; +} + void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("get_width"), &Image::get_width); @@ -1677,6 +2081,11 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data", "data"), &Image::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &Image::_get_data); + ClassDB::bind_method(D_METHOD("lock"), &Image::lock); + ClassDB::bind_method(D_METHOD("unlock"), &Image::unlock); + ClassDB::bind_method(D_METHOD("put_pixel", "x", "y", "color"), &Image::put_pixel); + ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &Image::get_pixel); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data"); BIND_CONSTANT(FORMAT_L8); //luminance @@ -1685,7 +2094,6 @@ void Image::_bind_methods() { BIND_CONSTANT(FORMAT_RG8); BIND_CONSTANT(FORMAT_RGB8); BIND_CONSTANT(FORMAT_RGBA8); - BIND_CONSTANT(FORMAT_RGB565); //16 bit BIND_CONSTANT(FORMAT_RGBA4444); BIND_CONSTANT(FORMAT_RGBA5551); BIND_CONSTANT(FORMAT_RF); //float @@ -1696,11 +2104,12 @@ void Image::_bind_methods() { BIND_CONSTANT(FORMAT_RGH); BIND_CONSTANT(FORMAT_RGBH); BIND_CONSTANT(FORMAT_RGBAH); + BIND_CONSTANT(FORMAT_RGBE9995); BIND_CONSTANT(FORMAT_DXT1); //s3tc bc1 BIND_CONSTANT(FORMAT_DXT3); //bc2 BIND_CONSTANT(FORMAT_DXT5); //bc3 - BIND_CONSTANT(FORMAT_ATI1); //bc4 - BIND_CONSTANT(FORMAT_ATI2); //bc5 + BIND_CONSTANT(FORMAT_RGTC_R); + BIND_CONSTANT(FORMAT_RGTC_RG); BIND_CONSTANT(FORMAT_BPTC_RGBA); //btpc bc6h BIND_CONSTANT(FORMAT_BPTC_RGBF); //float / BIND_CONSTANT(FORMAT_BPTC_RGBFU); //unsigned float @@ -1726,7 +2135,6 @@ void Image::_bind_methods() { BIND_CONSTANT(ALPHA_BIT); BIND_CONSTANT(ALPHA_BLEND); - BIND_CONSTANT(COMPRESS_16BIT); BIND_CONSTANT(COMPRESS_S3TC); BIND_CONSTANT(COMPRESS_PVRTC2); BIND_CONSTANT(COMPRESS_PVRTC4); @@ -1734,7 +2142,7 @@ void Image::_bind_methods() { BIND_CONSTANT(COMPRESS_ETC2); } -void Image::set_compress_bc_func(void (*p_compress_func)(Image *)) { +void Image::set_compress_bc_func(void (*p_compress_func)(Image *, bool)) { _image_compress_bc_func = p_compress_func; } @@ -1924,4 +2332,8 @@ Image::Image() { } Image::~Image() { + + if (write_lock.ptr()) { + unlock(); + } } diff --git a/core/image.h b/core/image.h index 273e2d0ab7..2a78870f53 100644 --- a/core/image.h +++ b/core/image.h @@ -66,7 +66,6 @@ public: FORMAT_RG8, FORMAT_RGB8, FORMAT_RGBA8, - FORMAT_RGB565, //16 bit FORMAT_RGBA4444, FORMAT_RGBA5551, FORMAT_RF, //float @@ -77,14 +76,15 @@ public: FORMAT_RGH, FORMAT_RGBH, FORMAT_RGBAH, + FORMAT_RGBE9995, FORMAT_DXT1, //s3tc bc1 FORMAT_DXT3, //bc2 FORMAT_DXT5, //bc3 - FORMAT_ATI1, //bc4 - FORMAT_ATI2, //bc5 - FORMAT_BPTC_RGBA, //btpc bc6h - FORMAT_BPTC_RGBF, //float / - FORMAT_BPTC_RGBFU, //unsigned float + FORMAT_RGTC_R, + FORMAT_RGTC_RG, + FORMAT_BPTC_RGBA, //btpc bc7 + FORMAT_BPTC_RGBF, //float bc6h + FORMAT_BPTC_RGBFU, //unsigned float bc6hu FORMAT_PVRTC2, //pvrtc FORMAT_PVRTC2A, FORMAT_PVRTC4, @@ -114,7 +114,7 @@ public: static Ref<Image> (*_png_mem_loader_func)(const uint8_t *p_png, int p_size); static Ref<Image> (*_jpg_mem_loader_func)(const uint8_t *p_png, int p_size); - static void (*_image_compress_bc_func)(Image *); + static void (*_image_compress_bc_func)(Image *, bool p_srgb); static void (*_image_compress_pvrtc2_func)(Image *); static void (*_image_compress_pvrtc4_func)(Image *); static void (*_image_compress_etc_func)(Image *); @@ -125,13 +125,13 @@ public: static void (*_image_decompress_etc)(Image *); static void (*_image_decompress_etc2)(Image *); - Error _decompress_bc(); - static PoolVector<uint8_t> (*lossy_packer)(const Ref<Image> &p_image, float p_quality); static Ref<Image> (*lossy_unpacker)(const PoolVector<uint8_t> &p_buffer); static PoolVector<uint8_t> (*lossless_packer)(const Ref<Image> &p_image); static Ref<Image> (*lossless_unpacker)(const PoolVector<uint8_t> &p_buffer); + PoolVector<uint8_t>::Write write_lock; + protected: static void _bind_methods(); @@ -253,21 +253,21 @@ public: static int get_format_pixel_size(Format p_format); static int get_format_pixel_rshift(Format p_format); + static int get_format_block_size(Format p_format); static void get_format_min_pixel_size(Format p_format, int &r_w, int &r_h); static int get_image_data_size(int p_width, int p_height, Format p_format, int p_mipmaps = 0); static int get_image_required_mipmaps(int p_width, int p_height, Format p_format); enum CompressMode { - COMPRESS_16BIT, COMPRESS_S3TC, COMPRESS_PVRTC2, COMPRESS_PVRTC4, COMPRESS_ETC, - COMPRESS_ETC2 + COMPRESS_ETC2, }; - Error compress(CompressMode p_mode = COMPRESS_S3TC); + Error compress(CompressMode p_mode = COMPRESS_S3TC, bool p_for_srgb = false); Error decompress(); bool is_compressed() const; @@ -281,7 +281,7 @@ public: Rect2 get_used_rect() const; Ref<Image> get_rect(const Rect2 &p_area) const; - static void set_compress_bc_func(void (*p_compress_func)(Image *)); + static void set_compress_bc_func(void (*p_compress_func)(Image *, bool)); static String get_format_name(Format p_format); Image(const uint8_t *p_mem_png_jpg, int p_len = -1); @@ -289,6 +289,24 @@ public: virtual Ref<Resource> duplicate(bool p_subresources = false) const; + void lock(); + void unlock(); + + //this is used for compression + enum DetectChannels { + DETECTED_L, + DETECTED_LA, + DETECTED_R, + DETECTED_RG, + DETECTED_RGB, + DETECTED_RGBA, + }; + + DetectChannels get_detected_channels(); + + Color get_pixel(int p_x, int p_y); + void put_pixel(int p_x, int p_y, const Color &p_color); + void copy_internals_from(const Ref<Image> &p_image) { ERR_FAIL_COND(p_image.is_null()); format = p_image->format; diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 6ed20ac015..23719940be 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -43,7 +43,7 @@ bool ImageFormatLoader::recognize(const String &p_extension) const { return false; } -Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom) { +Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom, bool p_force_linear) { ERR_FAIL_COND_V(p_image.is_null(), ERR_INVALID_PARAMETER); FileAccess *f = p_custom; @@ -62,7 +62,7 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c if (!loader[i]->recognize(extension)) continue; - Error err = loader[i]->load_image(p_image, f); + Error err = loader[i]->load_image(p_image, f, p_force_linear); if (err != ERR_FILE_UNRECOGNIZED) { diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 7114cbf8ad..e528d1423b 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -56,7 +56,7 @@ class ImageFormatLoader { friend class ImageLoader; protected: - virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess) = 0; + virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear) = 0; virtual void get_recognized_extensions(List<String> *p_extensions) const = 0; bool recognize(const String &p_extension) const; @@ -75,7 +75,7 @@ class ImageLoader { protected: public: - static Error load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom = NULL); + static Error load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom = NULL, bool p_force_linear = false); static void get_recognized_extensions(List<String> *p_extensions); static bool recognize(const String &p_extension); diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 06ec77daae..ca960aabad 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -51,9 +51,7 @@ class Math { public: Math() {} // useless to instance - enum { - RANDOM_MAX = 4294967295L - }; + static const uint64_t RANDOM_MAX = 4294967295; static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); } static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); } @@ -278,6 +276,10 @@ public: return u.f32; } + static _ALWAYS_INLINE_ float half_to_float(const uint16_t h) { + return halfptr_to_float(&h); + } + static _ALWAYS_INLINE_ uint16_t make_half_float(float f) { union { diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h index bcbf2e4531..c6dbfc2a7a 100644 --- a/core/method_ptrcall.h +++ b/core/method_ptrcall.h @@ -115,7 +115,6 @@ MAKE_PTRARG(PoolVector2Array); MAKE_PTRARG(PoolVector3Array); MAKE_PTRARG(PoolColorArray); MAKE_PTRARG(Variant); -MAKE_PTRARG(PowerState); //this is for Object diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 375121c0cc..805b66b983 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -252,6 +252,27 @@ double FileAccess::get_double() const { return m.d; }; +String FileAccess::get_token() const { + + CharString token; + + CharType c = get_8(); + + while (!eof_reached()) { + + if (c <= ' ') { + if (!token.empty()) + break; + } else { + token.push_back(c); + } + c = get_8(); + } + + token.push_back(0); + return String::utf8(token.get_data()); +} + String FileAccess::get_line() const { CharString line; diff --git a/core/os/file_access.h b/core/os/file_access.h index da15ddc544..6d3e491167 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -106,6 +106,7 @@ public: virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes virtual String get_line() const; + virtual String get_token() const; virtual Vector<String> get_csv_line(String delim = ",") const; /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index cf3b8f74ec..f96e08f479 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -62,11 +62,11 @@ bool InputEvent::is_action(const StringName &p_action) const { bool InputEvent::is_action_pressed(const StringName &p_action) const { - return false; // InputMap::get_singleton()->event_is_action(Ref<InputEvent>(this),p_action); + return (is_pressed() && !is_echo() && is_action(p_action)); } bool InputEvent::is_action_released(const StringName &p_action) const { - return false; + return (!is_pressed() && is_action(p_action)); } bool InputEvent::is_echo() const { @@ -324,20 +324,20 @@ int InputEventMouse::get_button_mask() const { return button_mask; } -void InputEventMouse::set_pos(const Vector2 &p_pos) { +void InputEventMouse::set_position(const Vector2 &p_pos) { pos = p_pos; } -Vector2 InputEventMouse::get_pos() const { +Vector2 InputEventMouse::get_position() const { return pos; } -void InputEventMouse::set_global_pos(const Vector2 &p_global_pos) { +void InputEventMouse::set_global_position(const Vector2 &p_global_pos) { global_pos = p_global_pos; } -Vector2 InputEventMouse::get_global_pos() const { +Vector2 InputEventMouse::get_global_position() const { return global_pos; } @@ -347,15 +347,15 @@ void InputEventMouse::_bind_methods() { ClassDB::bind_method(D_METHOD("set_button_mask", "button_mask"), &InputEventMouse::set_button_mask); ClassDB::bind_method(D_METHOD("get_button_mask"), &InputEventMouse::get_button_mask); - ClassDB::bind_method(D_METHOD("set_pos", "pos"), &InputEventMouse::set_pos); - ClassDB::bind_method(D_METHOD("get_pos"), &InputEventMouse::get_pos); + ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventMouse::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &InputEventMouse::get_position); - ClassDB::bind_method(D_METHOD("set_global_pos", "global_pos"), &InputEventMouse::set_global_pos); - ClassDB::bind_method(D_METHOD("get_global_pos"), &InputEventMouse::get_global_pos); + ClassDB::bind_method(D_METHOD("set_global_position", "global_position"), &InputEventMouse::set_global_position); + ClassDB::bind_method(D_METHOD("get_global_position"), &InputEventMouse::get_global_position); ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask"), "set_button_mask", "get_button_mask"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pos"), "set_pos", "get_pos"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_pos"), "set_global_pos", "get_global_pos"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position"), "set_global_position", "get_global_position"); } InputEventMouse::InputEventMouse() { @@ -404,8 +404,8 @@ bool InputEventMouseButton::is_doubleclick() const { Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Vector2 g = p_xform.xform(get_global_pos()); - Vector2 l = p_xform.xform(get_pos() + p_local_ofs); + Vector2 g = p_xform.xform(get_global_position()); + Vector2 l = p_xform.xform(get_position() + p_local_ofs); Ref<InputEventMouseButton> mb; mb.instance(); @@ -418,8 +418,8 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co mb->set_control(get_control()); mb->set_metakey(get_metakey()); - mb->set_pos(l); - mb->set_global_pos(g); + mb->set_position(l); + mb->set_global_position(g); mb->set_button_mask(get_button_mask()); mb->set_pressed(pressed); @@ -489,8 +489,8 @@ Vector2 InputEventMouseMotion::get_speed() const { Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Vector2 g = p_xform.xform(get_global_pos()); - Vector2 l = p_xform.xform(get_pos() + p_local_ofs); + Vector2 g = p_xform.xform(get_global_position()); + Vector2 l = p_xform.xform(get_position() + p_local_ofs); Vector2 r = p_xform.basis_xform(get_relative()); Vector2 s = p_xform.basis_xform(get_speed()); @@ -505,8 +505,8 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co mm->set_control(get_control()); mm->set_metakey(get_metakey()); - mm->set_pos(l); - mm->set_global_pos(g); + mm->set_position(l); + mm->set_global_position(g); mm->set_button_mask(get_button_mask()); mm->set_relative(r); @@ -650,11 +650,11 @@ int InputEventScreenTouch::get_index() const { return index; } -void InputEventScreenTouch::set_pos(const Vector2 &p_pos) { +void InputEventScreenTouch::set_position(const Vector2 &p_pos) { pos = p_pos; } -Vector2 InputEventScreenTouch::get_pos() const { +Vector2 InputEventScreenTouch::get_position() const { return pos; } @@ -675,7 +675,7 @@ Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, co st->set_id(get_id()); st->set_device(get_device()); st->set_index(index); - st->set_pos(p_xform.xform(pos + p_local_ofs)); + st->set_position(p_xform.xform(pos + p_local_ofs)); st->set_pressed(pressed); return st; @@ -686,14 +686,14 @@ void InputEventScreenTouch::_bind_methods() { ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenTouch::set_index); ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenTouch::get_index); - ClassDB::bind_method(D_METHOD("set_pos", "pos"), &InputEventScreenTouch::set_pos); - ClassDB::bind_method(D_METHOD("get_pos"), &InputEventScreenTouch::get_pos); + ClassDB::bind_method(D_METHOD("set_position", "pos"), &InputEventScreenTouch::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &InputEventScreenTouch::get_position); ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventScreenTouch::set_pressed); //ClassDB::bind_method(D_METHOD("is_pressed"),&InputEventScreenTouch::is_pressed); ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pos"), "set_pos", "get_pos"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); } @@ -715,11 +715,11 @@ int InputEventScreenDrag::get_index() const { return index; } -void InputEventScreenDrag::set_pos(const Vector2 &p_pos) { +void InputEventScreenDrag::set_position(const Vector2 &p_pos) { pos = p_pos; } -Vector2 InputEventScreenDrag::get_pos() const { +Vector2 InputEventScreenDrag::get_position() const { return pos; } @@ -752,7 +752,7 @@ Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, con sd->set_device(get_device()); sd->set_index(index); - sd->set_pos(p_xform.xform(pos + p_local_ofs)); + sd->set_position(p_xform.xform(pos + p_local_ofs)); sd->set_relative(p_xform.basis_xform(relative)); sd->set_speed(p_xform.basis_xform(speed)); @@ -764,8 +764,8 @@ void InputEventScreenDrag::_bind_methods() { ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenDrag::set_index); ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenDrag::get_index); - ClassDB::bind_method(D_METHOD("set_pos", "pos"), &InputEventScreenDrag::set_pos); - ClassDB::bind_method(D_METHOD("get_pos"), &InputEventScreenDrag::get_pos); + ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventScreenDrag::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &InputEventScreenDrag::get_position); ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventScreenDrag::set_relative); ClassDB::bind_method(D_METHOD("get_relative"), &InputEventScreenDrag::get_relative); @@ -774,7 +774,7 @@ void InputEventScreenDrag::_bind_methods() { ClassDB::bind_method(D_METHOD("get_speed"), &InputEventScreenDrag::get_speed); ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pos"), "set_pos", "get_pos"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed"); } diff --git a/core/os/input_event.h b/core/os/input_event.h index 31f88b295b..6a694df345 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -265,11 +265,11 @@ public: void set_button_mask(int p_mask); int get_button_mask() const; - void set_pos(const Vector2 &p_pos); - Vector2 get_pos() const; + void set_position(const Vector2 &p_pos); + Vector2 get_position() const; - void set_global_pos(const Vector2 &p_global_pos); - Vector2 get_global_pos() const; + void set_global_position(const Vector2 &p_global_pos); + Vector2 get_global_position() const; InputEventMouse(); }; @@ -390,8 +390,8 @@ public: void set_index(int p_index); int get_index() const; - void set_pos(const Vector2 &p_pos); - Vector2 get_pos() const; + void set_position(const Vector2 &p_pos); + Vector2 get_position() const; void set_pressed(bool p_pressed); virtual bool is_pressed() const; @@ -416,8 +416,8 @@ public: void set_index(int p_index); int get_index() const; - void set_pos(const Vector2 &p_pos); - Vector2 get_pos() const; + void set_position(const Vector2 &p_pos); + Vector2 get_position() const; void set_relative(const Vector2 &p_relative); Vector2 get_relative() const; diff --git a/core/os/os.h b/core/os/os.h index 037ce436c1..11fe8b44e3 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -413,4 +413,6 @@ public: virtual ~OS(); }; +VARIANT_ENUM_CAST(PowerState); + #endif diff --git a/core/ustring.cpp b/core/ustring.cpp index 7a5129962b..6a93d7789e 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -489,6 +489,18 @@ signed char String::naturalnocasecmp_to(const String &p_str) const { const CharType *that_str = p_str.c_str(); if (this_str && that_str) { + + while (*this_str == '.' || *that_str == '.') { + if (*this_str++ != '.') + return 1; + if (*that_str++ != '.') + return -1; + if (!*that_str) + return 1; + if (!*this_str) + return -1; + } + while (*this_str) { if (!*that_str) diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 0d4d0429e7..55e2bb42e3 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -695,6 +695,106 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } return OK; + } else if (id == "Object") { + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_PARENTHESIS_OPEN) { + r_err_str = "Expected '('"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream, token, line, r_err_str); + + if (token.type != TK_IDENTIFIER) { + r_err_str = "Expected identifier with type of object"; + return ERR_PARSE_ERROR; + } + + String type = token.value; + + Object *obj = ClassDB::instance(type); + + if (!obj) { + r_err_str = "Can't instance Object() of type: " + type; + return ERR_PARSE_ERROR; + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_COMMA) { + r_err_str = "Expected ',' after object type"; + return ERR_PARSE_ERROR; + } + + bool at_key = true; + String key; + Token token; + bool need_comma = false; + + while (true) { + + if (p_stream->is_eof()) { + r_err_str = "Unexpected End of File while parsing Object()"; + return ERR_FILE_CORRUPT; + } + + if (at_key) { + + Error err = get_token(p_stream, token, line, r_err_str); + if (err != OK) + return err; + + if (token.type == TK_PARENTHESIS_CLOSE) { + + return OK; + } + + if (need_comma) { + + if (token.type != TK_COMMA) { + + r_err_str = "Expected '}' or ','"; + return ERR_PARSE_ERROR; + } else { + need_comma = false; + continue; + } + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_STRING) { + r_err_str = "Expected property name as string"; + return ERR_PARSE_ERROR; + } + + key = token.value; + + err = get_token(p_stream, token, line, r_err_str); + + if (err != OK) + return err; + if (token.type != TK_COLON) { + + r_err_str = "Expected ':'"; + return ERR_PARSE_ERROR; + } + at_key = false; + } else { + + Error err = get_token(p_stream, token, line, r_err_str); + if (err != OK) + return err; + + Variant v; + err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); + if (err) + return err; + obj->set(key, v); + need_comma = true; + at_key = true; + } + } + + return OK; } else if (id == "Resource" || id == "SubResource" || id == "ExtResource") { @@ -1611,30 +1711,63 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str case Variant::OBJECT: { - RES res = p_variant; - if (res.is_null()) { + Object *obj = p_variant; + + if (!obj) { p_store_string_func(p_store_string_ud, "null"); break; // don't save it } - String res_text; + RES res = p_variant; + if (res.is_valid()) { + //is resource + String res_text; - if (p_encode_res_func) { + //try external function + if (p_encode_res_func) { - res_text = p_encode_res_func(p_encode_res_ud, res); - } + res_text = p_encode_res_func(p_encode_res_ud, res); + } + + //try path because it's a file + if (res_text == String() && res->get_path().is_resource_file()) { - if (res_text == String() && res->get_path().is_resource_file()) { + //external resource + String path = res->get_path(); + res_text = "Resource( \"" + path + "\")"; + } - //external resource - String path = res->get_path(); - res_text = "Resource( \"" + path + "\")"; + //could come up with some sort of text + if (res_text != String()) { + p_store_string_func(p_store_string_ud, res_text); + break; + } } - if (res_text == String()) - res_text = "null"; + //store as generic object + + p_store_string_func(p_store_string_ud, "Object(" + obj->get_class() + ","); + + List<PropertyInfo> props; + obj->get_property_list(&props); + bool first = true; + for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { + + if (E->get().usage & PROPERTY_USAGE_STORAGE || E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE) { + //must be serialized + + if (first) { + first = false; + } else { + p_store_string_func(p_store_string_ud, ","); + } + + p_store_string_func(p_store_string_ud, "\"" + E->get().name + "\":"); + write(obj->get(E->get().name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud); + } + } - p_store_string_func(p_store_string_ud, res_text); + p_store_string_func(p_store_string_ud, ")\n"); } break; |