From 484c5b5aff6e513a92baf5d3ddcae8bc8941ee26 Mon Sep 17 00:00:00 2001 From: Mika Viskari Date: Fri, 24 Nov 2023 18:47:55 +0200 Subject: [PATCH] Fix invalid frame index when Sprite2D's hframes or vframes has been changed --- doc/classes/Sprite2D.xml | 6 +++--- doc/classes/Sprite3D.xml | 6 +++--- scene/2d/sprite_2d.cpp | 17 +++++++++++++++++ scene/3d/sprite_3d.cpp | 21 +++++++++++++++++++-- 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/doc/classes/Sprite2D.xml b/doc/classes/Sprite2D.xml index 8eb9e26a838..f8622d8f386 100644 --- a/doc/classes/Sprite2D.xml +++ b/doc/classes/Sprite2D.xml @@ -60,13 +60,13 @@ If [code]true[/code], texture is flipped vertically. - Current frame to display from sprite sheet. [member hframes] or [member vframes] must be greater than 1. + Current frame to display from sprite sheet. [member hframes] or [member vframes] must be greater than 1. This property is automatically adjusted when [member hframes] or [member vframes] are changed to keep pointing to the same visual frame (same column and row). If that's impossible, this value is reset to [code]0[/code]. Coordinates of the frame to display from sprite sheet. This is as an alias for the [member frame] property. [member hframes] or [member vframes] must be greater than 1. - The number of columns in the sprite sheet. + The number of columns in the sprite sheet. When this property is changed, [member frame] is adjusted so that the same visual frame is maintained (same row and column). If that's impossible, [member frame] is reset to [code]0[/code]. The texture's drawing offset. @@ -84,7 +84,7 @@ [Texture2D] object to draw. - The number of rows in the sprite sheet. + The number of rows in the sprite sheet. When this property is changed, [member frame] is adjusted so that the same visual frame is maintained (same row and column). If that's impossible, [member frame] is reset to [code]0[/code]. diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml index 9733c5f48a2..4b4421aeba7 100644 --- a/doc/classes/Sprite3D.xml +++ b/doc/classes/Sprite3D.xml @@ -10,13 +10,13 @@ - Current frame to display from sprite sheet. [member hframes] or [member vframes] must be greater than 1. + Current frame to display from sprite sheet. [member hframes] or [member vframes] must be greater than 1. This property is automatically adjusted when [member hframes] or [member vframes] are changed to keep pointing to the same visual frame (same column and row). If that's impossible, this value is reset to [code]0[/code]. Coordinates of the frame to display from sprite sheet. This is as an alias for the [member frame] property. [member hframes] or [member vframes] must be greater than 1. - The number of columns in the sprite sheet. + The number of columns in the sprite sheet. When this property is changed, [member frame] is adjusted so that the same visual frame is maintained (same row and column). If that's impossible, [member frame] is reset to [code]0[/code]. If [code]true[/code], the sprite will use [member region_rect] and display only the specified part of its texture. @@ -28,7 +28,7 @@ [Texture2D] object to draw. If [member GeometryInstance3D.material_override] is used, this will be overridden. The size information is still used. - The number of rows in the sprite sheet. + The number of rows in the sprite sheet. When this property is changed, [member frame] is adjusted so that the same visual frame is maintained (same row and column). If that's impossible, [member frame] is reset to [code]0[/code]. diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index 7e6b43559ca..6d0a2968d79 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -261,6 +261,9 @@ Vector2i Sprite2D::get_frame_coords() const { void Sprite2D::set_vframes(int p_amount) { ERR_FAIL_COND_MSG(p_amount < 1, "Amount of vframes cannot be smaller than 1."); vframes = p_amount; + if (frame >= vframes * hframes) { + frame = 0; + } queue_redraw(); item_rect_changed(); notify_property_list_changed(); @@ -272,7 +275,21 @@ int Sprite2D::get_vframes() const { void Sprite2D::set_hframes(int p_amount) { ERR_FAIL_COND_MSG(p_amount < 1, "Amount of hframes cannot be smaller than 1."); + if (vframes > 1) { + // Adjust the frame to fit new sheet dimensions. + int original_column = frame % hframes; + if (original_column >= p_amount) { + // Frame's column was dropped, reset. + frame = 0; + } else { + int original_row = frame / hframes; + frame = original_row * p_amount + original_column; + } + } hframes = p_amount; + if (frame >= vframes * hframes) { + frame = 0; + } queue_redraw(); item_rect_changed(); notify_property_list_changed(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 920cf22b837..ffd328c37e8 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -804,8 +804,11 @@ Vector2i Sprite3D::get_frame_coords() const { } void Sprite3D::set_vframes(int p_amount) { - ERR_FAIL_COND(p_amount < 1); + ERR_FAIL_COND_MSG(p_amount < 1, "Amount of vframes cannot be smaller than 1."); vframes = p_amount; + if (frame >= vframes * hframes) { + frame = 0; + } _queue_redraw(); notify_property_list_changed(); } @@ -815,8 +818,22 @@ int Sprite3D::get_vframes() const { } void Sprite3D::set_hframes(int p_amount) { - ERR_FAIL_COND(p_amount < 1); + ERR_FAIL_COND_MSG(p_amount < 1, "Amount of hframes cannot be smaller than 1."); + if (vframes > 1) { + // Adjust the frame to fit new sheet dimensions. + int original_column = frame % hframes; + if (original_column >= p_amount) { + // Frame's column was dropped, reset. + frame = 0; + } else { + int original_row = frame / hframes; + frame = original_row * p_amount + original_column; + } + } hframes = p_amount; + if (frame >= vframes * hframes) { + frame = 0; + } _queue_redraw(); notify_property_list_changed(); }