From 43b6205887605c7ac2ac79d4bf9306fb143abc80 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Sat, 6 May 2023 08:44:24 +0100 Subject: [PATCH] Multirect - Fix refining regions for all derived Textures Fixes allowing all derived texture types to modify region prior to rendering. --- scene/2d/tile_map.cpp | 29 +++++++++++++++++++++-------- scene/resources/texture.cpp | 31 +++++++++++++++---------------- scene/resources/texture.h | 14 ++++++++++++-- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 8eb30f8e408..fabcf5bbb6f 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -565,17 +565,30 @@ void TileMap::update_dirty_quadrants() { Ref normal_map = tile_set->tile_get_normal_map(c.id); Color modulate = tile_set->tile_get_modulate(c.id) * get_self_modulate(); + if (r == Rect2()) { tex->draw_rect(canvas_item, rect, false, modulate, c.transpose, normal_map); } else { - Rect2 dst_rect; - Rect2 src_rect; - if (tex->get_combined_rect_region(rect, r, dst_rect, src_rect)) { - if (!multirect_started) { - multirect_started = true; - VisualServerCanvasHelper::tilemap_begin(); - } - VisualServerCanvasHelper::tilemap_add_rect(canvas_item, dst_rect, tex->get_rid(), src_rect, modulate, c.transpose, normal_map.is_valid() ? normal_map->get_rid() : RID(), clip_uv); + Texture::RefineRectResult res = tex->refine_rect_region(rect, r); + switch (res) { + case Texture::REFINE_RECT_RESULT_DRAW: { + if (!multirect_started) { + multirect_started = true; + VisualServerCanvasHelper::tilemap_begin(); + } + VisualServerCanvasHelper::tilemap_add_rect(canvas_item, rect, tex->get_rid(), r, modulate, c.transpose, normal_map.is_valid() ? normal_map->get_rid() : RID(), clip_uv); + } break; + case Texture::REFINE_RECT_RESULT_FALLBACK: { + if (multirect_started) { + // If we are currently writing a multirect, we must flush + // to ensure there are no issues due to overlap. + VisualServerCanvasHelper::tilemap_end(); + multirect_started = false; + } + tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map, clip_uv); + } break; + default: { + } break; } } diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index b9d8939a287..c55172501fa 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -66,10 +66,6 @@ bool Texture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect return true; } -bool Texture::get_combined_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_combined_rect, Rect2 &r_combined_src_rect) const { - return get_rect_region(p_rect, p_src_rect, r_combined_rect, r_combined_src_rect); -} - void Texture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_width"), &Texture::get_width); ClassDB::bind_method(D_METHOD("get_height"), &Texture::get_height); @@ -1032,6 +1028,21 @@ void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile atlas->draw_rect_region(p_canvas_item, dr, rc, p_modulate, p_transpose, p_normal_map); } + +Texture::RefineRectResult AtlasTexture::refine_rect_region(Rect2 &r_dst_rect, Rect2 &r_src_rect) const { + if (!atlas.is_valid()) { + return REFINE_RECT_RESULT_NO_DRAW; + } + Rect2 temp_rect = r_dst_rect; + Rect2 temp_src_rect = r_src_rect; + + if (get_rect_region(temp_rect, temp_src_rect, r_dst_rect, r_src_rect)) { + return atlas->refine_rect_region(r_dst_rect, r_src_rect); + } + + return REFINE_RECT_RESULT_NO_DRAW; +} + 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 &p_normal_map, bool p_clip_uv) const { if (!atlas.is_valid()) { return; @@ -1074,18 +1085,6 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, return true; } -bool AtlasTexture::get_combined_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_combined_rect, Rect2 &r_combined_src_rect) const { - if (!atlas.is_valid()) { - return false; - } - Rect2 dst; - Rect2 src; - if (get_rect_region(p_rect, p_src_rect, dst, src)) { - return atlas->get_combined_rect_region(dst, src, r_combined_rect, r_combined_src_rect); - } - return false; -} - bool AtlasTexture::is_pixel_opaque(int p_x, int p_y) const { if (!atlas.is_valid()) { return true; diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 82bab6f30c6..a9fad1a16a7 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -61,6 +61,12 @@ public: FLAG_MIRRORED_REPEAT = VisualServer::TEXTURE_FLAG_MIRRORED_REPEAT }; + enum RefineRectResult { + REFINE_RECT_RESULT_DRAW, + REFINE_RECT_RESULT_FALLBACK, + REFINE_RECT_RESULT_NO_DRAW, + }; + virtual int get_width() const = 0; virtual int get_height() const = 0; virtual Size2 get_size() const; @@ -77,7 +83,7 @@ public: virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; - virtual bool get_combined_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_combined_rect, Rect2 &r_combined_src_rect) const; + virtual RefineRectResult refine_rect_region(Rect2 &r_dst_rect, Rect2 &r_src_rect) const { return REFINE_RECT_RESULT_DRAW; } virtual Ref get_data() const { return Ref(); } @@ -145,6 +151,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), bool p_clip_uv = true) const; + virtual RefineRectResult refine_rect_region(Rect2 &r_dst_rect, Rect2 &r_src_rect) const { return ((w | h) == 0) ? REFINE_RECT_RESULT_NO_DRAW : REFINE_RECT_RESULT_DRAW; } void set_storage(Storage p_storage); Storage get_storage() const; @@ -216,6 +223,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), bool p_clip_uv = true) const; + virtual RefineRectResult refine_rect_region(Rect2 &r_dst_rect, Rect2 &r_src_rect) const { return ((w | h) == 0) ? REFINE_RECT_RESULT_NO_DRAW : REFINE_RECT_RESULT_DRAW; } virtual bool has_alpha() const; virtual void set_flags(uint32_t p_flags); @@ -277,7 +285,7 @@ public: virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; - virtual bool get_combined_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_combined_rect, Rect2 &r_combined_src_rect) const; + virtual RefineRectResult refine_rect_region(Rect2 &r_dst_rect, Rect2 &r_src_rect) const; bool is_pixel_opaque(int p_x, int p_y) const; @@ -319,6 +327,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), bool p_clip_uv = true) const; + virtual RefineRectResult refine_rect_region(Rect2 &r_dst_rect, Rect2 &r_src_rect) const { return REFINE_RECT_RESULT_FALLBACK; } bool is_pixel_opaque(int p_x, int p_y) const; @@ -367,6 +376,7 @@ public: virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref()) const; virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), bool p_clip_uv = true) const; + virtual RefineRectResult refine_rect_region(Rect2 &r_dst_rect, Rect2 &r_src_rect) const { return REFINE_RECT_RESULT_FALLBACK; } bool is_pixel_opaque(int p_x, int p_y) const;