diff options
Diffstat (limited to 'scene/resources/texture.cpp')
-rw-r--r-- | scene/resources/texture.cpp | 813 |
1 files changed, 411 insertions, 402 deletions
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 39237e1a33..063a13efc0 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -32,7 +32,6 @@ #include "core/core_string_names.h" #include "core/io/image_loader.h" -#include "core/method_bind_ext.gen.inc" #include "core/os/os.h" #include "mesh.h" #include "scene/resources/bit_map.h" @@ -46,28 +45,21 @@ bool Texture2D::is_pixel_opaque(int p_x, int p_y) const { return true; } -void Texture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); +void Texture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose); } -void Texture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); +void Texture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose); } -void Texture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); +void Texture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, p_clip_uv); } bool Texture2D::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { r_rect = p_rect; r_src_rect = p_src_rect; - return true; } @@ -76,10 +68,10 @@ void Texture2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_height"), &Texture2D::get_height); ClassDB::bind_method(D_METHOD("get_size"), &Texture2D::get_size); ClassDB::bind_method(D_METHOD("has_alpha"), &Texture2D::has_alpha); - ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); - ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); - ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_data"), &Texture2D::get_data); + ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose"), &Texture2D::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_image"), &Texture2D::get_image); ADD_GROUP("", ""); } @@ -96,13 +88,13 @@ void ImageTexture::reload_from_file() { } Ref<Image> img; - img.instance(); + img.instantiate(); if (ImageLoader::load_image(path, img) == OK) { create_from_image(img); } else { Resource::reload_from_file(); - _change_notify(); + notify_property_list_changed(); emit_changed(); } } @@ -124,7 +116,7 @@ bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) { bool ImageTexture::_get(const StringName &p_name, Variant &r_ret) const { if (p_name == "image") { - r_ret = get_data(); + r_ret = get_image(); } else if (p_name == "size") { r_ret = Size2(w, h); } else { @@ -146,7 +138,7 @@ void ImageTexture::_reload_hook(const RID &p_hook) { } Ref<Image> img; - img.instance(); + img.instantiate(); Error err = ImageLoader::load_image(path, img); ERR_FAIL_COND_MSG(err != OK, "Cannot load image from path '" + path + "'."); @@ -154,12 +146,12 @@ void ImageTexture::_reload_hook(const RID &p_hook) { RID new_texture = RenderingServer::get_singleton()->texture_2d_create(img); RenderingServer::get_singleton()->texture_replace(texture, new_texture); - _change_notify(); + notify_property_list_changed(); emit_changed(); } void ImageTexture::create_from_image(const Ref<Image> &p_image) { - ERR_FAIL_COND(p_image.is_null()); + ERR_FAIL_COND_MSG(p_image.is_null() || p_image->is_empty(), "Invalid image"); w = p_image->get_width(); h = p_image->get_height(); format = p_image->get_format(); @@ -171,7 +163,7 @@ void ImageTexture::create_from_image(const Ref<Image> &p_image) { RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_image); RenderingServer::get_singleton()->texture_replace(texture, new_texture); } - _change_notify(); + notify_property_list_changed(); emit_changed(); image_stored = true; @@ -181,20 +173,19 @@ Image::Format ImageTexture::get_format() const { return format; } -void ImageTexture::update(const Ref<Image> &p_image, bool p_immediate) { - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(texture.is_null()); - ERR_FAIL_COND(p_image->get_width() != w || p_image->get_height() != h); - ERR_FAIL_COND(p_image->get_format() != format); - ERR_FAIL_COND(mipmaps != p_image->has_mipmaps()); +void ImageTexture::update(const Ref<Image> &p_image) { + ERR_FAIL_COND_MSG(p_image.is_null(), "Invalid image"); + ERR_FAIL_COND_MSG(texture.is_null(), "Texture is not initialized."); + ERR_FAIL_COND_MSG(p_image->get_width() != w || p_image->get_height() != h, + "The new image dimensions must match the texture size."); + ERR_FAIL_COND_MSG(p_image->get_format() != format, + "The new image format must match the texture's image format."); + ERR_FAIL_COND_MSG(mipmaps != p_image->has_mipmaps(), + "The new image mipmaps configuration must match the texture's image mipmaps configuration"); - if (p_immediate) { - RenderingServer::get_singleton()->texture_2d_update_immediate(texture, p_image); - } else { - RenderingServer::get_singleton()->texture_2d_update(texture, p_image); - } + RenderingServer::get_singleton()->texture_2d_update(texture, p_image); - _change_notify(); + notify_property_list_changed(); emit_changed(); alpha_cache.unref(); @@ -205,7 +196,7 @@ void ImageTexture::_resource_path_changed() { String path = get_path(); } -Ref<Image> ImageTexture::get_data() const { +Ref<Image> ImageTexture::get_image() const { if (image_stored) { return RenderingServer::get_singleton()->texture_2d_get(texture); } else { @@ -233,43 +224,37 @@ bool ImageTexture::has_alpha() const { return (format == Image::FORMAT_LA8 || format == Image::FORMAT_RGBA8); } -void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { if ((w | h) == 0) { return; } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose); } -void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { if ((w | h) == 0) { return; } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose); } -void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { if ((w | h) == 0) { return; } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, p_clip_uv); } bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const { if (!alpha_cache.is_valid()) { - Ref<Image> img = get_data(); + Ref<Image> img = get_image(); if (img.is_valid()) { if (img->is_compressed()) { //must decompress, if compressed Ref<Image> decom = img->duplicate(); decom->decompress(); img = decom; } - alpha_cache.instance(); + alpha_cache.instantiate(); alpha_cache->create_from_image_alpha(img); } } @@ -316,17 +301,12 @@ void ImageTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("create_from_image", "image"), &ImageTexture::create_from_image); ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format); - ClassDB::bind_method(D_METHOD("update", "image", "immediate"), &ImageTexture::update, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("update", "image"), &ImageTexture::update); ClassDB::bind_method(D_METHOD("set_size_override", "size"), &ImageTexture::set_size_override); ClassDB::bind_method(D_METHOD("_reload_hook", "rid"), &ImageTexture::_reload_hook); } -ImageTexture::ImageTexture() { - w = h = 0; - image_stored = false; - mipmaps = false; - format = Image::FORMAT_L8; -} +ImageTexture::ImageTexture() {} ImageTexture::~ImageTexture() { if (texture.is_valid()) { @@ -343,7 +323,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit uint32_t mipmaps = f->get_32(); Image::Format format = Image::Format(f->get_32()); - if (data_format == DATA_FORMAT_LOSSLESS || data_format == DATA_FORMAT_LOSSY || data_format == DATA_FORMAT_BASIS_UNIVERSAL) { + if (data_format == DATA_FORMAT_PNG || data_format == DATA_FORMAT_WEBP || data_format == DATA_FORMAT_BASIS_UNIVERSAL) { //look for a PNG or WEBP file inside int sw = w; @@ -351,7 +331,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit //mipmaps need to be read independently, they will be later combined Vector<Ref<Image>> mipmap_images; - int total_size = 0; + uint64_t total_size = 0; bool first = true; @@ -374,16 +354,16 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit } Ref<Image> img; - if (data_format == DATA_FORMAT_BASIS_UNIVERSAL) { + if (data_format == DATA_FORMAT_BASIS_UNIVERSAL && Image::basis_universal_unpacker) { img = Image::basis_universal_unpacker(pv); - } else if (data_format == DATA_FORMAT_LOSSLESS) { - img = Image::lossless_unpacker(pv); - } else { - img = Image::lossy_unpacker(pv); + } else if (data_format == DATA_FORMAT_PNG && Image::png_unpacker) { + img = Image::png_unpacker(pv); + } else if (data_format == DATA_FORMAT_WEBP && Image::webp_unpacker) { + img = Image::webp_unpacker(pv); } - if (img.is_null() || img->empty()) { - ERR_FAIL_COND_V(img.is_null() || img->empty(), Ref<Image>()); + if (img.is_null() || img->is_empty()) { + ERR_FAIL_COND_V(img.is_null() || img->is_empty(), Ref<Image>()); } if (first) { @@ -406,7 +386,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit //print_line("mipmap read total: " + itos(mipmap_images.size())); Ref<Image> image; - image.instance(); + image.instantiate(); if (mipmap_images.size() == 1) { //only one image (which will most likely be the case anyway for this format) @@ -426,7 +406,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit Vector<uint8_t> id = mipmap_images[i]->get_data(); int len = id.size(); const uint8_t *r = id.ptr(); - copymem(&wr[ofs], r, len); + memcpy(&wr[ofs], r, len); ofs += len; } } @@ -458,7 +438,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit } Ref<Image> image; - image.instance(); + image.instantiate(); image->create(tw, th, mipmaps - i ? true : false, format, data); @@ -506,13 +486,13 @@ Image::Format StreamTexture2D::get_format() const { return format; } -Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) { +Error StreamTexture2D::_load_data(const String &p_path, int &r_width, int &r_height, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) { alpha_cache.unref(); ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER); FileAccess *f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path)); uint8_t header[4]; f->get_buffer(header, 4); @@ -527,8 +507,8 @@ Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &t memdelete(f); ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); } - tw_custom = f->get_32(); - th_custom = f->get_32(); + r_width = f->get_32(); + r_height = f->get_32(); uint32_t df = f->get_32(); //data format //skip reserved @@ -559,7 +539,7 @@ Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &t memdelete(f); - if (image.is_null() || image->empty()) { + if (image.is_null() || image->is_empty()) { return ERR_CANT_OPEN; } @@ -567,16 +547,16 @@ Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &t } Error StreamTexture2D::load(const String &p_path) { - int lw, lh, lwc, lhc; + int lw, lh; Ref<Image> image; - image.instance(); + image.instantiate(); bool request_3d; bool request_normal; bool request_roughness; int mipmap_limit; - Error err = _load_data(p_path, lw, lh, lwc, lhc, image, request_3d, request_normal, request_roughness, mipmap_limit); + Error err = _load_data(p_path, lw, lh, image, request_3d, request_normal, request_roughness, mipmap_limit); if (err) { return err; } @@ -587,12 +567,12 @@ Error StreamTexture2D::load(const String &p_path) { } else { texture = RS::get_singleton()->texture_2d_create(image); } - if (lwc || lhc) { - RS::get_singleton()->texture_set_size_override(texture, lwc, lhc); + if (lw || lh) { + RS::get_singleton()->texture_set_size_override(texture, lw, lh); } - w = lwc ? lwc : lw; - h = lhc ? lhc : lh; + w = lw; + h = lh; path_to_file = p_path; format = image->get_format(); @@ -628,7 +608,7 @@ Error StreamTexture2D::load(const String &p_path) { } #endif - _change_notify(); + notify_property_list_changed(); emit_changed(); return OK; } @@ -652,38 +632,32 @@ RID StreamTexture2D::get_rid() const { return texture; } -void StreamTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void StreamTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { if ((w | h) == 0) { return; } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose); } -void StreamTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void StreamTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { if ((w | h) == 0) { return; } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose); } -void StreamTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void StreamTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { if ((w | h) == 0) { return; } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, p_clip_uv); } bool StreamTexture2D::has_alpha() const { return false; } -Ref<Image> StreamTexture2D::get_data() const { +Ref<Image> StreamTexture2D::get_image() const { if (texture.is_valid()) { return RS::get_singleton()->texture_2d_get(texture); } else { @@ -693,7 +667,7 @@ Ref<Image> StreamTexture2D::get_data() const { bool StreamTexture2D::is_pixel_opaque(int p_x, int p_y) const { if (!alpha_cache.is_valid()) { - Ref<Image> img = get_data(); + Ref<Image> img = get_image(); if (img.is_valid()) { if (img->is_compressed()) { //must decompress, if compressed Ref<Image> decom = img->duplicate(); @@ -701,7 +675,7 @@ bool StreamTexture2D::is_pixel_opaque(int p_x, int p_y) const { img = decom; } - alpha_cache.instance(); + alpha_cache.instantiate(); alpha_cache->create_from_image_alpha(img); } } @@ -750,11 +724,7 @@ void StreamTexture2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); } -StreamTexture2D::StreamTexture2D() { - format = Image::FORMAT_MAX; - w = 0; - h = 0; -} +StreamTexture2D::StreamTexture2D() {} StreamTexture2D::~StreamTexture2D() { if (texture.is_valid()) { @@ -762,9 +732,9 @@ StreamTexture2D::~StreamTexture2D() { } } -RES ResourceFormatLoaderStreamTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoaderStreamTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { Ref<StreamTexture2D> st; - st.instance(); + st.instantiate(); Error err = st->load(p_path); if (r_error) { *r_error = err; @@ -913,7 +883,7 @@ Image::Format StreamTexture3D::get_format() const { Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps) { FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path)); uint8_t header[4]; f->get_buffer(header, 4); @@ -941,7 +911,7 @@ Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_da for (int i = 0; i < (r_depth + mipmaps); i++) { Ref<Image> image = StreamTexture2D::load_image_from_file(f, 0); - ERR_FAIL_COND_V(image.is_null() || image->empty(), ERR_CANT_OPEN); + ERR_FAIL_COND_V(image.is_null() || image->is_empty(), ERR_CANT_OPEN); if (i == 0) { r_format = image->get_format(); r_width = image->get_width(); @@ -985,7 +955,7 @@ Error StreamTexture3D::load(const String &p_path) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); } - _change_notify(); + notify_property_list_changed(); emit_changed(); return OK; } @@ -1050,13 +1020,7 @@ void StreamTexture3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); } -StreamTexture3D::StreamTexture3D() { - format = Image::FORMAT_MAX; - w = 0; - h = 0; - d = 0; - mipmaps = false; -} +StreamTexture3D::StreamTexture3D() {} StreamTexture3D::~StreamTexture3D() { if (texture.is_valid()) { @@ -1066,9 +1030,9 @@ StreamTexture3D::~StreamTexture3D() { ///////////////////////////// -RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { Ref<StreamTexture3D> st; - st.instance(); + st.instantiate(); Error err = st->load(p_path); if (r_error) { *r_error = err; @@ -1142,7 +1106,6 @@ void AtlasTexture::set_atlas(const Ref<Texture2D> &p_atlas) { } atlas = p_atlas; emit_changed(); - _change_notify("atlas"); } Ref<Texture2D> AtlasTexture::get_atlas() const { @@ -1155,7 +1118,6 @@ void AtlasTexture::set_region(const Rect2 &p_region) { } region = p_region; emit_changed(); - _change_notify("region"); } Rect2 AtlasTexture::get_region() const { @@ -1168,7 +1130,6 @@ void AtlasTexture::set_margin(const Rect2 &p_margin) { } margin = p_margin; emit_changed(); - _change_notify("margin"); } Rect2 AtlasTexture::get_margin() const { @@ -1178,7 +1139,6 @@ Rect2 AtlasTexture::get_margin() const { void AtlasTexture::set_filter_clip(const bool p_enable) { filter_clip = p_enable; emit_changed(); - _change_notify("filter_clip"); } bool AtlasTexture::has_filter_clip() const { @@ -1204,7 +1164,7 @@ void AtlasTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_clip"), "set_filter_clip", "has_filter_clip"); } -void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { if (!atlas.is_valid()) { return; } @@ -1219,12 +1179,10 @@ void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_m rc.size.height = atlas->get_height(); } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, filter_clip); } -void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { if (!atlas.is_valid()) { return; } @@ -1242,12 +1200,10 @@ void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile Vector2 scale = p_rect.size / (region.size + margin.size); Rect2 dr(p_rect.position + margin.position * scale, rc.size * scale); - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, filter_clip); } -void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { //this might not necessarily work well if using a rect, needs to be fixed properly if (!atlas.is_valid()) { return; @@ -1257,9 +1213,7 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons Rect2 src_c; get_rect_region(p_rect, p_src_rect, dr, src_c); - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, filter_clip); } bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -1276,7 +1230,7 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Vector2 scale = p_rect.size / src.size; src.position += (rc.position - margin.position); - Rect2 src_c = rc.clip(src); + Rect2 src_c = rc.intersection(src); if (src_c.size == Size2()) { return false; } @@ -1318,9 +1272,7 @@ bool AtlasTexture::is_pixel_opaque(int p_x, int p_y) const { return atlas->is_pixel_opaque(x, y); } -AtlasTexture::AtlasTexture() { - filter_clip = false; -} +AtlasTexture::AtlasTexture() {} ///////////////////////////////////////// @@ -1364,7 +1316,7 @@ Ref<Texture2D> MeshTexture::get_base_texture() const { return base_texture; } -void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { if (mesh.is_null() || base_texture.is_null()) { return; } @@ -1374,12 +1326,10 @@ void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_mo SWAP(xform.elements[0][1], xform.elements[1][0]); SWAP(xform.elements[0][0], xform.elements[1][1]); } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid()); } -void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { +void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { if (mesh.is_null() || base_texture.is_null()) { return; } @@ -1398,12 +1348,10 @@ void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, SWAP(xform.elements[0][1], xform.elements[1][0]); SWAP(xform.elements[0][0], xform.elements[1][1]); } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid()); } -void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { if (mesh.is_null() || base_texture.is_null()) { return; } @@ -1422,9 +1370,7 @@ void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const SWAP(xform.elements[0][1], xform.elements[1][0]); SWAP(xform.elements[0][0], xform.elements[1][1]); } - RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid()); } bool MeshTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -1455,283 +1401,341 @@ MeshTexture::MeshTexture() { ////////////////////////////////////////// -int LargeTexture::get_width() const { - return size.width; -} - -int LargeTexture::get_height() const { - return size.height; -} +void CurveTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); -RID LargeTexture::get_rid() const { - return RID(); -} + ClassDB::bind_method(D_METHOD("set_curve", "curve"), &CurveTexture::set_curve); + ClassDB::bind_method(D_METHOD("get_curve"), &CurveTexture::get_curve); -bool LargeTexture::has_alpha() const { - for (int i = 0; i < pieces.size(); i++) { - if (pieces[i].texture->has_alpha()) { - return true; - } - } + ClassDB::bind_method(D_METHOD("set_texture_mode", "texture_mode"), &CurveTexture::set_texture_mode); + ClassDB::bind_method(D_METHOD("get_texture_mode"), &CurveTexture::get_texture_mode); - return false; -} + ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update); -int LargeTexture::add_piece(const Point2 &p_offset, const Ref<Texture2D> &p_texture) { - ERR_FAIL_COND_V(p_texture.is_null(), -1); - Piece p; - p.offset = p_offset; - p.texture = p_texture; - pieces.push_back(p); + ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "RGB,Red"), "set_texture_mode", "get_texture_mode"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); - return pieces.size() - 1; + BIND_ENUM_CONSTANT(TEXTURE_MODE_RGB); + BIND_ENUM_CONSTANT(TEXTURE_MODE_RED); } -void LargeTexture::set_piece_offset(int p_idx, const Point2 &p_offset) { - ERR_FAIL_INDEX(p_idx, pieces.size()); - pieces.write[p_idx].offset = p_offset; -}; +void CurveTexture::set_width(int p_width) { + ERR_FAIL_COND(p_width < 32 || p_width > 4096); -void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture2D> &p_texture) { - ERR_FAIL_COND(p_texture == this); - ERR_FAIL_COND(p_texture.is_null()); - ERR_FAIL_INDEX(p_idx, pieces.size()); - pieces.write[p_idx].texture = p_texture; -}; + if (_width == p_width) { + return; + } -void LargeTexture::set_size(const Size2 &p_size) { - size = p_size; + _width = p_width; + _update(); } -void LargeTexture::clear() { - pieces.clear(); - size = Size2i(); +int CurveTexture::get_width() const { + return _width; } -Array LargeTexture::_get_data() const { - Array arr; - for (int i = 0; i < pieces.size(); i++) { - arr.push_back(pieces[i].offset); - arr.push_back(pieces[i].texture); +void CurveTexture::ensure_default_setup(float p_min, float p_max) { + if (_curve.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); + set_curve(curve); + // Min and max is 0..1 by default } - arr.push_back(Size2(size)); - return arr; } -void LargeTexture::_set_data(const Array &p_array) { - ERR_FAIL_COND(p_array.size() < 1); - ERR_FAIL_COND(!(p_array.size() & 1)); - clear(); - for (int i = 0; i < p_array.size() - 1; i += 2) { - add_piece(p_array[i], p_array[i + 1]); +void CurveTexture::set_curve(Ref<Curve> p_curve) { + if (_curve != p_curve) { + if (_curve.is_valid()) { + _curve->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveTexture::_update)); + } + _curve = p_curve; + if (_curve.is_valid()) { + _curve->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveTexture::_update)); + } + _update(); } - size = Size2(p_array[p_array.size() - 1]); } -int LargeTexture::get_piece_count() const { - return pieces.size(); -} +void CurveTexture::_update() { + Vector<uint8_t> data; + data.resize(_width * sizeof(float) * (texture_mode == TEXTURE_MODE_RGB ? 3 : 1)); -Vector2 LargeTexture::get_piece_offset(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, pieces.size(), Vector2()); - return pieces[p_idx].offset; -} + // The array is locked in that scope + { + uint8_t *wd8 = data.ptrw(); + float *wd = (float *)wd8; -Ref<Texture2D> LargeTexture::get_piece_texture(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, pieces.size(), Ref<Texture2D>()); - return pieces[p_idx].texture; -} + if (_curve.is_valid()) { + Curve &curve = **_curve; + for (int i = 0; i < _width; ++i) { + float t = i / static_cast<float>(_width); + if (texture_mode == TEXTURE_MODE_RGB) { + wd[i * 3 + 0] = curve.interpolate_baked(t); + wd[i * 3 + 1] = wd[i * 3 + 0]; + wd[i * 3 + 2] = wd[i * 3 + 0]; + } else { + wd[i] = curve.interpolate_baked(t); + } + } -Ref<Image> LargeTexture::to_image() const { - Ref<Image> img = memnew(Image(this->get_width(), this->get_height(), false, Image::FORMAT_RGBA8)); - for (int i = 0; i < pieces.size(); i++) { - Ref<Image> src_img = pieces[i].texture->get_data(); - img->blit_rect(src_img, Rect2(0, 0, src_img->get_width(), src_img->get_height()), pieces[i].offset); + } else { + for (int i = 0; i < _width; ++i) { + if (texture_mode == TEXTURE_MODE_RGB) { + wd[i * 3 + 0] = 0; + wd[i * 3 + 1] = 0; + wd[i * 3 + 2] = 0; + } else { + wd[i] = 0; + } + } + } } - return img; -} - -void LargeTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_piece", "ofs", "texture"), &LargeTexture::add_piece); - ClassDB::bind_method(D_METHOD("set_piece_offset", "idx", "ofs"), &LargeTexture::set_piece_offset); - ClassDB::bind_method(D_METHOD("set_piece_texture", "idx", "texture"), &LargeTexture::set_piece_texture); - ClassDB::bind_method(D_METHOD("set_size", "size"), &LargeTexture::set_size); - ClassDB::bind_method(D_METHOD("clear"), &LargeTexture::clear); + Ref<Image> image = memnew(Image(_width, 1, false, texture_mode == TEXTURE_MODE_RGB ? Image::FORMAT_RGBF : Image::FORMAT_RF, data)); - ClassDB::bind_method(D_METHOD("get_piece_count"), &LargeTexture::get_piece_count); - ClassDB::bind_method(D_METHOD("get_piece_offset", "idx"), &LargeTexture::get_piece_offset); - ClassDB::bind_method(D_METHOD("get_piece_texture", "idx"), &LargeTexture::get_piece_texture); - - ClassDB::bind_method(D_METHOD("_set_data", "data"), &LargeTexture::_set_data); - ClassDB::bind_method(D_METHOD("_get_data"), &LargeTexture::_get_data); + if (_texture.is_valid()) { + if (_current_texture_mode != texture_mode || _current_width != _width) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(_texture, new_texture); + } else { + RS::get_singleton()->texture_2d_update(_texture, image); + } + } else { + _texture = RS::get_singleton()->texture_2d_create(image); + } + _current_texture_mode = texture_mode; + _current_width = _width; - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + emit_changed(); } -void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { - for (int i = 0; i < pieces.size(); i++) { - // TODO - pieces[i].texture->draw(p_canvas_item, pieces[i].offset + p_pos, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, p_texture_filter, p_texture_repeat); - } +Ref<Curve> CurveTexture::get_curve() const { + return _curve; } -void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { - //tiling not supported for this - if (size.x == 0 || size.y == 0) { +void CurveTexture::set_texture_mode(TextureMode p_mode) { + if (texture_mode == p_mode) { return; } - - Size2 scale = p_rect.size / size; - - for (int i = 0; i < pieces.size(); i++) { - // TODO - pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.position, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, p_texture_filter, p_texture_repeat); - } + texture_mode = p_mode; + _update(); +} +CurveTexture::TextureMode CurveTexture::get_texture_mode() const { + return texture_mode; } -void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { - //tiling not supported for this - if (p_src_rect.size.x == 0 || p_src_rect.size.y == 0) { - return; - } - - Size2 scale = p_rect.size / p_src_rect.size; - - for (int i = 0; i < pieces.size(); i++) { - // TODO - Rect2 rect(pieces[i].offset, pieces[i].texture->get_size()); - if (!p_src_rect.intersects(rect)) { - continue; - } - Rect2 local = p_src_rect.clip(rect); - Rect2 target = local; - target.size *= scale; - target.position = p_rect.position + (p_src_rect.position + rect.position) * scale; - local.position -= rect.position; - pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, p_texture_filter, p_texture_repeat, false); +RID CurveTexture::get_rid() const { + if (!_texture.is_valid()) { + _texture = RS::get_singleton()->texture_2d_placeholder_create(); } + return _texture; } -bool LargeTexture::is_pixel_opaque(int p_x, int p_y) const { - for (int i = 0; i < pieces.size(); i++) { - // TODO - if (!pieces[i].texture.is_valid()) { - continue; - } +CurveTexture::CurveTexture() {} - Rect2 rect(pieces[i].offset, pieces[i].texture->get_size()); - if (rect.has_point(Point2(p_x, p_y))) { - return pieces[i].texture->is_pixel_opaque(p_x - rect.position.x, p_y - rect.position.y); - } +CurveTexture::~CurveTexture() { + if (_texture.is_valid()) { + RS::get_singleton()->free(_texture); } - - return true; } -LargeTexture::LargeTexture() { -} +////////////////// -/////////////////// +void CurveXYZTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveXYZTexture::set_width); -void CurveTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); + ClassDB::bind_method(D_METHOD("set_curve_x", "curve"), &CurveXYZTexture::set_curve_x); + ClassDB::bind_method(D_METHOD("get_curve_x"), &CurveXYZTexture::get_curve_x); - ClassDB::bind_method(D_METHOD("set_curve", "curve"), &CurveTexture::set_curve); - ClassDB::bind_method(D_METHOD("get_curve"), &CurveTexture::get_curve); + ClassDB::bind_method(D_METHOD("set_curve_y", "curve"), &CurveXYZTexture::set_curve_y); + ClassDB::bind_method(D_METHOD("get_curve_y"), &CurveXYZTexture::get_curve_y); - ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update); + ClassDB::bind_method(D_METHOD("set_curve_z", "curve"), &CurveXYZTexture::set_curve_z); + ClassDB::bind_method(D_METHOD("get_curve_z"), &CurveXYZTexture::get_curve_z); - ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); + ClassDB::bind_method(D_METHOD("_update"), &CurveXYZTexture::_update); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_x", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_x", "get_curve_x"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_y", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_y", "get_curve_y"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_z", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_z", "get_curve_z"); } -void CurveTexture::set_width(int p_width) { +void CurveXYZTexture::set_width(int p_width) { ERR_FAIL_COND(p_width < 32 || p_width > 4096); + + if (_width == p_width) { + return; + } + _width = p_width; _update(); } -int CurveTexture::get_width() const { +int CurveXYZTexture::get_width() const { return _width; } -void CurveTexture::ensure_default_setup(float p_min, float p_max) { - if (_curve.is_null()) { +void CurveXYZTexture::ensure_default_setup(float p_min, float p_max) { + if (_curve_x.is_null()) { Ref<Curve> curve = Ref<Curve>(memnew(Curve)); curve->add_point(Vector2(0, 1)); curve->add_point(Vector2(1, 1)); curve->set_min_value(p_min); curve->set_max_value(p_max); - set_curve(curve); - // Min and max is 0..1 by default + set_curve_x(curve); + } + + if (_curve_y.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); + set_curve_y(curve); + } + + if (_curve_z.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); + set_curve_z(curve); } } -void CurveTexture::set_curve(Ref<Curve> p_curve) { - if (_curve != p_curve) { - if (_curve.is_valid()) { - _curve->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveTexture::_update)); +void CurveXYZTexture::set_curve_x(Ref<Curve> p_curve) { + if (_curve_x != p_curve) { + if (_curve_x.is_valid()) { + _curve_x->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update)); } - _curve = p_curve; - if (_curve.is_valid()) { - _curve->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveTexture::_update)); + _curve_x = p_curve; + if (_curve_x.is_valid()) { + _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); } _update(); } } -void CurveTexture::_update() { +void CurveXYZTexture::set_curve_y(Ref<Curve> p_curve) { + if (_curve_y != p_curve) { + if (_curve_y.is_valid()) { + _curve_y->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update)); + } + _curve_y = p_curve; + if (_curve_y.is_valid()) { + _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); + } + _update(); + } +} + +void CurveXYZTexture::set_curve_z(Ref<Curve> p_curve) { + if (_curve_z != p_curve) { + if (_curve_z.is_valid()) { + _curve_z->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update)); + } + _curve_z = p_curve; + if (_curve_z.is_valid()) { + _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); + } + _update(); + } +} + +void CurveXYZTexture::_update() { Vector<uint8_t> data; - data.resize(_width * sizeof(float)); + data.resize(_width * sizeof(float) * 3); // The array is locked in that scope { uint8_t *wd8 = data.ptrw(); float *wd = (float *)wd8; - if (_curve.is_valid()) { - Curve &curve = **_curve; + if (_curve_x.is_valid()) { + Curve &curve_x = **_curve_x; + for (int i = 0; i < _width; ++i) { + float t = i / static_cast<float>(_width); + wd[i * 3 + 0] = curve_x.interpolate_baked(t); + } + + } else { + for (int i = 0; i < _width; ++i) { + wd[i * 3 + 0] = 0; + } + } + + if (_curve_y.is_valid()) { + Curve &curve_y = **_curve_y; + for (int i = 0; i < _width; ++i) { + float t = i / static_cast<float>(_width); + wd[i * 3 + 1] = curve_y.interpolate_baked(t); + } + + } else { + for (int i = 0; i < _width; ++i) { + wd[i * 3 + 1] = 0; + } + } + + if (_curve_z.is_valid()) { + Curve &curve_z = **_curve_z; for (int i = 0; i < _width; ++i) { float t = i / static_cast<float>(_width); - wd[i] = curve.interpolate_baked(t); + wd[i * 3 + 2] = curve_z.interpolate_baked(t); } } else { for (int i = 0; i < _width; ++i) { - wd[i] = 0; + wd[i * 3 + 2] = 0; } } } - Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data)); + Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RGBF, data)); if (_texture.is_valid()) { - RID new_texture = RS::get_singleton()->texture_2d_create(image); - RS::get_singleton()->texture_replace(_texture, new_texture); + if (_current_width != _width) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(_texture, new_texture); + } else { + RS::get_singleton()->texture_2d_update(_texture, image); + } } else { _texture = RS::get_singleton()->texture_2d_create(image); } + _current_width = _width; emit_changed(); } -Ref<Curve> CurveTexture::get_curve() const { - return _curve; +Ref<Curve> CurveXYZTexture::get_curve_x() const { + return _curve_x; } -RID CurveTexture::get_rid() const { +Ref<Curve> CurveXYZTexture::get_curve_y() const { + return _curve_y; +} + +Ref<Curve> CurveXYZTexture::get_curve_z() const { + return _curve_z; +} + +RID CurveXYZTexture::get_rid() const { if (!_texture.is_valid()) { _texture = RS::get_singleton()->texture_2d_placeholder_create(); } return _texture; } -CurveTexture::CurveTexture() { - _width = 2048; -} +CurveXYZTexture::CurveXYZTexture() {} -CurveTexture::~CurveTexture() { +CurveXYZTexture::~CurveXYZTexture() { if (_texture.is_valid()) { RS::get_singleton()->free(_texture); } @@ -1739,16 +1743,7 @@ CurveTexture::~CurveTexture() { ////////////////// -//setter and getter names for property serialization -#define COLOR_RAMP_GET_OFFSETS "get_offsets" -#define COLOR_RAMP_GET_COLORS "get_colors" -#define COLOR_RAMP_SET_OFFSETS "set_offsets" -#define COLOR_RAMP_SET_COLORS "set_colors" - GradientTexture::GradientTexture() { - update_pending = false; - width = 2048; - _queue_update(); } @@ -1763,11 +1758,16 @@ void GradientTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_gradient"), &GradientTexture::get_gradient); ClassDB::bind_method(D_METHOD("set_width", "width"), &GradientTexture::set_width); + // The `get_width()` method is already exposed by the parent class Texture2D. + + ClassDB::bind_method(D_METHOD("set_use_hdr", "enabled"), &GradientTexture::set_use_hdr); + ClassDB::bind_method(D_METHOD("is_using_hdr"), &GradientTexture::is_using_hdr); ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr"); } void GradientTexture::set_gradient(Ref<Gradient> p_gradient) { @@ -1795,7 +1795,7 @@ void GradientTexture::_queue_update() { } update_pending = true; - call_deferred("_update"); + call_deferred(SNAME("_update")); } void GradientTexture::_update() { @@ -1805,36 +1805,56 @@ void GradientTexture::_update() { return; } - Vector<uint8_t> data; - data.resize(width * 4); - { - uint8_t *wd8 = data.ptrw(); + if (use_hdr) { + // High dynamic range. + Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBAF)); Gradient &g = **gradient; - + // `create()` isn't available for non-uint8_t data, so fill in the data manually. for (int i = 0; i < width; i++) { float ofs = float(i) / (width - 1); - Color color = g.get_color_at_offset(ofs); + image->set_pixel(i, 0, g.get_color_at_offset(ofs)); + } - wd8[i * 4 + 0] = uint8_t(CLAMP(color.r * 255.0, 0, 255)); - wd8[i * 4 + 1] = uint8_t(CLAMP(color.g * 255.0, 0, 255)); - wd8[i * 4 + 2] = uint8_t(CLAMP(color.b * 255.0, 0, 255)); - wd8[i * 4 + 3] = uint8_t(CLAMP(color.a * 255.0, 0, 255)); + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_2d_create(image); + } + } else { + // Low dynamic range. "Overbright" colors will be clamped. + Vector<uint8_t> data; + data.resize(width * 4); + { + uint8_t *wd8 = data.ptrw(); + Gradient &g = **gradient; + + for (int i = 0; i < width; i++) { + float ofs = float(i) / (width - 1); + Color color = g.get_color_at_offset(ofs); + + wd8[i * 4 + 0] = uint8_t(CLAMP(color.r * 255.0, 0, 255)); + wd8[i * 4 + 1] = uint8_t(CLAMP(color.g * 255.0, 0, 255)); + wd8[i * 4 + 2] = uint8_t(CLAMP(color.b * 255.0, 0, 255)); + wd8[i * 4 + 3] = uint8_t(CLAMP(color.a * 255.0, 0, 255)); + } } - } - Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data)); + Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data)); - if (texture.is_valid()) { - RID new_texture = RS::get_singleton()->texture_2d_create(image); - RS::get_singleton()->texture_replace(texture, new_texture); - } else { - texture = RS::get_singleton()->texture_2d_create(image); + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_2d_create(image); + } } emit_changed(); } void GradientTexture::set_width(int p_width) { + ERR_FAIL_COND(p_width <= 0); width = p_width; _queue_update(); } @@ -1843,7 +1863,20 @@ int GradientTexture::get_width() const { return width; } -Ref<Image> GradientTexture::get_data() const { +void GradientTexture::set_use_hdr(bool p_enabled) { + if (p_enabled == use_hdr) { + return; + } + + use_hdr = p_enabled; + _queue_update(); +} + +bool GradientTexture::is_using_hdr() const { + return use_hdr; +} + +Ref<Image> GradientTexture::get_image() const { if (!texture.is_valid()) { return Ref<Image>(); } @@ -1961,7 +1994,7 @@ void AnimatedTexture::_update_proxy() { } } time -= frame_limit; - _change_notify("current_frame"); + } else { break; } @@ -2092,14 +2125,14 @@ bool AnimatedTexture::has_alpha() const { return frames[current_frame].texture->has_alpha(); } -Ref<Image> AnimatedTexture::get_data() const { +Ref<Image> AnimatedTexture::get_image() const { RWLockRead r(rw_lock); if (!frames[current_frame].texture.is_valid()) { return Ref<Image>(); } - return frames[current_frame].texture->get_data(); + return frames[current_frame].texture->get_image(); } bool AnimatedTexture::is_pixel_opaque(int p_x, int p_y) const { @@ -2116,7 +2149,7 @@ void AnimatedTexture::_validate_property(PropertyInfo &property) const { if (prop.begins_with("frame_")) { int frame = prop.get_slicec('/', 0).get_slicec('_', 1).to_int(); if (frame >= frame_count) { - property.usage = 0; + property.usage = PROPERTY_USAGE_NONE; } } } @@ -2144,7 +2177,7 @@ void AnimatedTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_frame_delay", "frame"), &AnimatedTexture::get_frame_delay); ADD_PROPERTY(PropertyInfo(Variant::INT, "frames", PROPERTY_HINT_RANGE, "1," + itos(MAX_FRAMES), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_frames", "get_frames"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "current_frame", PROPERTY_HINT_NONE, "", 0), "set_current_frame", "get_current_frame"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "current_frame", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_frame", "get_current_frame"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pause"), "set_pause", "get_pause"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "oneshot"), "set_oneshot", "get_oneshot"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fps", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_fps", "get_fps"); @@ -2163,28 +2196,12 @@ AnimatedTexture::AnimatedTexture() { proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); RenderingServer::get_singleton()->texture_set_force_redraw_if_visible(proxy, true); - time = 0; - frame_count = 1; - fps = 4; - prev_ticks = 0; - current_frame = 0; - pause = false; - oneshot = false; RenderingServer::get_singleton()->connect("frame_pre_draw", callable_mp(this, &AnimatedTexture::_update_proxy)); - -#ifndef NO_THREADS - rw_lock = RWLock::create(); -#else - rw_lock = nullptr; -#endif } AnimatedTexture::~AnimatedTexture() { RS::get_singleton()->free(proxy); RS::get_singleton()->free(proxy_ph); - if (rw_lock) { - memdelete(rw_lock); - } } /////////////////////////////// @@ -2258,7 +2275,7 @@ Error ImageTextureLayered::create_from_images(Vector<Ref<Image>> p_images) { "Cubemap array layers must be a multiple of 6"); } - ERR_FAIL_COND_V(p_images[0].is_null() || p_images[0]->empty(), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(p_images[0].is_null() || p_images[0]->is_empty(), ERR_INVALID_PARAMETER); Image::Format new_format = p_images[0]->get_format(); int new_width = p_images[0]->get_width(); @@ -2332,11 +2349,6 @@ void ImageTextureLayered::_bind_methods() { ImageTextureLayered::ImageTextureLayered(LayeredType p_layered_type) { layered_type = p_layered_type; - format = Image::FORMAT_MAX; - - width = 0; - height = 0; - layers = 0; } ImageTextureLayered::~ImageTextureLayered() { @@ -2363,7 +2375,7 @@ Error StreamTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> ERR_FAIL_COND_V(images.size() != 0, ERR_INVALID_PARAMETER); FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path)); uint8_t header[4]; f->get_buffer(header, 4); @@ -2396,7 +2408,7 @@ Error StreamTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> for (uint32_t i = 0; i < layer_count; i++) { Ref<Image> image = StreamTexture2D::load_image_from_file(f, p_size_limit); - ERR_FAIL_COND_V(image.is_null() || image->empty(), ERR_CANT_OPEN); + ERR_FAIL_COND_V(image.is_null() || image->is_empty(), ERR_CANT_OPEN); images.write[i] = image; } @@ -2433,7 +2445,7 @@ Error StreamTextureLayered::load(const String &p_path) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); } - _change_notify(); + notify_property_list_changed(); emit_changed(); return OK; } @@ -2504,11 +2516,6 @@ void StreamTextureLayered::_bind_methods() { StreamTextureLayered::StreamTextureLayered(LayeredType p_type) { layered_type = p_type; - format = Image::FORMAT_MAX; - w = 0; - h = 0; - layers = 0; - mipmaps = false; } StreamTextureLayered::~StreamTextureLayered() { @@ -2519,19 +2526,19 @@ StreamTextureLayered::~StreamTextureLayered() { ///////////////////////////////////////////////// -RES ResourceFormatLoaderStreamTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoaderStreamTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { Ref<StreamTextureLayered> st; if (p_path.get_extension().to_lower() == "stexarray") { Ref<StreamTexture2DArray> s; - s.instance(); + s.instantiate(); st = s; } else if (p_path.get_extension().to_lower() == "scube") { Ref<StreamCubemap> s; - s.instance(); + s.instantiate(); st = s; } else if (p_path.get_extension().to_lower() == "scubearray") { Ref<StreamCubemapArray> s; - s.instance(); + s.instantiate(); st = s; } else { if (r_error) { @@ -2617,7 +2624,10 @@ RID CameraTexture::get_rid() const { if (feed.is_valid()) { return feed->get_texture(which_feed); } else { - return RID(); + if (_texture.is_null()) { + _texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + } + return _texture; } } @@ -2630,14 +2640,14 @@ uint32_t CameraTexture::get_flags() const { return 0; } -Ref<Image> CameraTexture::get_data() const { +Ref<Image> CameraTexture::get_image() const { // not (yet) supported return Ref<Image>(); } void CameraTexture::set_camera_feed_id(int p_new_id) { camera_feed_id = p_new_id; - _change_notify(); + notify_property_list_changed(); } int CameraTexture::get_camera_feed_id() const { @@ -2646,7 +2656,7 @@ int CameraTexture::get_camera_feed_id() const { void CameraTexture::set_which_feed(CameraServer::FeedImage p_which) { which_feed = p_which; - _change_notify(); + notify_property_list_changed(); } CameraServer::FeedImage CameraTexture::get_which_feed() const { @@ -2657,7 +2667,7 @@ void CameraTexture::set_camera_active(bool p_active) { Ref<CameraFeed> feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id); if (feed.is_valid()) { feed->set_active(p_active); - _change_notify(); + notify_property_list_changed(); } } @@ -2670,11 +2680,10 @@ bool CameraTexture::get_camera_active() const { } } -CameraTexture::CameraTexture() { - camera_feed_id = 0; - which_feed = CameraServer::FEED_RGBA_IMAGE; -} +CameraTexture::CameraTexture() {} CameraTexture::~CameraTexture() { - // nothing to do here yet + if (_texture.is_valid()) { + RenderingServer::get_singleton()->free(_texture); + } } |