fix asymmetrical 9-slicing (#14148)

# Objective

Fixes #14147.

## Solution

Modify the slicing checks and algorithm to fully allow asymmetrical
textures to work.
Some opinionated code cleanup.

## Testing

Tested using the ui_texture_slice example and a custom asymmetrical
texture.

Before:

![asymmetrical_texture_slice_before](https://github.com/bevyengine/bevy/assets/88861660/00dafce1-904a-41ac-b5d9-faaf087b0681)

After:

![asymmetrical_texture_slice_after](https://github.com/bevyengine/bevy/assets/88861660/f3d742f3-6157-4d35-b383-aee4b8f6e7d0)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
JJJimbo1 2024-08-01 15:03:23 -05:00 committed by GitHub
parent 4c4a6c4506
commit 56c9d4489b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -126,11 +126,11 @@ impl TextureSlicer {
), ),
}, },
draw_size: vec2( draw_size: vec2(
bl_corner.draw_size.x, tl_corner.draw_size.x,
render_size.y - (bl_corner.draw_size.y + tl_corner.draw_size.y), render_size.y - (tl_corner.draw_size.y + bl_corner.draw_size.y),
), ),
offset: vec2( offset: vec2(
-render_size.x + bl_corner.draw_size.x, tl_corner.draw_size.x - render_size.x,
bl_corner.draw_size.y - tl_corner.draw_size.y, bl_corner.draw_size.y - tl_corner.draw_size.y,
) / 2.0, ) / 2.0,
}, },
@ -141,21 +141,21 @@ impl TextureSlicer {
base_rect.max.x - self.border.right, base_rect.max.x - self.border.right,
base_rect.min.y + self.border.top, base_rect.min.y + self.border.top,
), ),
max: vec2(base_rect.max.x, base_rect.max.y - self.border.bottom), max: base_rect.max - vec2(0.0, self.border.bottom),
}, },
draw_size: vec2( draw_size: vec2(
br_corner.draw_size.x, tr_corner.draw_size.x,
render_size.y - (br_corner.draw_size.y + tr_corner.draw_size.y), render_size.y - (tr_corner.draw_size.y + br_corner.draw_size.y),
), ),
offset: vec2( offset: vec2(
render_size.x - br_corner.draw_size.x, render_size.x - tr_corner.draw_size.x,
br_corner.draw_size.y - tr_corner.draw_size.y, br_corner.draw_size.y - tr_corner.draw_size.y,
) / 2.0, ) / 2.0,
}, },
] ]
} }
/// Computes the 2 vertical side slices (bottom and top borders) /// Computes the 2 vertical side slices (top and bottom borders)
#[must_use] #[must_use]
fn vertical_side_slices( fn vertical_side_slices(
&self, &self,
@ -164,24 +164,6 @@ impl TextureSlicer {
render_size: Vec2, render_size: Vec2,
) -> [TextureSlice; 2] { ) -> [TextureSlice; 2] {
[ [
// Bottom
TextureSlice {
texture_rect: Rect {
min: vec2(
base_rect.min.x + self.border.left,
base_rect.max.y - self.border.bottom,
),
max: vec2(base_rect.max.x - self.border.right, base_rect.max.y),
},
draw_size: vec2(
render_size.x - (bl_corner.draw_size.x + br_corner.draw_size.x),
bl_corner.draw_size.y,
),
offset: vec2(
(bl_corner.draw_size.x - br_corner.draw_size.x) / 2.0,
bl_corner.offset.y,
),
},
// Top // Top
TextureSlice { TextureSlice {
texture_rect: Rect { texture_rect: Rect {
@ -196,9 +178,27 @@ impl TextureSlicer {
tl_corner.draw_size.y, tl_corner.draw_size.y,
), ),
offset: vec2( offset: vec2(
(tl_corner.draw_size.x - tr_corner.draw_size.x) / 2.0, tl_corner.draw_size.x - tr_corner.draw_size.x,
tl_corner.offset.y, render_size.y - tl_corner.draw_size.y,
) / 2.0,
},
// Bottom
TextureSlice {
texture_rect: Rect {
min: vec2(
base_rect.min.x + self.border.left,
base_rect.max.y - self.border.bottom,
),
max: base_rect.max - vec2(self.border.right, 0.0),
},
draw_size: vec2(
render_size.x - (bl_corner.draw_size.x + br_corner.draw_size.x),
bl_corner.draw_size.y,
), ),
offset: vec2(
bl_corner.draw_size.x - br_corner.draw_size.x,
bl_corner.draw_size.y - render_size.y,
) / 2.0,
}, },
] ]
} }
@ -216,11 +216,8 @@ impl TextureSlicer {
#[must_use] #[must_use]
pub fn compute_slices(&self, rect: Rect, render_size: Option<Vec2>) -> Vec<TextureSlice> { pub fn compute_slices(&self, rect: Rect, render_size: Option<Vec2>) -> Vec<TextureSlice> {
let render_size = render_size.unwrap_or_else(|| rect.size()); let render_size = render_size.unwrap_or_else(|| rect.size());
let rect_size = rect.size() / 2.0; if self.border.left + self.border.right >= rect.size().x
if self.border.left >= rect_size.x || self.border.top + self.border.bottom >= rect.size().y
|| self.border.right >= rect_size.x
|| self.border.top >= rect_size.y
|| self.border.bottom >= rect_size.y
{ {
bevy_utils::tracing::error!( bevy_utils::tracing::error!(
"TextureSlicer::border has out of bounds values. No slicing will be applied" "TextureSlicer::border has out of bounds values. No slicing will be applied"
@ -234,7 +231,7 @@ impl TextureSlicer {
let mut slices = Vec::with_capacity(9); let mut slices = Vec::with_capacity(9);
// Corners are in this order: [TL, TR, BL, BR] // Corners are in this order: [TL, TR, BL, BR]
let corners = self.corner_slices(rect, render_size); let corners = self.corner_slices(rect, render_size);
// Vertical Sides: [B, T] // Vertical Sides: [T, B]
let vertical_sides = self.vertical_side_slices(&corners, rect, render_size); let vertical_sides = self.vertical_side_slices(&corners, rect, render_size);
// Horizontal Sides: [L, R] // Horizontal Sides: [L, R]
let horizontal_sides = self.horizontal_side_slices(&corners, rect, render_size); let horizontal_sides = self.horizontal_side_slices(&corners, rect, render_size);
@ -242,19 +239,13 @@ impl TextureSlicer {
let center = TextureSlice { let center = TextureSlice {
texture_rect: Rect { texture_rect: Rect {
min: rect.min + vec2(self.border.left, self.border.top), min: rect.min + vec2(self.border.left, self.border.top),
max: vec2( max: rect.max - vec2(self.border.right, self.border.bottom),
rect.max.x - self.border.right,
rect.max.y - self.border.bottom,
),
}, },
draw_size: vec2( draw_size: vec2(
render_size.x - (corners[2].draw_size.x + corners[3].draw_size.x), render_size.x - (corners[0].draw_size.x + corners[1].draw_size.x),
render_size.y - (corners[2].draw_size.y + corners[0].draw_size.y), render_size.y - (corners[0].draw_size.y + corners[2].draw_size.y),
),
offset: Vec2::new(
(corners[0].draw_size.x - corners[3].draw_size.x) / 2.0,
(corners[2].draw_size.y - corners[0].draw_size.y) / 2.0,
), ),
offset: vec2(vertical_sides[0].offset.x, horizontal_sides[0].offset.y),
}; };
slices.extend(corners); slices.extend(corners);
@ -399,7 +390,7 @@ mod test {
} }
); );
assert_eq!( assert_eq!(
vertical_sides[1], /* top */ vertical_sides[0], /* top */
TextureSlice { TextureSlice {
texture_rect: Rect { texture_rect: Rect {
min: Vec2::new(5.0, 0.0), min: Vec2::new(5.0, 0.0),