diff options
85 files changed, 911 insertions, 357 deletions
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 4513c66ab5..1ce50bc186 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -234,6 +234,8 @@ typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtension typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name); typedef struct { + GDNativeBool is_virtual; + GDNativeBool is_abstract; GDNativeExtensionClassSet set_func; GDNativeExtensionClassGet get_func; GDNativeExtensionClassGetPropertyList get_property_list_func; diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index 6418da2235..cc019584a5 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -152,6 +152,8 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr extension->native_extension.parent_class_name = parent_class_name; extension->native_extension.class_name = class_name; extension->native_extension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR; + extension->native_extension.is_virtual = p_extension_funcs->is_virtual; + extension->native_extension.is_abstract = p_extension_funcs->is_abstract; extension->native_extension.set = p_extension_funcs->set_func; extension->native_extension.get = p_extension_funcs->get_func; extension->native_extension.get_property_list = p_extension_funcs->get_property_list_func; diff --git a/core/io/image.cpp b/core/io/image.cpp index 4be624a5a8..3450eb7abd 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -982,7 +982,7 @@ void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) { } void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { - ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use create() or create_from_data() first."); + ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use set_data() first."); ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats."); bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */; @@ -1017,7 +1017,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { } bool interpolate_mipmaps = mipmap_aware && mip1 != mip2; if (interpolate_mipmaps) { - dst2.create(p_width, p_height, false, format); + dst2.initialize_data(p_width, p_height, false, format); } bool had_mipmaps = mipmaps; @@ -2016,9 +2016,7 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con uint8_t* wr = imgdata.ptrw(); memcpy(wr.ptr(), ptr, size); wr = uint8_t*(); - Ref<Image> im; - im.instantiate(); - im->create(w, h, false, format, imgdata); + Ref<Image> im = Image::create_from_data(w, h, false, format, imgdata); im->save_png("res://mipmap_" + itos(i) + ".png"); } #endif @@ -2051,7 +2049,25 @@ Vector<uint8_t> Image::get_data() const { return data; } -void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { +Ref<Image> Image::create_empty(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { + Ref<Image> image; + image.instantiate(); + image->initialize_data(p_width, p_height, p_use_mipmaps, p_format); + return image; +} + +Ref<Image> Image::create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { + Ref<Image> image; + image.instantiate(); + image->initialize_data(p_width, p_height, p_use_mipmaps, p_format, p_data); + return image; +} + +void Image::set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { + initialize_data(p_width, p_height, p_use_mipmaps, p_format, p_data); +} + +void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels."); ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels."); ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, @@ -2077,7 +2093,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma format = p_format; } -void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { +void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels."); ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels."); ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, @@ -2115,7 +2131,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma mipmaps = p_use_mipmaps; } -void Image::create(const char **p_xpm) { +void Image::initialize_data(const char **p_xpm) { int size_width = 0; int size_height = 0; int pixelchars = 0; @@ -2230,7 +2246,7 @@ void Image::create(const char **p_xpm) { } if (line == colormap_size) { status = READING_PIXELS; - create(size_width, size_height, false, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8); + initialize_data(size_width, size_height, false, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8); data_write = data.ptrw(); pixel_size = has_alpha ? 4 : 3; } @@ -2559,7 +2575,7 @@ Image::Image(const char **p_xpm) { mipmaps = false; format = FORMAT_L8; - create(p_xpm); + initialize_data(p_xpm); } Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { @@ -2568,7 +2584,7 @@ Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { mipmaps = p_use_mipmaps; format = FORMAT_L8; - create(p_width, p_height, p_use_mipmaps, p_format); + initialize_data(p_width, p_height, p_use_mipmaps, p_format); } Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { @@ -2577,7 +2593,7 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const V mipmaps = p_mipmaps; format = FORMAT_L8; - create(p_width, p_height, p_mipmaps, p_format, p_data); + initialize_data(p_width, p_height, p_mipmaps, p_format, p_data); } Rect2i Image::get_used_rect() const { @@ -2931,7 +2947,7 @@ void Image::_set_data(const Dictionary &p_data) { ERR_FAIL_COND(ddformat == FORMAT_MAX); - create(dwidth, dheight, dmipmaps, ddformat, ddata); + initialize_data(dwidth, dheight, dmipmaps, ddformat, ddata); } Dictionary Image::_get_data() const { @@ -3294,8 +3310,9 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_mipmaps", "renormalize"), &Image::generate_mipmaps, DEFVAL(false)); ClassDB::bind_method(D_METHOD("clear_mipmaps"), &Image::clear_mipmaps); - ClassDB::bind_method(D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::create_empty); - ClassDB::bind_method(D_METHOD("create_from_data", "width", "height", "use_mipmaps", "format", "data"), &Image::create_from_data); + ClassDB::bind_static_method("Image", D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::create_empty); + ClassDB::bind_static_method("Image", D_METHOD("create_from_data", "width", "height", "use_mipmaps", "format", "data"), &Image::create_from_data); + ClassDB::bind_method(D_METHOD("set_data", "width", "height", "use_mipmaps", "format", "data"), &Image::set_data); ClassDB::bind_method(D_METHOD("is_empty"), &Image::is_empty); @@ -3460,9 +3477,7 @@ Ref<Image> Image::rgbe_to_srgb() { ERR_FAIL_COND_V(format != FORMAT_RGBE9995, Ref<Image>()); - Ref<Image> new_image; - new_image.instantiate(); - new_image->create(width, height, false, Image::FORMAT_RGB8); + Ref<Image> new_image = create_empty(width, height, false, Image::FORMAT_RGB8); for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { diff --git a/core/io/image.h b/core/io/image.h index fd264a7a38..194ee05bc7 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -279,12 +279,12 @@ public: void normalize(); //for normal maps /** - * Create a new image of a given size and format. Current image will be lost + * Creates new internal image data of a given size and format. Current image will be lost. */ - void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format); - void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); + void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format); + void initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); + void initialize_data(const char **p_xpm); - void create(const char **p_xpm); /** * returns true when the image is empty (0,0) in size */ @@ -303,13 +303,9 @@ public: Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const; Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const; - void create_empty(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { - create(p_width, p_height, p_use_mipmaps, p_format); - } - - void create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { - create(p_width, p_height, p_use_mipmaps, p_format, p_data); - } + static Ref<Image> create_empty(int p_width, int p_height, bool p_use_mipmaps, Format p_format); + static Ref<Image> create_from_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); + void set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data); /** * create an empty image diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp index e573e8de19..200e5f5e83 100644 --- a/core/io/zip_io.cpp +++ b/core/io/zip_io.cpp @@ -37,11 +37,17 @@ void *zipio_open(voidpf opaque, const char *p_fname, int mode) { String fname; fname.parse_utf8(p_fname); + int file_access_mode = 0; if (mode & ZLIB_FILEFUNC_MODE_WRITE) { - (*fa) = FileAccess::open(fname, FileAccess::WRITE); - } else { - (*fa) = FileAccess::open(fname, FileAccess::READ); + file_access_mode |= FileAccess::WRITE; } + if (mode & ZLIB_FILEFUNC_MODE_READ) { + file_access_mode |= FileAccess::READ; + } + if (mode & ZLIB_FILEFUNC_MODE_CREATE) { + file_access_mode |= FileAccess::WRITE_READ; + } + (*fa) = FileAccess::open(fname, file_access_mode); if (fa->is_null()) { return nullptr; diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index ca56add2ab..41585943b3 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -1528,7 +1528,10 @@ void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) { c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION; c.native_extension = p_extension; c.name = p_extension->class_name; - c.creation_func = parent->creation_func; + c.is_virtual = p_extension->is_virtual; + if (!p_extension->is_abstract) { + c.creation_func = parent->creation_func; + } c.inherits = parent->name; c.class_ptr = parent->class_ptr; c.inherits_ptr = parent; diff --git a/core/object/object.h b/core/object/object.h index 5ba5453b31..359ab0f211 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -295,6 +295,8 @@ struct ObjectNativeExtension { StringName parent_class_name; StringName class_name; bool editor_class = false; + bool is_virtual = false; + bool is_abstract = false; GDNativeExtensionClassSet set; GDNativeExtensionClassGet get; GDNativeExtensionClassGetPropertyList get_property_list; diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 510f14ec54..eb5b3dad91 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -111,8 +111,8 @@ Copies [param src] image to this image. </description> </method> - <method name="create"> - <return type="void" /> + <method name="create" qualifiers="static"> + <return type="Image" /> <param index="0" name="width" type="int" /> <param index="1" name="height" type="int" /> <param index="2" name="use_mipmaps" type="bool" /> @@ -121,8 +121,8 @@ Creates an empty image of given size and format. See [enum Format] constants. If [param use_mipmaps] is [code]true[/code] then generate mipmaps for this image. See the [method generate_mipmaps]. </description> </method> - <method name="create_from_data"> - <return type="void" /> + <method name="create_from_data" qualifiers="static"> + <return type="Image" /> <param index="0" name="width" type="int" /> <param index="1" name="height" type="int" /> <param index="2" name="use_mipmaps" type="bool" /> @@ -454,6 +454,17 @@ Saves the image as a WebP (Web Picture) file to a byte array. By default it will save lossless. If [param lossy] is true, the image will be saved lossy, using the [param quality] setting between 0.0 and 1.0 (inclusive). </description> </method> + <method name="set_data"> + <return type="void" /> + <param index="0" name="width" type="int" /> + <param index="1" name="height" type="int" /> + <param index="2" name="use_mipmaps" type="bool" /> + <param index="3" name="format" type="int" enum="Image.Format" /> + <param index="4" name="data" type="PackedByteArray" /> + <description> + Overwrites data of an existing [Image]. Non-static equivalent of [method create_from_data]. + </description> + </method> <method name="set_pixel"> <return type="void" /> <param index="0" name="x" type="int" /> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index bceb285584..620895d8d8 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -529,9 +529,9 @@ <method name="move_child"> <return type="void" /> <param index="0" name="child_node" type="Node" /> - <param index="1" name="to_position" type="int" /> + <param index="1" name="to_index" type="int" /> <description> - Moves a child node to a different position (order) among the other children. Since calls, signals, etc are performed by tree order, changing the order of children nodes may be useful. If [param to_position] is negative, the index will be counted from the end. + Moves a child node to a different index (order) among the other children. Since calls, signals, etc. are performed by tree order, changing the order of children nodes may be useful. If [param to_index] is negative, the index will be counted from the end. [b]Note:[/b] Internal children can only be moved within their expected "internal range" (see [code]internal[/code] parameter in [method add_child]). </description> </method> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 4b2bb3b6e9..ff66affeab 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -413,6 +413,9 @@ <member name="debug/gdscript/warnings/standalone_ternary" type="int" setter="" getter="" default="1"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a ternary expression that has no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement. </member> + <member name="debug/gdscript/warnings/static_called_on_instance" type="int" setter="" getter="" default="1"> + When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a static method from an instance of a class instead of from the class directly. + </member> <member name="debug/gdscript/warnings/treat_warnings_as_errors" type="bool" setter="" getter="" default="false"> If [code]true[/code], all warnings will be reported as if they are errors. </member> diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 65bb98d29e..b407670098 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -130,7 +130,10 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ if (syncStatus == GL_UNSIGNALED) { // If older than 2 frames, wait for sync OpenGL can have up to 3 frames in flight, any more and we need to sync anyway. if (state.canvas_instance_data_buffers[state.current_buffer].last_frame_used < RSG::rasterizer->get_frame_number() - 2) { +#ifndef WEB_ENABLED + // On web, we do nothing as the glSubBufferData will force a sync anyway and WebGL does not like waiting. glClientWaitSync(state.canvas_instance_data_buffers[state.current_buffer].fence, 0, 100000000); // wait for up to 100ms +#endif } else { // Used in last frame or frame before that. OpenGL can get up to two frames behind, so these buffers may still be in use // Allocate a new buffer and use that. @@ -1010,7 +1013,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Tran _add_to_batch(r_index, r_batch_broken); if (primitive->point_count == 4) { - // Reset base data + // Reset base data. _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world); state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0; state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0; @@ -1018,12 +1021,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Tran state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config for (uint32_t j = 0; j < 3; j++) { - //second half of triangle - state.instance_data_array[r_index].points[j * 2 + 0] = primitive->points[j + 1].x; - state.instance_data_array[r_index].points[j * 2 + 1] = primitive->points[j + 1].y; - state.instance_data_array[r_index].uvs[j * 2 + 0] = primitive->uvs[j + 1].x; - state.instance_data_array[r_index].uvs[j * 2 + 1] = primitive->uvs[j + 1].y; - Color col = primitive->colors[j + 1] * base_color; + int offset = j == 0 ? 0 : 1; + // Second triangle in the quad. Uses vertices 0, 2, 3. + state.instance_data_array[r_index].points[j * 2 + 0] = primitive->points[j + offset].x; + state.instance_data_array[r_index].points[j * 2 + 1] = primitive->points[j + offset].y; + state.instance_data_array[r_index].uvs[j * 2 + 0] = primitive->uvs[j + offset].x; + state.instance_data_array[r_index].uvs[j * 2 + 1] = primitive->uvs[j + offset].y; + Color col = primitive->colors[j + offset] * base_color; state.instance_data_array[r_index].colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r); state.instance_data_array[r_index].colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b); } diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 22a11cdc29..23db41802e 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -211,7 +211,9 @@ void main() { #include "canvas_uniforms_inc.glsl" #include "stdlib_inc.glsl" +#ifndef DISABLE_LIGHTING uniform sampler2D atlas_texture; //texunit:-2 +#endif // DISABLE_LIGHTING //uniform sampler2D shadow_atlas_texture; //texunit:-3 uniform sampler2D screen_texture; //texunit:-4 uniform sampler2D sdf_texture; //texunit:-5 diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl index 43d275205f..dd5ebecb1a 100644 --- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl +++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl @@ -82,6 +82,7 @@ layout(std140) uniform CanvasData { //ubo:0 uint pad2; }; +#ifndef DISABLE_LIGHTING #define LIGHT_FLAGS_BLEND_MASK uint(3 << 16) #define LIGHT_FLAGS_BLEND_MODE_ADD uint(0 << 16) #define LIGHT_FLAGS_BLEND_MODE_SUB uint(1 << 16) @@ -114,7 +115,7 @@ struct Light { layout(std140) uniform LightData { //ubo:2 Light light_array[MAX_LIGHTS]; }; - +#endif // DISABLE_LIGHTING layout(std140) uniform DrawDataInstances { //ubo:3 DrawData draw_data[MAX_DRAW_DATA_INSTANCES]; diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 48f460f995..554b4165fa 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -59,9 +59,7 @@ TextureStorage::TextureStorage() { { //create default textures { // White Textures - Ref<Image> image; - image.instantiate(); - image->create(4, 4, true, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(1, 1, 1, 1)); image->generate_mipmaps(); @@ -90,9 +88,7 @@ TextureStorage::TextureStorage() { } { // black - Ref<Image> image; - image.instantiate(); - image->create(4, 4, true, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(0, 0, 0, 1)); image->generate_mipmaps(); @@ -116,9 +112,7 @@ TextureStorage::TextureStorage() { } { // transparent black - Ref<Image> image; - image.instantiate(); - image->create(4, 4, true, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(0, 0, 0, 0)); image->generate_mipmaps(); @@ -127,9 +121,7 @@ TextureStorage::TextureStorage() { } { - Ref<Image> image; - image.instantiate(); - image->create(4, 4, true, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(0.5, 0.5, 1, 1)); image->generate_mipmaps(); @@ -138,9 +130,7 @@ TextureStorage::TextureStorage() { } { - Ref<Image> image; - image.instantiate(); - image->create(4, 4, true, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, true, Image::FORMAT_RGBA8); image->fill(Color(1.0, 0.5, 1, 1)); image->generate_mipmaps(); @@ -745,9 +735,7 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { //this could be better optimized to reuse an existing image , done this way //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); image->fill(Color(1, 0, 1, 1)); texture_2d_initialize(p_texture, image); @@ -756,9 +744,7 @@ void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) { //this could be better optimized to reuse an existing image , done this way //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); image->fill(Color(1, 0, 1, 1)); Vector<Ref<Image>> images; @@ -777,9 +763,7 @@ void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, Re void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { //this could be better optimized to reuse an existing image , done this way //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); image->fill(Color(1, 0, 1, 1)); Vector<Ref<Image>> images; @@ -833,9 +817,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { data.resize(data_size); ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(texture->width, texture->height, texture->mipmaps > 1, texture->real_format, data); + Ref<Image> image = Image::create_from_data(texture->width, texture->height, texture->mipmaps > 1, texture->real_format, data); ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); if (texture->format != texture->real_format) { image->convert(texture->format); diff --git a/drivers/png/png_driver_common.cpp b/drivers/png/png_driver_common.cpp index bc4bb3782b..79641464d8 100644 --- a/drivers/png/png_driver_common.cpp +++ b/drivers/png/png_driver_common.cpp @@ -119,7 +119,7 @@ Error png_to_image(const uint8_t *p_source, size_t p_size, bool p_force_linear, ERR_FAIL_COND_V(!success, ERR_FILE_CORRUPT); //print_line("png width: "+itos(png_img.width)+" height: "+itos(png_img.height)); - p_image->create(png_img.width, png_img.height, false, dest_format, buffer); + p_image->set_data(png_img.width, png_img.height, false, dest_format, buffer); return OK; } diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index a882275375..dfa2b8e70f 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -308,9 +308,7 @@ void EditorProfiler::_update_plot() { } } - Ref<Image> img; - img.instantiate(); - img->create(w, h, false, Image::FORMAT_RGBA8, graph_image); + Ref<Image> img = Image::create_from_data(w, h, false, Image::FORMAT_RGBA8, graph_image); if (reset_texture) { if (graph_texture.is_null()) { diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index 8e7135f1c5..8552c8e9ef 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -298,9 +298,7 @@ void EditorVisualProfiler::_update_plot() { } } - Ref<Image> img; - img.instantiate(); - img->create(w, h, false, Image::FORMAT_RGBA8, graph_image); + Ref<Image> img = Image::create_from_data(w, h, false, Image::FORMAT_RGBA8, graph_image); if (reset_texture) { if (graph_texture.is_null()) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bf50efc4f9..8ee82888f3 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1618,7 +1618,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { // which would result in an invalid texture. if (c3d == 0 && c2d == 0) { img.instantiate(); - img->create(1, 1, false, Image::FORMAT_RGB8); + img->initialize_data(1, 1, false, Image::FORMAT_RGB8); } else if (c3d < c2d) { Ref<ViewportTexture> viewport_texture = scene_root->get_texture(); if (viewport_texture->get_width() > 0 && viewport_texture->get_height() > 0) { diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 332e47dc52..899fa69be1 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -90,7 +90,9 @@ void EditorPropertyText::update_property() { String s = get_edited_object()->get(get_edited_property()); updating = true; if (text->get_text() != s) { + int caret = text->get_caret_column(); text->set_text(s); + text->set_caret_column(caret); } text->set_editable(!is_read_only()); updating = false; diff --git a/editor/event_listener_line_edit.cpp b/editor/event_listener_line_edit.cpp index 14e482432a..e4c35a5b81 100644 --- a/editor/event_listener_line_edit.cpp +++ b/editor/event_listener_line_edit.cpp @@ -59,8 +59,9 @@ void EventListenerLineEdit::gui_input(const Ref<InputEvent> &p_event) { // First event will be an event which is used to focus this control - i.e. a mouse click, or a tab press. // Ignore the first one so that clicking into the LineEdit does not override the current event. // Ignore is reset to true when the control is unfocused. - if (ignore) { - ignore = false; + // This class also specially handles grab_focus() calls. + if (ignore_next_event) { + ignore_next_event = false; return; } @@ -85,7 +86,7 @@ void EventListenerLineEdit::_on_focus() { } void EventListenerLineEdit::_on_unfocus() { - ignore = true; + ignore_next_event = true; set_placeholder(TTR("Filter by event...")); } @@ -109,6 +110,12 @@ int EventListenerLineEdit::get_allowed_input_types() const { return allowed_input_types; } +void EventListenerLineEdit::grab_focus() { + // If we grab focus through code, we don't need to ignore the first event! + ignore_next_event = false; + Control::grab_focus(); +} + void EventListenerLineEdit::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { diff --git a/editor/event_listener_line_edit.h b/editor/event_listener_line_edit.h index 5b415e8a2d..c4cd5e4511 100644 --- a/editor/event_listener_line_edit.h +++ b/editor/event_listener_line_edit.h @@ -44,7 +44,7 @@ class EventListenerLineEdit : public LineEdit { GDCLASS(EventListenerLineEdit, LineEdit) int allowed_input_types = INPUT_KEY | INPUT_MOUSE_BUTTON | INPUT_JOY_BUTTON | INPUT_JOY_MOTION; - bool ignore = true; + bool ignore_next_event = true; bool share_keycodes = false; Ref<InputEvent> event; @@ -67,6 +67,8 @@ public: void set_allowed_input_types(int input_types); int get_allowed_input_types() const; + void grab_focus(); + public: EventListenerLineEdit(); }; diff --git a/editor/icons/Line.svg b/editor/icons/Line.svg new file mode 100644 index 0000000000..c7b1f8a701 --- /dev/null +++ b/editor/icons/Line.svg @@ -0,0 +1 @@ +<svg height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="m2 1050.4 8-8" fill="none" stroke="#ffffff" stroke-linecap="round" stroke-width="2" transform="translate(0 -1040.4)"/></svg> diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index 9dafa47c1c..e1df78e741 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -186,9 +186,7 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons int mm_d = MAX(1, d >> 1); for (int i = 0; i < mm_d; i++) { - Ref<Image> mm; - mm.instantiate(); - mm->create(mm_w, mm_h, false, p_images[0]->get_format()); + Ref<Image> mm = Image::create_empty(mm_w, mm_h, false, p_images[0]->get_format()); Vector3 pos; pos.z = float(i) * float(d) / float(mm_d) + 0.5; for (int x = 0; x < mm_w; x++) { diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index 9171f04f42..bf22a9377e 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -273,9 +273,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file EditorAtlasPacker::chart_pack(charts, atlas_width, atlas_height); //blit the atlas - Ref<Image> new_atlas; - new_atlas.instantiate(); - new_atlas->create(atlas_width, atlas_height, false, Image::FORMAT_RGBA8); + Ref<Image> new_atlas = Image::create_empty(atlas_width, atlas_height, false, Image::FORMAT_RGBA8); for (int i = 0; i < pack_data_files.size(); i++) { PackData &pack_data = pack_data_files.write[i]; diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp index ed9a5898fb..c577c61db7 100644 --- a/editor/input_event_configuration_dialog.cpp +++ b/editor/input_event_configuration_dialog.cpp @@ -533,6 +533,10 @@ String InputEventConfigurationDialog::_get_device_string(int p_device) const { void InputEventConfigurationDialog::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + event_listener->grab_focus(); + } break; + case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { input_list_search->set_right_icon(input_list_search->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index a48990779b..b4737976d8 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -128,14 +128,11 @@ void AnimationPlayerEditor::_notification(int p_what) { { Ref<Image> autoplay_img = autoplay_icon->get_image(); Ref<Image> reset_img = reset_icon->get_image(); - Ref<Image> autoplay_reset_img; Size2 icon_size = autoplay_img->get_size(); - autoplay_reset_img.instantiate(); - autoplay_reset_img->create(icon_size.x * 2, icon_size.y, false, autoplay_img->get_format()); + Ref<Image> autoplay_reset_img = Image::create_empty(icon_size.x * 2, icon_size.y, false, autoplay_img->get_format()); autoplay_reset_img->blit_rect(autoplay_img, Rect2i(Point2i(), icon_size), Point2i()); autoplay_reset_img->blit_rect(reset_img, Rect2i(Point2i(), icon_size), Point2i(icon_size.x, 0)); - autoplay_reset_icon.instantiate(); - autoplay_reset_icon->set_image(autoplay_reset_img); + autoplay_reset_icon = ImageTexture::create_from_image(autoplay_reset_img); } stop->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 8d1df0b32c..434e6a92e3 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -805,7 +805,7 @@ Ref<Texture2D> CurvePreviewGenerator::generate(const Ref<Resource> &p_from, cons img_ref.instantiate(); Image &im = **img_ref; - im.create(thumbnail_size, thumbnail_size / 2, false, Image::FORMAT_RGBA8); + im.initialize_data(thumbnail_size, thumbnail_size / 2, false, Image::FORMAT_RGBA8); Color bg_color(0.1, 0.1, 0.1, 1.0); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 59b8f31720..836f76ac4f 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -210,9 +210,7 @@ Ref<Texture2D> EditorBitmapPreviewPlugin::generate(const Ref<Resource> &p_from, } } - Ref<Image> img; - img.instantiate(); - img->create(bm->get_size().width, bm->get_size().height, false, Image::FORMAT_L8, data); + Ref<Image> img = Image::create_from_data(bm->get_size().width, bm->get_size().height, false, Image::FORMAT_L8, data); if (img->is_compressed()) { if (img->decompress() != OK) { @@ -483,10 +481,8 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from, int line = 0; int col = 0; - Ref<Image> img; - img.instantiate(); int thumbnail_size = MAX(p_size.x, p_size.y); - img->create(thumbnail_size, thumbnail_size, false, Image::FORMAT_RGBA8); + Ref<Image> img = Image::create_empty(thumbnail_size, thumbnail_size, false, Image::FORMAT_RGBA8); Color bg_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/background_color"); Color keyword_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/keyword_color"); @@ -660,9 +656,7 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const Ref<Resource> &p_f //post_process_preview(img); - Ref<Image> image; - image.instantiate(); - image->create(w, h, false, Image::FORMAT_RGB8, img); + Ref<Image> image = Image::create_from_data(w, h, false, Image::FORMAT_RGB8, img); return ImageTexture::create_from_image(image); } diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp index 1b2afe2151..891b9efa4f 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp @@ -299,7 +299,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { } img.instantiate(); - img->create(w, h, false, Image::FORMAT_RGF, texdata); + img->set_data(w, h, false, Image::FORMAT_RGF, texdata); pm->set_emission_point_texture(ImageTexture::create_from_image(img)); pm->set_emission_point_count(vpc); @@ -315,7 +315,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { } img.instantiate(); - img->create(w, h, false, Image::FORMAT_RGBA8, colordata); + img->set_data(w, h, false, Image::FORMAT_RGBA8, colordata); pm->set_emission_color_texture(ImageTexture::create_from_image(img)); } @@ -335,7 +335,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { } img.instantiate(); - img->create(w, h, false, Image::FORMAT_RGF, normdata); + img->set_data(w, h, false, Image::FORMAT_RGF, normdata); pm->set_emission_normal_texture(ImageTexture::create_from_image(img)); } else { diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp index d7e08db954..167c6d169b 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.cpp +++ b/editor/plugins/tiles/atlas_merging_dialog.cpp @@ -47,9 +47,7 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla merged_mapping.clear(); if (p_atlas_sources.size() >= 2) { - Ref<Image> output_image; - output_image.instantiate(); - output_image->create(1, 1, false, Image::FORMAT_RGBA8); + Ref<Image> output_image = Image::create_empty(1, 1, false, Image::FORMAT_RGBA8); // Compute the new texture region size. Vector2i new_texture_region_size; diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index dd16d4ffea..cbc95ef6d6 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -460,7 +460,7 @@ void TileMapEditorTilesPlugin::_update_theme() { source_sort_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Sort"), SNAME("EditorIcons"))); select_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); paint_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); - line_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons"))); + line_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Line"), SNAME("EditorIcons"))); rect_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Rectangle"), SNAME("EditorIcons"))); bucket_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons"))); @@ -3277,7 +3277,7 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() { void TileMapEditorTerrainsPlugin::_update_theme() { paint_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); - line_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons"))); + line_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Line"), SNAME("EditorIcons"))); rect_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Rectangle"), SNAME("EditorIcons"))); bucket_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons"))); diff --git a/main/main.cpp b/main/main.cpp index 08a9b4c310..c990e01ee3 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2127,7 +2127,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { } else { // Create a 1×1 transparent image. This will effectively hide the splash image. boot_logo.instantiate(); - boot_logo->create(1, 1, false, Image::FORMAT_RGBA8); + boot_logo->initialize_data(1, 1, false, Image::FORMAT_RGBA8); boot_logo->set_pixel(0, 0, Color(0, 0, 0, 0)); } diff --git a/modules/basis_universal/register_types.cpp b/modules/basis_universal/register_types.cpp index e80d453df7..155f7809b0 100644 --- a/modules/basis_universal/register_types.cpp +++ b/modules/basis_universal/register_types.cpp @@ -253,7 +253,7 @@ static Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size }; image.instantiate(); - image->create(info.m_width, info.m_height, info.m_total_levels > 1, imgfmt, gpudata); + image->set_data(info.m_width, info.m_height, info.m_total_levels > 1, imgfmt, gpudata); return image; } diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp index cc21ed28e8..681b3e74bc 100644 --- a/modules/bmp/image_loader_bmp.cpp +++ b/modules/bmp/image_loader_bmp.cpp @@ -156,7 +156,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, if (p_color_buffer == nullptr || color_table_size == 0) { // regular pixels - p_image->create(width, height, false, Image::FORMAT_RGBA8, data); + p_image->set_data(width, height, false, Image::FORMAT_RGBA8, data); } else { // data is in indexed format, extend it @@ -194,7 +194,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, dest += 4; } - p_image->create(width, height, false, Image::FORMAT_RGBA8, extended_data); + p_image->set_data(width, height, false, Image::FORMAT_RGBA8, extended_data); } } return err; diff --git a/modules/camera/camera_macos.mm b/modules/camera/camera_macos.mm index 0b9696a3e9..0e61dde8e9 100644 --- a/modules/camera/camera_macos.mm +++ b/modules/camera/camera_macos.mm @@ -158,7 +158,7 @@ memcpy(w, dataY, new_width * new_height); img[0].instantiate(); - img[0]->create(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]); + img[0]->set_data(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]); } { @@ -177,7 +177,7 @@ ///TODO OpenGL doesn't support FORMAT_RG8, need to do some form of conversion img[1].instantiate(); - img[1]->create(new_width, new_height, 0, Image::FORMAT_RG8, img_data[1]); + img[1]->set_data(new_width, new_height, 0, Image::FORMAT_RG8, img_data[1]); } // set our texture... diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp index 3322ff0a1b..89705e4ee0 100644 --- a/modules/cvtt/image_compress_cvtt.cpp +++ b/modules/cvtt/image_compress_cvtt.cpp @@ -230,7 +230,7 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann h = MAX(h / 2, 1); } - p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); + p_image->set_data(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); } void image_decompress_cvtt(Image *p_image) { @@ -339,5 +339,5 @@ void image_decompress_cvtt(Image *p_image) { w >>= 1; h >>= 1; } - p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); + p_image->set_data(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); } diff --git a/modules/denoise/lightmap_denoiser.cpp b/modules/denoise/lightmap_denoiser.cpp index a0dbd07b10..2b9221bc43 100644 --- a/modules/denoise/lightmap_denoiser.cpp +++ b/modules/denoise/lightmap_denoiser.cpp @@ -51,7 +51,7 @@ Ref<Image> LightmapDenoiserOIDN::denoise_image(const Ref<Image> &p_image) { return p_image; } - img->create(img->get_width(), img->get_height(), false, img->get_format(), data); + img->set_data(img->get_width(), img->get_height(), false, img->get_format(), data); return img; } diff --git a/modules/etcpak/image_compress_etcpak.cpp b/modules/etcpak/image_compress_etcpak.cpp index 7d5557d197..3d66b27556 100644 --- a/modules/etcpak/image_compress_etcpak.cpp +++ b/modules/etcpak/image_compress_etcpak.cpp @@ -233,7 +233,7 @@ void _compress_etcpak(EtcpakType p_compresstype, Image *r_img, float p_lossy_qua } // Replace original image with compressed one. - r_img->create(width, height, mipmaps, target_format, dest_data); + r_img->set_data(width, height, mipmaps, target_format, dest_data); print_verbose(vformat("ETCPAK encode took %s ms.", rtos(OS::get_singleton()->get_ticks_msec() - start_time))); } diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index b3ca8ff00a..6fbdec863f 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -2552,6 +2552,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) { parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name); } + + if (is_static && !base_type.is_meta_type && !(callee_type != GDScriptParser::Node::SUBSCRIPT && parser->current_function != nullptr && parser->current_function->is_static)) { + parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, base_type.to_string()); + } #endif // DEBUG_ENABLED call_type = return_type; diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 1cae7bdfac..a0c107aa53 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -155,6 +155,10 @@ String GDScriptWarning::get_message() const { case INT_ASSIGNED_TO_ENUM: { return "Integer used when an enum value is expected. If this is intended cast the integer to the enum type."; } + case STATIC_CALLED_ON_INSTANCE: { + CHECK_SYMBOLS(2); + return vformat(R"(The function '%s()' is a static function but was called from an instance. Instead, it should be directly called from the type: '%s.%s()'.)", symbols[0], symbols[1], symbols[0]); + } case WARNING_MAX: break; // Can't happen, but silences warning } @@ -215,6 +219,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "EMPTY_FILE", "SHADOWED_GLOBAL_IDENTIFIER", "INT_ASSIGNED_TO_ENUM", + "STATIC_CALLED_ON_INSTANCE", }; static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names."); diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index a639e7b44e..7e4e975510 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -78,6 +78,7 @@ public: EMPTY_FILE, // A script file is empty. SHADOWED_GLOBAL_IDENTIFIER, // A global class or function has the same name as variable. INT_ASSIGNED_TO_ENUM, // An integer value was assigned to an enum-typed variable without casting. + STATIC_CALLED_ON_INSTANCE, // A static method was called on an instance of a class instead of on the class itself. WARNING_MAX, }; diff --git a/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd new file mode 100644 index 0000000000..29d8501b78 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd @@ -0,0 +1,11 @@ +class Player: + var x = 3 + +func test(): + # These should not emit a warning. + var _player = Player.new() + print(String.num_uint64(8589934592)) # 2 ^ 33 + + # This should emit a warning. + var some_string = String() + print(some_string.num_uint64(8589934592)) # 2 ^ 33 diff --git a/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out new file mode 100644 index 0000000000..3933a35178 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out @@ -0,0 +1,7 @@ +GDTEST_OK +>> WARNING +>> Line: 11 +>> STATIC_CALLED_ON_INSTANCE +>> The function 'num_uint64()' is a static function but was called from an instance. Instead, it should be directly called from the type: 'String.num_uint64()'. +8589934592 +8589934592 diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 6700b6de0a..cb148463a7 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -3484,7 +3484,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { height = albedo_texture->get_height(); width = albedo_texture->get_width(); } - orm_image->create(width, height, false, Image::FORMAT_RGBA8); + orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8); if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) { ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS); } @@ -3860,13 +3860,11 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re if (r_spec_gloss->diffuse_img.is_null()) { return; } - Ref<Image> rm_img; - rm_img.instantiate(); bool has_roughness = false; bool has_metal = false; p_material->set_roughness(1.0f); p_material->set_metallic(1.0f); - rm_img->create(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), false, Image::FORMAT_RGBA8); + Ref<Image> rm_img = Image::create_empty(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), false, Image::FORMAT_RGBA8); r_spec_gloss->spec_gloss_img->decompress(); if (r_spec_gloss->diffuse_img.is_valid()) { r_spec_gloss->diffuse_img->decompress(); diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp index 6f0bc16a26..457b263e16 100644 --- a/modules/hdr/image_loader_hdr.cpp +++ b/modules/hdr/image_loader_hdr.cpp @@ -140,7 +140,7 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, Ref<FileAccess> f, BitField } } - p_image->create(width, height, false, Image::FORMAT_RGBE9995, imgdata); + p_image->set_data(width, height, false, Image::FORMAT_RGBE9995, imgdata); return OK; } diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index ce20ac9060..d465467cf9 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -99,7 +99,7 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p fmt = Image::FORMAT_RGB8; } - p_image->create(image_width, image_height, false, fmt, data); + p_image->set_data(image_width, image_height, false, fmt, data); return OK; } diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 8785f327db..9111827c1b 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -251,15 +251,11 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ } for (int i = 0; i < atlas_slices; i++) { - Ref<Image> albedo; - albedo.instantiate(); - albedo->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBA8); + Ref<Image> albedo = Image::create_empty(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBA8); albedo->set_as_black(); albedo_images.write[i] = albedo; - Ref<Image> emission; - emission.instantiate(); - emission->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH); + Ref<Image> emission = Image::create_empty(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH); emission->set_as_black(); emission_images.write[i] = emission; } @@ -478,9 +474,7 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i grid_usage.write[j] = count > 0 ? 255 : 0; } - Ref<Image> img; - img.instantiate(); - img->create(grid_size, grid_size, false, Image::FORMAT_L8, grid_usage); + Ref<Image> img = Image::create_from_data(grid_size, grid_size, false, Image::FORMAT_L8, grid_usage); img->save_png("res://grid_layer_" + itos(1000 + i).substr(1, 3) + ".png"); } #endif @@ -660,9 +654,7 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade #ifdef DEBUG_TEXTURES for (int i = 0; i < atlas_slices; i++) { Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); img->convert(Image::FORMAT_RGBA8); img->save_png("res://5_dilated_" + itos(i) + ".png"); } @@ -778,7 +770,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d panorama_tex->convert(Image::FORMAT_RGBAF); } else { panorama_tex.instantiate(); - panorama_tex->create(8, 8, false, Image::FORMAT_RGBAF); + panorama_tex->initialize_data(8, 8, false, Image::FORMAT_RGBAF); panorama_tex->fill(Color(0, 0, 0, 1)); } @@ -953,13 +945,11 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d for (int i = 0; i < atlas_slices; i++) { Vector<uint8_t> s = rd->texture_get_data(position_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAF, s); + Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAF, s); img->save_exr("res://1_position_" + itos(i) + ".exr", false); s = rd->texture_get_data(normal_tex, i); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->set_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); img->save_exr("res://1_normal_" + itos(i) + ".exr", false); } #endif @@ -1182,9 +1172,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d for (int i = 0; i < atlas_slices; i++) { Vector<uint8_t> s = rd->texture_get_data(light_source_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); img->save_exr("res://2_light_primary_" + itos(i) + ".exr", false); } #endif @@ -1415,14 +1403,10 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d #if 0 for (int i = 0; i < probe_positions.size(); i++) { - Ref<Image> img; - img.instantiate(); - img->create(6, 4, false, Image::FORMAT_RGB8); + Ref<Image> img = Image::create_empty(6, 4, false, Image::FORMAT_RGB8); for (int j = 0; j < 6; j++) { Vector<uint8_t> s = rd->texture_get_data(lightprobe_tex, i * 6 + j); - Ref<Image> img2; - img2.instantiate(); - img2->create(2, 2, false, Image::FORMAT_RGBAF, s); + Ref<Image> img2 = Image::create_from_data(2, 2, false, Image::FORMAT_RGBAF, s); img2->convert(Image::FORMAT_RGB8); img->blit_rect(img2, Rect2i(0, 0, 2, 2), Point2i((j % 3) * 2, (j / 3) * 2)); } @@ -1449,9 +1433,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d if (denoiser.is_valid()) { for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); Ref<Image> denoised = denoiser->denoise_image(img); if (denoised != img) { @@ -1484,9 +1466,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); img->save_exr("res://4_light_secondary_" + itos(i) + ".exr", false); } #endif @@ -1640,9 +1620,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); img->save_exr("res://5_blendseams" + itos(i) + ".exr", false); } #endif @@ -1652,9 +1630,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); img->convert(Image::FORMAT_RGBH); //remove alpha bake_textures.push_back(img); } @@ -1667,9 +1643,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d #ifdef DEBUG_TEXTURES { - Ref<Image> img2; - img2.instantiate(); - img2->create(probe_values.size(), 1, false, Image::FORMAT_RGBAF, probe_data); + Ref<Image> img2 = Image::create_from_data(probe_values.size(), 1, false, Image::FORMAT_RGBAF, probe_data); img2->save_exr("res://6_lightprobes.exr", false); } #endif diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 13070c8033..664b2e0f34 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -292,6 +292,18 @@ namespace Godot } /// <summary> + /// Constructs a <see cref="Plane"/> from a <paramref name="normal"/> vector and + /// a <paramref name="point"/> on the plane. + /// </summary> + /// <param name="normal">The normal of the plane, must be normalized.</param> + /// <param name="point">The point on the plane.</param> + public Plane(Vector3 normal, Vector3 point) + { + _normal = normal; + D = _normal.Dot(point); + } + + /// <summary> /// Constructs a <see cref="Plane"/> from the three points, given in clockwise order. /// </summary> /// <param name="v1">The first point.</param> diff --git a/modules/noise/noise_texture_2d.cpp b/modules/noise/noise_texture_2d.cpp index 23d60c4866..8c785d7591 100644 --- a/modules/noise/noise_texture_2d.cpp +++ b/modules/noise/noise_texture_2d.cpp @@ -176,9 +176,7 @@ Ref<Image> NoiseTexture2D::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradi int width = p_image->get_width(); int height = p_image->get_height(); - Ref<Image> new_image; - new_image.instantiate(); - new_image->create(width, height, false, Image::FORMAT_RGBA8); + Ref<Image> new_image = Image::create_empty(width, height, false, Image::FORMAT_RGBA8); for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { diff --git a/modules/squish/image_decompress_squish.cpp b/modules/squish/image_decompress_squish.cpp index 3a810e5259..2abd9a0c69 100644 --- a/modules/squish/image_decompress_squish.cpp +++ b/modules/squish/image_decompress_squish.cpp @@ -70,7 +70,7 @@ void image_decompress_squish(Image *p_image) { h >>= 1; } - p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); + p_image->set_data(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); if (p_image->get_format() == Image::FORMAT_DXT5_RA_AS_RG) { p_image->convert_ra_rgba8_to_rg(); diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index f43f2784c7..b8c412a201 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -135,7 +135,7 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin res = sw_canvas->clear(true); memfree(buffer); - p_image->create(width, height, false, Image::FORMAT_RGBA8, image); + p_image->set_data(width, height, false, Image::FORMAT_RGBA8, image); } void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const { diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index c9b0fa7dd5..eb398f77c7 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -2494,9 +2494,7 @@ void TextServerAdvanced::_font_set_texture_image(const RID &p_font_rid, const Ve tex.texture_h = p_image->get_height(); tex.format = p_image->get_format(); - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -2515,11 +2513,7 @@ Ref<Image> TextServerAdvanced::_font_get_texture_image(const RID &p_font_rid, co ERR_FAIL_INDEX_V(p_texture_index, fd->cache[size]->textures.size(), Ref<Image>()); const FontTexture &tex = fd->cache[size]->textures[p_texture_index]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); - - return img; + return Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); } void TextServerAdvanced::_font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) { @@ -2853,9 +2847,7 @@ RID TextServerAdvanced::_font_get_glyph_texture_rid(const RID &p_font_rid, const if (gl[p_glyph | mod].texture_idx != -1) { if (fd->cache[size]->textures[gl[p_glyph | mod].texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph | mod].texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -2901,9 +2893,7 @@ Size2 TextServerAdvanced::_font_get_glyph_texture_size(const RID &p_font_rid, co if (gl[p_glyph | mod].texture_idx != -1) { if (fd->cache[size]->textures[gl[p_glyph | mod].texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph | mod].texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -3248,9 +3238,7 @@ void TextServerAdvanced::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca if (RenderingServer::get_singleton() != nullptr) { if (fd->cache[size]->textures[gl.texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -3340,9 +3328,7 @@ void TextServerAdvanced::_font_draw_glyph_outline(const RID &p_font_rid, const R if (RenderingServer::get_singleton() != nullptr) { if (fd->cache[size]->textures[gl.texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 518c877baa..13c997c981 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -1588,9 +1588,7 @@ void TextServerFallback::_font_set_texture_image(const RID &p_font_rid, const Ve tex.texture_h = p_image->get_height(); tex.format = p_image->get_format(); - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -1609,11 +1607,7 @@ Ref<Image> TextServerFallback::_font_get_texture_image(const RID &p_font_rid, co ERR_FAIL_INDEX_V(p_texture_index, fd->cache[size]->textures.size(), Ref<Image>()); const FontTexture &tex = fd->cache[size]->textures[p_texture_index]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); - - return img; + return Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); } void TextServerFallback::_font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) { @@ -1933,9 +1927,7 @@ RID TextServerFallback::_font_get_glyph_texture_rid(const RID &p_font_rid, const if (gl[p_glyph | mod].texture_idx != -1) { if (fd->cache[size]->textures[gl[p_glyph | mod].texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph | mod].texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -1981,9 +1973,7 @@ Size2 TextServerFallback::_font_get_glyph_texture_size(const RID &p_font_rid, co if (gl[p_glyph | mod].texture_idx != -1) { if (fd->cache[size]->textures[gl[p_glyph | mod].texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph | mod].texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -2310,9 +2300,7 @@ void TextServerFallback::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca if (RenderingServer::get_singleton() != nullptr) { if (fd->cache[size]->textures[gl.texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } @@ -2402,9 +2390,7 @@ void TextServerFallback::_font_draw_glyph_outline(const RID &p_font_rid, const R if (RenderingServer::get_singleton() != nullptr) { if (fd->cache[size]->textures[gl.texture_idx].dirty) { FontTexture &tex = fd->cache[size]->textures.write[gl.texture_idx]; - Ref<Image> img; - img.instantiate(); - img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + Ref<Image> img = Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); if (fd->mipmaps) { img->generate_mipmaps(); } diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index aed95294e7..a6fc650414 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -246,7 +246,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff } } - p_image->create(width, height, false, Image::FORMAT_RGBA8, image_data); + p_image->initialize_data(width, height, false, Image::FORMAT_RGBA8, image_data); return OK; } diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 1284412cd8..69fb079970 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -336,9 +336,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { size.x = w; size.y = h; - Ref<Image> img; - img.instantiate(); - img->create(w, h, false, Image::FORMAT_RGBA8); + Ref<Image> img = Image::create_empty(w, h, false, Image::FORMAT_RGBA8); texture->set_image(img); } else { diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 5c43bfc8b7..c5aa110fe6 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -280,7 +280,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, BitF } } - p_image->create(exr_image.width, exr_image.height, false, format, imgdata); + p_image->set_data(exr_image.width, exr_image.height, false, format, imgdata); FreeEXRHeader(&exr_header); FreeEXRImage(&exr_image); diff --git a/modules/webp/webp_common.cpp b/modules/webp/webp_common.cpp index 8657a98853..049c1c3a32 100644 --- a/modules/webp/webp_common.cpp +++ b/modules/webp/webp_common.cpp @@ -183,7 +183,7 @@ Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p ERR_FAIL_COND_V_MSG(errdec, ERR_FILE_CORRUPT, "Failed decoding WebP image."); - p_image->create(features.width, features.height, false, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image); + p_image->set_data(features.width, features.height, false, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image); return OK; } diff --git a/modules/zip/SCsub b/modules/zip/SCsub new file mode 100644 index 0000000000..b7710123fd --- /dev/null +++ b/modules/zip/SCsub @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_zip = env_modules.Clone() + +# Module files +env_zip.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/zip/config.py b/modules/zip/config.py new file mode 100644 index 0000000000..96cd2fc5bd --- /dev/null +++ b/modules/zip/config.py @@ -0,0 +1,17 @@ +def can_build(env, platform): + return env["minizip"] + + +def configure(env): + pass + + +def get_doc_classes(): + return [ + "ZIPReader", + "ZIPPacker", + ] + + +def get_doc_path(): + return "doc_classes" diff --git a/modules/zip/doc_classes/ZIPPacker.xml b/modules/zip/doc_classes/ZIPPacker.xml new file mode 100644 index 0000000000..95d7ef50f9 --- /dev/null +++ b/modules/zip/doc_classes/ZIPPacker.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ZIPPacker" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> + <brief_description> + Allows the creation of zip files. + </brief_description> + <description> + This class implements a writer that allows storing the multiple blobs in a zip archive. + [codeblock] + func write_zip_file(): + var writer := ZIPPacker.new() + var err := writer.open("user://archive.zip") + if err != OK: + return err + writer.start_file("hello.txt") + writer.write_file("Hello World".to_utf8_buffer()) + writer.close_file() + + writer.close() + return OK + [/codeblock] + </description> + <tutorials> + </tutorials> + <methods> + <method name="close"> + <return type="int" enum="Error" /> + <description> + Closes the underlying resources used by this instance. + </description> + </method> + <method name="close_file"> + <return type="int" enum="Error" /> + <description> + Stops writing to a file within the archive. + It will fail if there is no open file. + </description> + </method> + <method name="open"> + <return type="int" enum="Error" /> + <param index="0" name="path" type="String" /> + <param index="1" name="append" type="int" enum="ZIPPacker.ZipAppend" default="0" /> + <description> + Opens a zip file for writing at the given path using the specified write mode. + This must be called before everything else. + </description> + </method> + <method name="start_file"> + <return type="int" enum="Error" /> + <param index="0" name="path" type="String" /> + <description> + Starts writing to a file within the archive. Only one file can be written at the same time. + Must be called after [method open]. + </description> + </method> + <method name="write_file"> + <return type="int" enum="Error" /> + <param index="0" name="data" type="PackedByteArray" /> + <description> + Write the given [param data] to the file. + Needs to be called after [method start_file]. + </description> + </method> + </methods> + <constants> + <constant name="APPEND_CREATE" value="0" enum="ZipAppend"> + </constant> + <constant name="APPEND_CREATEAFTER" value="1" enum="ZipAppend"> + </constant> + <constant name="APPEND_ADDINZIP" value="2" enum="ZipAppend"> + </constant> + </constants> +</class> diff --git a/modules/zip/doc_classes/ZIPReader.xml b/modules/zip/doc_classes/ZIPReader.xml new file mode 100644 index 0000000000..717116a531 --- /dev/null +++ b/modules/zip/doc_classes/ZIPReader.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ZIPReader" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> + <brief_description> + Allows reading the content of a zip file. + </brief_description> + <description> + This class implements a reader that can extract the content of individual files inside a zip archive. + [codeblock] + func read_zip_file(): + var reader := ZIPReader.new() + var err := reader.open("user://archive.zip") + if err == OK: + return PackedByteArray() + var res := reader.read_file("hello.txt") + reader.close() + return res + [/codeblock] + </description> + <tutorials> + </tutorials> + <methods> + <method name="close"> + <return type="int" enum="Error" /> + <description> + Closes the underlying resources used by this instance. + </description> + </method> + <method name="get_files"> + <return type="PackedStringArray" /> + <description> + Returns the list of names of all files in the loaded archive. + Must be called after [method open]. + </description> + </method> + <method name="open"> + <return type="int" enum="Error" /> + <param index="0" name="path" type="String" /> + <description> + Opens the zip archive at the given [param path] and reads its file index. + </description> + </method> + <method name="read_file"> + <return type="PackedByteArray" /> + <param index="0" name="path" type="String" /> + <param index="1" name="case_sensitive" type="bool" default="true" /> + <description> + Loads the whole content of a file in the loaded zip archive into memory and returns it. + Must be called after [method open]. + </description> + </method> + </methods> +</class> diff --git a/modules/zip/register_types.cpp b/modules/zip/register_types.cpp new file mode 100644 index 0000000000..20fb484cfe --- /dev/null +++ b/modules/zip/register_types.cpp @@ -0,0 +1,50 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "register_types.h" + +#include "core/object/class_db.h" +#include "zip_packer.h" +#include "zip_reader.h" + +void initialize_zip_module(ModuleInitializationLevel p_level) { + if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } + + GDREGISTER_CLASS(ZIPPacker); + GDREGISTER_CLASS(ZIPReader); +} + +void uninitialize_zip_module(ModuleInitializationLevel p_level) { + if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } +} diff --git a/modules/zip/register_types.h b/modules/zip/register_types.h new file mode 100644 index 0000000000..2640be12b8 --- /dev/null +++ b/modules/zip/register_types.h @@ -0,0 +1,39 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef ZIP_REGISTER_TYPES_H +#define ZIP_REGISTER_TYPES_H + +#include "modules/register_module_types.h" + +void initialize_zip_module(ModuleInitializationLevel p_level); +void uninitialize_zip_module(ModuleInitializationLevel p_level); + +#endif // ZIP_REGISTER_TYPES_H diff --git a/modules/zip/zip_packer.cpp b/modules/zip/zip_packer.cpp new file mode 100644 index 0000000000..c37fc0945e --- /dev/null +++ b/modules/zip/zip_packer.cpp @@ -0,0 +1,108 @@ +/*************************************************************************/ +/* zip_packer.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "zip_packer.h" + +#include "core/io/zip_io.h" +#include "core/os/os.h" + +Error ZIPPacker::open(String p_path, ZipAppend p_append) { + if (fa.is_valid()) { + close(); + } + + zlib_filefunc_def io = zipio_create_io(&fa); + zf = zipOpen2(p_path.utf8().get_data(), p_append, NULL, &io); + return zf != NULL ? OK : FAILED; +} + +Error ZIPPacker::close() { + ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker cannot be closed because it is not open."); + + return zipClose(zf, NULL) == ZIP_OK ? OK : FAILED; +} + +Error ZIPPacker::start_file(String p_path) { + ERR_FAIL_COND_V_MSG(zf != NULL, FAILED, "ZIPPacker is already in use."); + ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker must be opened before use."); + + zip_fileinfo zipfi; + + OS::DateTime time = OS::get_singleton()->get_datetime(); + + zipfi.tmz_date.tm_hour = time.hour; + zipfi.tmz_date.tm_mday = time.day; + zipfi.tmz_date.tm_min = time.minute; + zipfi.tmz_date.tm_mon = time.month - 1; + zipfi.tmz_date.tm_sec = time.second; + zipfi.tmz_date.tm_year = time.year; + zipfi.dosDate = 0; + zipfi.external_fa = 0; + zipfi.internal_fa = 0; + + int ret = zipOpenNewFileInZip(zf, p_path.utf8().get_data(), &zipfi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); + return ret == ZIP_OK ? OK : FAILED; +} + +Error ZIPPacker::write_file(Vector<uint8_t> p_data) { + ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker must be opened before use."); + + return zipWriteInFileInZip(zf, p_data.ptr(), p_data.size()) == ZIP_OK ? OK : FAILED; +} + +Error ZIPPacker::close_file() { + ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker must be opened before use."); + + Error err = zipCloseFileInZip(zf) == ZIP_OK ? OK : FAILED; + if (err == OK) { + zf = NULL; + } + return err; +} + +void ZIPPacker::_bind_methods() { + ClassDB::bind_method(D_METHOD("open", "path", "append"), &ZIPPacker::open, DEFVAL(Variant(APPEND_CREATE))); + ClassDB::bind_method(D_METHOD("start_file", "path"), &ZIPPacker::start_file); + ClassDB::bind_method(D_METHOD("write_file", "data"), &ZIPPacker::write_file); + ClassDB::bind_method(D_METHOD("close_file"), &ZIPPacker::close_file); + ClassDB::bind_method(D_METHOD("close"), &ZIPPacker::close); + + BIND_ENUM_CONSTANT(APPEND_CREATE); + BIND_ENUM_CONSTANT(APPEND_CREATEAFTER); + BIND_ENUM_CONSTANT(APPEND_ADDINZIP); +} + +ZIPPacker::ZIPPacker() {} + +ZIPPacker::~ZIPPacker() { + if (fa.is_valid()) { + close(); + } +} diff --git a/modules/zip/zip_packer.h b/modules/zip/zip_packer.h new file mode 100644 index 0000000000..23e96b5ad2 --- /dev/null +++ b/modules/zip/zip_packer.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* zip_packer.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef ZIP_PACKER_H +#define ZIP_PACKER_H + +#include "core/io/file_access.h" +#include "core/object/ref_counted.h" + +#include "thirdparty/minizip/zip.h" + +class ZIPPacker : public RefCounted { + GDCLASS(ZIPPacker, RefCounted); + + Ref<FileAccess> fa; + zipFile zf; + +protected: + static void _bind_methods(); + +public: + enum ZipAppend { + APPEND_CREATE = 0, + APPEND_CREATEAFTER = 1, + APPEND_ADDINZIP = 2, + }; + + Error open(String p_path, ZipAppend p_append); + Error close(); + + Error start_file(String p_path); + Error write_file(Vector<uint8_t> p_data); + Error close_file(); + + ZIPPacker(); + ~ZIPPacker(); +}; + +VARIANT_ENUM_CAST(ZIPPacker::ZipAppend) + +#endif // ZIP_PACKER_H diff --git a/modules/zip/zip_reader.cpp b/modules/zip/zip_reader.cpp new file mode 100644 index 0000000000..f35b947cef --- /dev/null +++ b/modules/zip/zip_reader.cpp @@ -0,0 +1,123 @@ +/*************************************************************************/ +/* zip_reader.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "zip_reader.h" + +#include "core/error/error_macros.h" +#include "core/io/zip_io.h" + +Error ZIPReader::open(String p_path) { + if (fa.is_valid()) { + close(); + } + + zlib_filefunc_def io = zipio_create_io(&fa); + uzf = unzOpen2(p_path.utf8().get_data(), &io); + return uzf != NULL ? OK : FAILED; +} + +Error ZIPReader::close() { + ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPReader cannot be closed because it is not open."); + + return unzClose(uzf) == UNZ_OK ? OK : FAILED; +} + +PackedStringArray ZIPReader::get_files() { + ERR_FAIL_COND_V_MSG(fa.is_null(), PackedStringArray(), "ZIPReader must be opened before use."); + + List<String> s; + + if (unzGoToFirstFile(uzf) != UNZ_OK) { + return PackedStringArray(); + } + + do { + unz_file_info64 file_info; + char filename[256]; // Note filename is a path ! + int err = unzGetCurrentFileInfo64(uzf, &file_info, filename, sizeof(filename), NULL, 0, NULL, 0); + if (err == UNZ_OK) { + s.push_back(filename); + } else { + // Assume filename buffer was too small + char *long_filename_buff = (char *)memalloc(file_info.size_filename); + int err2 = unzGetCurrentFileInfo64(uzf, NULL, long_filename_buff, sizeof(long_filename_buff), NULL, 0, NULL, 0); + if (err2 == UNZ_OK) { + s.push_back(long_filename_buff); + memfree(long_filename_buff); + } + } + } while (unzGoToNextFile(uzf) == UNZ_OK); + + PackedStringArray arr; + arr.resize(s.size()); + int idx = 0; + for (const List<String>::Element *E = s.front(); E; E = E->next()) { + arr.set(idx++, E->get()); + } + return arr; +} + +PackedByteArray ZIPReader::read_file(String p_path, bool p_case_sensitive) { + ERR_FAIL_COND_V_MSG(fa.is_null(), PackedByteArray(), "ZIPReader must be opened before use."); + + int cs = p_case_sensitive ? 1 : 2; + if (unzLocateFile(uzf, p_path.utf8().get_data(), cs) != UNZ_OK) { + ERR_FAIL_V_MSG(PackedByteArray(), "File does not exist in zip archive: " + p_path); + } + if (unzOpenCurrentFile(uzf) != UNZ_OK) { + ERR_FAIL_V_MSG(PackedByteArray(), "Could not open file within zip archive."); + } + + unz_file_info info; + unzGetCurrentFileInfo(uzf, &info, NULL, 0, NULL, 0, NULL, 0); + PackedByteArray data; + data.resize(info.uncompressed_size); + + uint8_t *w = data.ptrw(); + unzReadCurrentFile(uzf, &w[0], info.uncompressed_size); + + unzCloseCurrentFile(uzf); + return data; +} + +ZIPReader::ZIPReader() {} + +ZIPReader::~ZIPReader() { + if (fa.is_valid()) { + close(); + } +} + +void ZIPReader::_bind_methods() { + ClassDB::bind_method(D_METHOD("open", "path"), &ZIPReader::open); + ClassDB::bind_method(D_METHOD("close"), &ZIPReader::close); + ClassDB::bind_method(D_METHOD("get_files"), &ZIPReader::get_files); + ClassDB::bind_method(D_METHOD("read_file", "path", "case_sensitive"), &ZIPReader::read_file, DEFVAL(Variant(true))); +} diff --git a/modules/zip/zip_reader.h b/modules/zip/zip_reader.h new file mode 100644 index 0000000000..fbc2fc0409 --- /dev/null +++ b/modules/zip/zip_reader.h @@ -0,0 +1,59 @@ +/*************************************************************************/ +/* zip_reader.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef ZIP_READER_H +#define ZIP_READER_H + +#include "core/io/file_access.h" +#include "core/object/ref_counted.h" + +#include "thirdparty/minizip/unzip.h" + +class ZIPReader : public RefCounted { + GDCLASS(ZIPReader, RefCounted) + + Ref<FileAccess> fa; + unzFile uzf; + +protected: + static void _bind_methods(); + +public: + Error open(String p_path); + Error close(); + + PackedStringArray get_files(); + PackedByteArray read_file(String p_path, bool p_case_sensitive); + + ZIPReader(); + ~ZIPReader(); +}; + +#endif // ZIP_READER_H diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index ef3b79b630..317f111202 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1551,7 +1551,7 @@ String EditorExportPlatformAndroid::load_splash_refs(Ref<Image> &splash_image, R print_verbose("Creating splash background color image."); splash_bg_color_image.instantiate(); - splash_bg_color_image->create(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format()); + splash_bg_color_image->initialize_data(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format()); splash_bg_color_image->fill(bg_color); String processed_splash_config_xml = vformat(SPLASH_CONFIG_XML_CONTENT, bool_to_string(apply_filter)); diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index 74a57dc614..83b2012d3e 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -740,8 +740,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp img->resize(info.width, info.width / aspect_ratio); } } - Ref<Image> new_img = memnew(Image); - new_img->create(info.width, info.height, false, Image::FORMAT_RGBA8); + Ref<Image> new_img = Image::create_empty(info.width, info.height, false, Image::FORMAT_RGBA8); new_img->fill(boot_bg_color); _blend_and_rotate(new_img, img, false); err = new_img->save_png(p_dest_dir + info.export_name); @@ -755,8 +754,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp } } else { // Generate loading screen from the splash screen - Ref<Image> img = memnew(Image); - img->create(info.width, info.height, false, Image::FORMAT_RGBA8); + Ref<Image> img = Image::create_empty(info.width, info.height, false, Image::FORMAT_RGBA8); img->fill(boot_bg_color); Ref<Image> img_bs; diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp index d57e6bd21c..2c5df48b75 100644 --- a/scene/3d/gpu_particles_collision_3d.cpp +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -490,9 +490,7 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() { params.thickness = th; _compute_sdf(¶ms); - Ref<Image> ret; - ret.instantiate(); - ret->create(sdf_size.x, sdf_size.y * sdf_size.z, false, Image::FORMAT_RF, cells_data); + Ref<Image> ret = Image::create_from_data(sdf_size.x, sdf_size.y * sdf_size.z, false, Image::FORMAT_RF, cells_data); ret->convert(Image::FORMAT_RH); //convert to half, save space ret->set_meta("depth", sdf_size.z); //hack, make sure to add to the docs of this function diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 3ea1de57cd..1b5427c80d 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -145,10 +145,7 @@ Array LightmapGIData::_get_light_textures_data() const { for (int i = 0; i < texture_count; i++) { int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture; - Ref<Image> texture_image; - texture_image.instantiate(); - - texture_image->create(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); + Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); for (int j = 0; j < texture_slice_count; j++) { texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j)); @@ -818,7 +815,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa } md.albedo_on_uv2.instantiate(); - md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom); + md.albedo_on_uv2->set_data(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom); } md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION]; @@ -1054,7 +1051,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa } break; case ENVIRONMENT_MODE_CUSTOM_COLOR: { environment_image.instantiate(); - environment_image->create(128, 64, false, Image::FORMAT_RGBAF); + environment_image->initialize_data(128, 64, false, Image::FORMAT_RGBAF); Color c = environment_custom_color; c.r *= environment_custom_energy; c.g *= environment_custom_energy; diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 3dba0221bb..7caf2f4874 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -77,9 +77,7 @@ Dictionary VoxelGIData::_get_data() const { d["octree_cells"] = get_octree_cells(); d["octree_data"] = get_data_cells(); if (otsize != Vector3i()) { - Ref<Image> img; - img.instantiate(); - img->create(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field()); + Ref<Image> img = Image::create_from_data(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field()); Vector<uint8_t> df_png = img->save_png_to_buffer(); ERR_FAIL_COND_V(df_png.size() == 0, Dictionary()); d["octree_df_png"] = df_png; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 6ab27853f1..2ea45df309 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -322,62 +322,62 @@ void Node::_propagate_exit_tree() { data.depth = -1; } -void Node::move_child(Node *p_child, int p_pos) { +void Node::move_child(Node *p_child, int p_index) { ERR_FAIL_NULL(p_child); ERR_FAIL_COND_MSG(p_child->data.parent != this, "Child is not a child of this node."); // We need to check whether node is internal and move it only in the relevant node range. if (p_child->_is_internal_front()) { - if (p_pos < 0) { - p_pos += data.internal_children_front; + if (p_index < 0) { + p_index += data.internal_children_front; } - ERR_FAIL_INDEX_MSG(p_pos, data.internal_children_front, vformat("Invalid new child position: %d. Child is internal.", p_pos)); - _move_child(p_child, p_pos); + ERR_FAIL_INDEX_MSG(p_index, data.internal_children_front, vformat("Invalid new child index: %d. Child is internal.", p_index)); + _move_child(p_child, p_index); } else if (p_child->_is_internal_back()) { - if (p_pos < 0) { - p_pos += data.internal_children_back; + if (p_index < 0) { + p_index += data.internal_children_back; } - ERR_FAIL_INDEX_MSG(p_pos, data.internal_children_back, vformat("Invalid new child position: %d. Child is internal.", p_pos)); - _move_child(p_child, data.children.size() - data.internal_children_back + p_pos); + ERR_FAIL_INDEX_MSG(p_index, data.internal_children_back, vformat("Invalid new child index: %d. Child is internal.", p_index)); + _move_child(p_child, data.children.size() - data.internal_children_back + p_index); } else { - if (p_pos < 0) { - p_pos += get_child_count(false); + if (p_index < 0) { + p_index += get_child_count(false); } - ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1 - data.internal_children_front - data.internal_children_back, vformat("Invalid new child position: %d.", p_pos)); - _move_child(p_child, p_pos + data.internal_children_front); + ERR_FAIL_INDEX_MSG(p_index, data.children.size() + 1 - data.internal_children_front - data.internal_children_back, vformat("Invalid new child index: %d.", p_index)); + _move_child(p_child, p_index + data.internal_children_front); } } -void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) { +void Node::_move_child(Node *p_child, int p_index, bool p_ignore_end) { ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, move_child() failed. Consider using call_deferred(\"move_child\") instead (or \"popup\" if this is from a popup)."); // Specifying one place beyond the end - // means the same as moving to the last position + // means the same as moving to the last index if (!p_ignore_end) { // p_ignore_end is a little hack to make back internal children work properly. if (p_child->_is_internal_front()) { - if (p_pos == data.internal_children_front) { - p_pos--; + if (p_index == data.internal_children_front) { + p_index--; } } else if (p_child->_is_internal_back()) { - if (p_pos == data.children.size()) { - p_pos--; + if (p_index == data.children.size()) { + p_index--; } } else { - if (p_pos == data.children.size() - data.internal_children_back) { - p_pos--; + if (p_index == data.children.size() - data.internal_children_back) { + p_index--; } } } - if (p_child->data.pos == p_pos) { + if (p_child->data.index == p_index) { return; //do nothing } - int motion_from = MIN(p_pos, p_child->data.pos); - int motion_to = MAX(p_pos, p_child->data.pos); + int motion_from = MIN(p_index, p_child->data.index); + int motion_to = MAX(p_index, p_child->data.index); - data.children.remove_at(p_child->data.pos); - data.children.insert(p_pos, p_child); + data.children.remove_at(p_child->data.index); + data.children.insert(p_index, p_child); if (data.tree) { data.tree->tree_changed(); @@ -386,7 +386,7 @@ void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) { data.blocked++; //new pos first for (int i = motion_from; i <= motion_to; i++) { - data.children[i]->data.pos = i; + data.children[i]->data.index = i; } // notification second move_child_notify(p_child); @@ -1104,7 +1104,7 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) { //add a child node quickly, without name validation p_child->data.name = p_name; - p_child->data.pos = data.children.size(); + p_child->data.index = data.children.size(); data.children.push_back(p_child); p_child->data.parent = this; @@ -1171,9 +1171,9 @@ void Node::remove_child(Node *p_child) { Node **children = data.children.ptrw(); int idx = -1; - if (p_child->data.pos >= 0 && p_child->data.pos < child_count) { - if (children[p_child->data.pos] == p_child) { - idx = p_child->data.pos; + if (p_child->data.index >= 0 && p_child->data.index < child_count) { + if (children[p_child->data.index] == p_child) { + idx = p_child->data.index; } } @@ -1209,12 +1209,12 @@ void Node::remove_child(Node *p_child) { children = data.children.ptrw(); for (int i = idx; i < child_count; i++) { - children[i]->data.pos = i; + children[i]->data.index = i; children[i]->notification(NOTIFICATION_MOVED_IN_PARENT); } p_child->data.parent = nullptr; - p_child->data.pos = -1; + p_child->data.index = -1; if (data.inside_tree) { p_child->_propagate_after_exit_tree(); @@ -1473,7 +1473,7 @@ bool Node::is_greater_than(const Node *p_node) const { int idx = data.depth - 1; while (n) { ERR_FAIL_INDEX_V(idx, data.depth, false); - this_stack[idx--] = n->data.pos; + this_stack[idx--] = n->data.index; n = n->data.parent; } ERR_FAIL_COND_V(idx != -1, false); @@ -1481,7 +1481,7 @@ bool Node::is_greater_than(const Node *p_node) const { idx = p_node->data.depth - 1; while (n) { ERR_FAIL_INDEX_V(idx, p_node->data.depth, false); - that_stack[idx--] = n->data.pos; + that_stack[idx--] = n->data.index; n = n->data.parent; } @@ -1892,9 +1892,9 @@ int Node::get_index(bool p_include_internal) const { ERR_FAIL_COND_V_MSG(!p_include_internal && (_is_internal_front() || _is_internal_back()), -1, "Node is internal. Can't get index with 'include_internal' being false."); if (data.parent && !p_include_internal) { - return data.pos - data.parent->data.internal_children_front; + return data.index - data.parent->data.internal_children_front; } - return data.pos; + return data.index; } Ref<Tween> Node::create_tween() { @@ -2389,12 +2389,12 @@ void Node::replace_by(Node *p_node, bool p_keep_groups) { } Node *parent = data.parent; - int pos_in_parent = data.pos; + int index_in_parent = data.index; if (data.parent) { parent->remove_child(this); parent->add_child(p_node); - parent->move_child(p_node, pos_in_parent); + parent->move_child(p_node, index_in_parent); } while (get_child_count()) { @@ -2757,7 +2757,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("add_to_group", "group", "persistent"), &Node::add_to_group, DEFVAL(false)); ClassDB::bind_method(D_METHOD("remove_from_group", "group"), &Node::remove_from_group); ClassDB::bind_method(D_METHOD("is_in_group", "group"), &Node::is_in_group); - ClassDB::bind_method(D_METHOD("move_child", "child_node", "to_position"), &Node::move_child); + ClassDB::bind_method(D_METHOD("move_child", "child_node", "to_index"), &Node::move_child); ClassDB::bind_method(D_METHOD("get_groups"), &Node::_get_groups); ClassDB::bind_method(D_METHOD("set_owner", "owner"), &Node::set_owner); ClassDB::bind_method(D_METHOD("get_owner"), &Node::get_owner); diff --git a/scene/main/node.h b/scene/main/node.h index 8c82c41e46..c8c8c395ce 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -105,7 +105,7 @@ private: int internal_children_front = 0; int internal_children_back = 0; - int pos = -1; + int index = -1; int depth = -1; int blocked = 0; // Safeguard that throws an error when attempting to modify the tree in a harmful way while being traversed. StringName name; @@ -187,8 +187,8 @@ private: Error _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); Error _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); - _FORCE_INLINE_ bool _is_internal_front() const { return data.parent && data.pos < data.parent->data.internal_children_front; } - _FORCE_INLINE_ bool _is_internal_back() const { return data.parent && data.pos >= data.parent->data.children.size() - data.parent->data.internal_children_back; } + _FORCE_INLINE_ bool _is_internal_front() const { return data.parent && data.index < data.parent->data.internal_children_front; } + _FORCE_INLINE_ bool _is_internal_back() const { return data.parent && data.index >= data.parent->data.children.size() - data.parent->data.internal_children_back; } friend class SceneTree; @@ -347,8 +347,8 @@ public: void get_groups(List<GroupInfo> *p_groups) const; int get_persistent_group_count() const; - void move_child(Node *p_child, int p_pos); - void _move_child(Node *p_child, int p_pos, bool p_ignore_end = false); + void move_child(Node *p_child, int p_index); + void _move_child(Node *p_child, int p_index, bool p_ignore_end = false); void set_owner(Node *p_owner); Node *get_owner() const; diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 0505f6b559..1b06e09bb8 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -639,9 +639,7 @@ void BitMap::resize(const Size2i &p_new_size) { } Ref<Image> BitMap::convert_to_image() const { - Ref<Image> image; - image.instantiate(); - image->create(width, height, false, Image::FORMAT_L8); + Ref<Image> image = Image::create_empty(width, height, false, Image::FORMAT_L8); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 4085aa8ec2..3a2b0ed9cb 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -740,7 +740,7 @@ Ref<Image> CompressedTexture2D::load_image_from_file(Ref<FileAccess> f, int p_si } } - image->create(w, h, true, mipmap_images[0]->get_format(), img_data); + image->set_data(w, h, true, mipmap_images[0]->get_format(), img_data); return image; } @@ -766,10 +766,7 @@ Ref<Image> CompressedTexture2D::load_image_from_file(Ref<FileAccess> f, int p_si f->get_buffer(wr, data.size()); } - Ref<Image> image; - image.instantiate(); - - image->create(tw, th, mipmaps - i ? true : false, format, data); + Ref<Image> image = Image::create_from_data(tw, th, mipmaps - i ? true : false, format, data); return image; } @@ -2336,11 +2333,11 @@ void GradientTexture2D::_update() { image.instantiate(); if (gradient->get_points_count() <= 1) { // No need to interpolate. - image->create(width, height, false, (use_hdr) ? Image::FORMAT_RGBAF : Image::FORMAT_RGBA8); + image->initialize_data(width, height, false, (use_hdr) ? Image::FORMAT_RGBAF : Image::FORMAT_RGBA8); image->fill((gradient->get_points_count() == 1) ? gradient->get_color(0) : Color(0, 0, 0, 1)); } else { if (use_hdr) { - image->create(width, height, false, Image::FORMAT_RGBAF); + image->initialize_data(width, height, false, Image::FORMAT_RGBAF); Gradient &g = **gradient; // `create()` isn't available for non-uint8_t data, so fill in the data manually. for (int y = 0; y < height; y++) { @@ -2367,7 +2364,7 @@ void GradientTexture2D::_update() { } } } - image->create(width, height, false, Image::FORMAT_RGBA8, data); + image->set_data(width, height, false, Image::FORMAT_RGBA8, data); } } diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index d7d7b5fe31..3caf6484d9 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -1801,11 +1801,11 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) { // Get the best tile. Ref<Texture2D> texture = counts[terrain_set][terrain].texture; Rect2i region = counts[terrain_set][terrain].region; - image->create(region.size.x, region.size.y, false, Image::FORMAT_RGBA8); + image->initialize_data(region.size.x, region.size.y, false, Image::FORMAT_RGBA8); image->blit_rect(texture->get_image(), region, Point2i()); image->resize(p_size.x, p_size.y, Image::INTERPOLATE_NEAREST); } else { - image->create(1, 1, false, Image::FORMAT_RGBA8); + image->initialize_data(1, 1, false, Image::FORMAT_RGBA8); image->set_pixel(0, 0, get_terrain_color(terrain_set, terrain)); } Ref<ImageTexture> icon = ImageTexture::create_from_image(image); @@ -4602,9 +4602,7 @@ void TileSetAtlasSource::_update_padded_texture() { return; } - Ref<Image> image; - image.instantiate(); - image->create(size.x, size.y, false, src->get_format()); + Ref<Image> image = Image::create_empty(size.x, size.y, false, src->get_format()); for (KeyValue<Vector2i, TileAlternativesData> kv : tiles) { for (int frame = 0; frame < (int)kv.value.animation_frames_durations.size(); frame++) { diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index ab7354f6e7..f125b05a26 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -460,9 +460,9 @@ void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector2> image.instantiate(); if (p_array.size() == 0) { - image->create(1, 1, false, Image::Format::FORMAT_RGBF); + image->initialize_data(1, 1, false, Image::Format::FORMAT_RGBF); } else { - image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); + image->initialize_data(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); } for (int i = 0; i < p_array.size(); i++) { @@ -481,9 +481,9 @@ void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector3> image.instantiate(); if (p_array.size() == 0) { - image->create(1, 1, false, Image::Format::FORMAT_RGBF); + image->initialize_data(1, 1, false, Image::Format::FORMAT_RGBF); } else { - image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); + image->initialize_data(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); } for (int i = 0; i < p_array.size(); i++) { @@ -502,9 +502,9 @@ void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Color> &p image.instantiate(); if (p_array.size() == 0) { - image->create(1, 1, false, Image::Format::FORMAT_RGBA8); + image->initialize_data(1, 1, false, Image::Format::FORMAT_RGBA8); } else { - image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBA8); + image->initialize_data(p_array.size(), 1, false, Image::Format::FORMAT_RGBA8); } for (int i = 0; i < p_array.size(); i++) { diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 9b6be0b422..f4a27144d9 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -2335,7 +2335,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_ img.instantiate(); for (uint32_t i = 0; i < cascade_size; i++) { Vector<uint8_t> subarr = data.slice(128 * 128 * i, 128 * 128 * (i + 1)); - img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr); + img->set_data(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr); img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png"); } diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 4ff2a66975..6940276040 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -772,9 +772,7 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0); RD::get_singleton()->free(rad_tex); - Ref<Image> img; - img.instantiate(); - img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data); + Ref<Image> img = Image::create_from_data(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data); for (int i = 0; i < p_size.width; i++) { for (int j = 0; j < p_size.height; j++) { Color c = img->get_pixel(i, j); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index e5e94ea1fb..75fe84f46b 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -250,9 +250,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba panorama_color = ambient_color.lerp(panorama_color, ambient_color_sky_mix); } - Ref<Image> panorama; - panorama.instantiate(); - panorama->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF); + Ref<Image> panorama = Image::create_empty(p_size.width, p_size.height, false, Image::FORMAT_RGBAF); panorama->fill(panorama_color); return panorama; } @@ -1305,36 +1303,28 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Typed { PackedByteArray data = RD::get_singleton()->texture_get_data(albedo_alpha_tex, 0); - Ref<Image> img; - img.instantiate(); - img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); + Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); RD::get_singleton()->free(albedo_alpha_tex); ret.push_back(img); } { PackedByteArray data = RD::get_singleton()->texture_get_data(normal_tex, 0); - Ref<Image> img; - img.instantiate(); - img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); + Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); RD::get_singleton()->free(normal_tex); ret.push_back(img); } { PackedByteArray data = RD::get_singleton()->texture_get_data(orm_tex, 0); - Ref<Image> img; - img.instantiate(); - img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); + Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data); RD::get_singleton()->free(orm_tex); ret.push_back(img); } { PackedByteArray data = RD::get_singleton()->texture_get_data(emission_tex, 0); - Ref<Image> img; - img.instantiate(); - img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBAH, data); + Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBAH, data); RD::get_singleton()->free(emission_tex); ret.push_back(img); } diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index d5285c07f4..bc70c57b69 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -1124,9 +1124,7 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { //this could be better optimized to reuse an existing image , done this way //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); image->fill(Color(1, 0, 1, 1)); texture_2d_initialize(p_texture, image); @@ -1135,9 +1133,7 @@ void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) { void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) { //this could be better optimized to reuse an existing image , done this way //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); image->fill(Color(1, 0, 1, 1)); Vector<Ref<Image>> images; @@ -1156,9 +1152,7 @@ void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { //this could be better optimized to reuse an existing image , done this way //for now to get it working - Ref<Image> image; - image.instantiate(); - image->create(4, 4, false, Image::FORMAT_RGBA8); + Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8); image->fill(Color(1, 0, 1, 1)); Vector<Ref<Image>> images; @@ -1181,9 +1175,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { #endif Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + Ref<Image> image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); if (tex->format != tex->validated_format) { image->convert(tex->format); @@ -1204,9 +1196,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); - Ref<Image> image; - image.instantiate(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + Ref<Image> image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); if (tex->format != tex->validated_format) { image->convert(tex->format); @@ -1232,9 +1222,7 @@ Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size); - Ref<Image> img; - img.instantiate(); - img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); + Ref<Image> img = Image::create_from_data(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); if (tex->format != tex->validated_format) { img->convert(tex->format); diff --git a/servers/rendering/renderer_scene_occlusion_cull.cpp b/servers/rendering/renderer_scene_occlusion_cull.cpp index bda0950097..e1ca5a7103 100644 --- a/servers/rendering/renderer_scene_occlusion_cull.cpp +++ b/servers/rendering/renderer_scene_occlusion_cull.cpp @@ -180,7 +180,7 @@ RID RendererSceneOcclusionCull::HZBuffer::get_debug_texture() { ptrw[i] = MIN(mips[0][i] / debug_tex_range, 1.0) * 255; } - debug_image->create(sizes[0].x, sizes[0].y, false, Image::FORMAT_L8, debug_data); + debug_image->set_data(sizes[0].x, sizes[0].y, false, Image::FORMAT_L8, debug_data); if (debug_texture.is_null()) { debug_texture = RS::get_singleton()->texture_2d_create(debug_image); diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 430e2042d9..a5ee1d5726 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -222,12 +222,7 @@ RID XRInterface::get_vrs_texture() { data_ptr[d++] = density; } } - - Ref<Image> image; - image.instantiate(); - image->create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data); - - images.push_back(image); + images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data)); } if (images.size() == 1) { diff --git a/tests/scene/test_bit_map.h b/tests/scene/test_bit_map.h index 635449181e..a102f40725 100644 --- a/tests/scene/test_bit_map.h +++ b/tests/scene/test_bit_map.h @@ -76,15 +76,11 @@ TEST_CASE("[BitMap] Create bit map from image alpha") { bit_map.create_from_image_alpha(empty_img); CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because bitmap creation from an empty image should fail."); - Ref<Image> wrong_format_img; - wrong_format_img.instantiate(); - wrong_format_img->create(3, 3, false, Image::Format::FORMAT_DXT1); + Ref<Image> wrong_format_img = Image::create_empty(3, 3, false, Image::Format::FORMAT_DXT1); bit_map.create_from_image_alpha(wrong_format_img); CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because converting from a compressed image should fail."); - Ref<Image> img; - img.instantiate(); - img->create(3, 3, false, Image::Format::FORMAT_RGBA8); + Ref<Image> img = Image::create_empty(3, 3, false, Image::Format::FORMAT_RGBA8); img->set_pixel(0, 0, Color(0, 0, 0, 0)); img->set_pixel(0, 1, Color(0, 0, 0, 0.09f)); img->set_pixel(0, 2, Color(0, 0, 0, 0.25f)); |