From 0c64841620863786e3a0b3c0b021652882781447 Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Tue, 18 Jun 2024 19:59:30 -0400 Subject: [PATCH 1/4] hack: Almost working. --- crates/bevy_sprite/src/texture_slice/mod.rs | 2 +- .../bevy_sprite/src/texture_slice/slicer.rs | 130 +++++++++++++++++- 2 files changed, 126 insertions(+), 6 deletions(-) diff --git a/crates/bevy_sprite/src/texture_slice/mod.rs b/crates/bevy_sprite/src/texture_slice/mod.rs index 4cb6f3e2de2e1..2dea51adc6d41 100644 --- a/crates/bevy_sprite/src/texture_slice/mod.rs +++ b/crates/bevy_sprite/src/texture_slice/mod.rs @@ -11,7 +11,7 @@ pub(crate) use computed_slices::{ }; /// Single texture slice, representing a texture rect to draw in a given area -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct TextureSlice { /// texture area to draw pub texture_rect: Rect, diff --git a/crates/bevy_sprite/src/texture_slice/slicer.rs b/crates/bevy_sprite/src/texture_slice/slicer.rs index d930aab705d12..86f463bece4f7 100644 --- a/crates/bevy_sprite/src/texture_slice/slicer.rs +++ b/crates/bevy_sprite/src/texture_slice/slicer.rs @@ -129,7 +129,7 @@ impl TextureSlicer { bl_corner.draw_size.x, render_size.y - bl_corner.draw_size.y - tl_corner.draw_size.y, ), - offset: vec2(-render_size.x + bl_corner.draw_size.x, 0.0) / 2.0, + offset: vec2(-render_size.x + bl_corner.draw_size.x, bl_corner.draw_size.y - tl_corner.draw_size.y) / 2.0 }, // right TextureSlice { @@ -144,7 +144,7 @@ impl TextureSlicer { br_corner.draw_size.x, render_size.y - (br_corner.draw_size.y + tr_corner.draw_size.y), ), - offset: vec2(render_size.x - br_corner.draw_size.x, 0.0) / 2.0, + offset: vec2(render_size.x - br_corner.draw_size.x, br_corner.draw_size.y - tr_corner.draw_size.y) / 2.0, }, ] } @@ -171,7 +171,7 @@ impl TextureSlicer { render_size.x - (bl_corner.draw_size.x + br_corner.draw_size.x), bl_corner.draw_size.y, ), - offset: vec2(0.0, bl_corner.offset.y), + offset: vec2((bl_corner.draw_size.x - br_corner.draw_size.x) / 2.0, bl_corner.offset.y), }, // Top TextureSlice { @@ -186,7 +186,7 @@ impl TextureSlicer { render_size.x - (tl_corner.draw_size.x + tr_corner.draw_size.x), tl_corner.draw_size.y, ), - offset: vec2(0.0, tl_corner.offset.y), + offset: vec2((tl_corner.draw_size.x - tr_corner.draw_size.x) / 2.0, tl_corner.offset.y), }, ] } @@ -221,6 +221,8 @@ impl TextureSlicer { } let mut slices = Vec::with_capacity(9); // Corners + // + // [tl_corner, tr_corner, bl_corner, br_corner]: &[TextureSlice; 4], let corners = self.corner_slices(rect, render_size); // Sides let vertical_sides = self.vertical_side_slices(&corners, rect, render_size); @@ -235,7 +237,8 @@ impl TextureSlicer { render_size.x - (corners[2].draw_size.x + corners[3].draw_size.x), render_size.y - (corners[2].draw_size.y + corners[0].draw_size.y), ), - offset: Vec2::ZERO, + 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), }; slices.extend(corners); @@ -279,3 +282,120 @@ impl Default for TextureSlicer { } } } + +#[cfg(test)] +mod test { + use super::*; + // fn to_debug(x: T) -> String { + // format!("{:?}", x) + // } + + #[test] + fn test_horizontal_sizes_uniform() { + let slicer = TextureSlicer { + border: + BorderRect { + left: 10., + right: 10., + top: 10., + bottom: 10., + }, + center_scale_mode: SliceScaleMode::Stretch, + sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + max_corner_scale: 1.0, + }; + let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let render_rect = Vec2::splat(100.); + let slices = slicer.corner_slices(base_rect, render_rect); + assert_eq!(slices[0], TextureSlice { + texture_rect: Rect { min: Vec2::ZERO, + max: Vec2::splat(10.0) }, + draw_size: Vec2::new(10.0, 10.0), + offset: Vec2::new(-45.0, 45.0), + }); + } + + #[test] + fn test_horizontal_sizes_non_uniform_bigger() { + let slicer = TextureSlicer { + border: + BorderRect { + left: 20., + right: 10., + top: 10., + bottom: 10., + }, + center_scale_mode: SliceScaleMode::Stretch, + sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + max_corner_scale: 1.0, + }; + let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let render_rect = Vec2::splat(100.); + let slices = slicer.corner_slices(base_rect, render_rect); + assert_eq!(slices[0], TextureSlice { + texture_rect: Rect { min: Vec2::ZERO, + max: Vec2::new(20.0, 10.0) }, + draw_size: Vec2::new(20.0, 10.0), + offset: Vec2::new(-40.0, 45.0), + }); + } + + #[test] + fn test_horizontal_sizes_non_uniform_smaller() { + let slicer = TextureSlicer { + border: + BorderRect { + left: 5., + right: 10., + top: 10., + bottom: 10., + }, + center_scale_mode: SliceScaleMode::Stretch, + sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + max_corner_scale: 1.0, + }; + let rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let render_size = Vec2::splat(100.); + let corners = slicer.corner_slices(rect, render_size); + + let vertical_sides = slicer.vertical_side_slices(&corners, rect, render_size); + let horizontal_sides = slicer.horizontal_side_slices(&corners, rect, render_size); + assert_eq!(corners[0], TextureSlice { + texture_rect: Rect { min: Vec2::ZERO, + max: Vec2::new(5.0, 10.0) }, + draw_size: Vec2::new(5.0, 10.0), + offset: Vec2::new(-47.5, 45.0), + }); + assert_eq!(vertical_sides[1] /* top */, TextureSlice { + texture_rect: Rect { min: Vec2::new(5.0, 0.0), + max: Vec2::new(40.0, 10.0) }, + draw_size: Vec2::new(85.0, 10.0), + offset: Vec2::new(0.0, 45.0), + }); + } + + #[test] + fn test_horizontal_sizes_non_uniform_zero() { + let slicer = TextureSlicer { + border: + BorderRect { + left: 0., + right: 10., + top: 10., + bottom: 10., + }, + center_scale_mode: SliceScaleMode::Stretch, + sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + max_corner_scale: 1.0, + }; + let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let render_rect = Vec2::splat(100.); + let slices = slicer.corner_slices(base_rect, render_rect); + assert_eq!(slices[0], TextureSlice { + texture_rect: Rect { min: Vec2::ZERO, + max: Vec2::new(0.0, 10.0) }, + draw_size: Vec2::new(0.0, 10.0), + offset: Vec2::new(-50.0, 45.0), + }); + } +} From 2bbde571afb5221cd66ce19ddc55fc09d6de85b5 Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Tue, 18 Jun 2024 23:20:46 -0400 Subject: [PATCH 2/4] bug: Fix some other scaling issues. --- crates/bevy_sprite/src/texture_slice/slicer.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_sprite/src/texture_slice/slicer.rs b/crates/bevy_sprite/src/texture_slice/slicer.rs index 86f463bece4f7..76b7bdeb44b5b 100644 --- a/crates/bevy_sprite/src/texture_slice/slicer.rs +++ b/crates/bevy_sprite/src/texture_slice/slicer.rs @@ -127,18 +127,18 @@ impl TextureSlicer { }, draw_size: vec2( bl_corner.draw_size.x, - render_size.y - bl_corner.draw_size.y - tl_corner.draw_size.y, + render_size.y - (bl_corner.draw_size.y + tl_corner.draw_size.y), ), - offset: vec2(-render_size.x + bl_corner.draw_size.x, bl_corner.draw_size.y - tl_corner.draw_size.y) / 2.0 + offset: vec2(-render_size.x + bl_corner.draw_size.x, bl_corner.draw_size.y - tl_corner.draw_size.y) / 2.0, }, // right TextureSlice { texture_rect: Rect { min: vec2( base_rect.max.x - self.border.right, - base_rect.min.y + self.border.bottom, + base_rect.min.y + self.border.top, ), - max: vec2(base_rect.max.x, base_rect.max.y - self.border.top), + max: vec2(base_rect.max.x, base_rect.max.y - self.border.bottom), }, draw_size: vec2( br_corner.draw_size.x, @@ -230,8 +230,8 @@ impl TextureSlicer { // Center let center = TextureSlice { texture_rect: Rect { - min: rect.min + vec2(self.border.left, self.border.bottom), - max: vec2(rect.max.x - self.border.right, rect.max.y - self.border.top), + min: rect.min + vec2(self.border.left, self.border.top), + max: vec2(rect.max.x - self.border.right, rect.max.y - self.border.bottom), }, draw_size: vec2( render_size.x - (corners[2].draw_size.x + corners[3].draw_size.x), From cc7dbe9458efdd0656081c8e8241c07edc156635 Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Tue, 18 Jun 2024 23:32:45 -0400 Subject: [PATCH 3/4] doc: Clean up comments. --- .../bevy_sprite/src/texture_slice/slicer.rs | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/crates/bevy_sprite/src/texture_slice/slicer.rs b/crates/bevy_sprite/src/texture_slice/slicer.rs index 76b7bdeb44b5b..fa77272135960 100644 --- a/crates/bevy_sprite/src/texture_slice/slicer.rs +++ b/crates/bevy_sprite/src/texture_slice/slicer.rs @@ -44,7 +44,7 @@ pub enum SliceScaleMode { } impl TextureSlicer { - /// Computes the 4 corner slices + /// Computes the 4 corner slices: top left, top right, bottom left, bottom right. #[must_use] fn corner_slices(&self, base_rect: Rect, render_size: Vec2) -> [TextureSlice; 4] { let coef = render_size / base_rect.size(); @@ -116,7 +116,7 @@ impl TextureSlicer { render_size: Vec2, ) -> [TextureSlice; 2] { [ - // left + // Left TextureSlice { texture_rect: Rect { min: base_rect.min + vec2(0.0, self.border.top), @@ -131,7 +131,7 @@ impl TextureSlicer { ), offset: vec2(-render_size.x + bl_corner.draw_size.x, bl_corner.draw_size.y - tl_corner.draw_size.y) / 2.0, }, - // right + // Right TextureSlice { texture_rect: Rect { min: vec2( @@ -220,12 +220,11 @@ impl TextureSlicer { }]; } let mut slices = Vec::with_capacity(9); - // Corners - // - // [tl_corner, tr_corner, bl_corner, br_corner]: &[TextureSlice; 4], + // Corners are in this order: [TL, TR, BL, BR] let corners = self.corner_slices(rect, render_size); - // Sides + // Vertical Sides: [B, T] let vertical_sides = self.vertical_side_slices(&corners, rect, render_size); + // Horizontal Sides: [L, R] let horizontal_sides = self.horizontal_side_slices(&corners, rect, render_size); // Center let center = TextureSlice { @@ -286,10 +285,6 @@ impl Default for TextureSlicer { #[cfg(test)] mod test { use super::*; - // fn to_debug(x: T) -> String { - // format!("{:?}", x) - // } - #[test] fn test_horizontal_sizes_uniform() { let slicer = TextureSlicer { @@ -301,7 +296,7 @@ mod test { bottom: 10., }, center_scale_mode: SliceScaleMode::Stretch, - sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; @@ -326,7 +321,7 @@ mod test { bottom: 10., }, center_scale_mode: SliceScaleMode::Stretch, - sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; @@ -351,7 +346,7 @@ mod test { bottom: 10., }, center_scale_mode: SliceScaleMode::Stretch, - sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; let rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; @@ -359,7 +354,6 @@ mod test { let corners = slicer.corner_slices(rect, render_size); let vertical_sides = slicer.vertical_side_slices(&corners, rect, render_size); - let horizontal_sides = slicer.horizontal_side_slices(&corners, rect, render_size); assert_eq!(corners[0], TextureSlice { texture_rect: Rect { min: Vec2::ZERO, max: Vec2::new(5.0, 10.0) }, @@ -370,7 +364,7 @@ mod test { texture_rect: Rect { min: Vec2::new(5.0, 0.0), max: Vec2::new(40.0, 10.0) }, draw_size: Vec2::new(85.0, 10.0), - offset: Vec2::new(0.0, 45.0), + offset: Vec2::new(-2.5, 45.0), }); } @@ -385,7 +379,7 @@ mod test { bottom: 10., }, center_scale_mode: SliceScaleMode::Stretch, - sides_scale_mode: SliceScaleMode::Stretch, //Tile { stretch_value: 1.0 }, + sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; From b0da90b332a052ddfbd12e52267ade802d466095 Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Tue, 18 Jun 2024 23:33:23 -0400 Subject: [PATCH 4/4] chore: Run cargo fmt. --- .../bevy_sprite/src/texture_slice/slicer.rs | 148 ++++++++++++------ 1 file changed, 99 insertions(+), 49 deletions(-) diff --git a/crates/bevy_sprite/src/texture_slice/slicer.rs b/crates/bevy_sprite/src/texture_slice/slicer.rs index fa77272135960..2b69f6fc1f38d 100644 --- a/crates/bevy_sprite/src/texture_slice/slicer.rs +++ b/crates/bevy_sprite/src/texture_slice/slicer.rs @@ -129,7 +129,10 @@ impl TextureSlicer { bl_corner.draw_size.x, render_size.y - (bl_corner.draw_size.y + tl_corner.draw_size.y), ), - offset: vec2(-render_size.x + bl_corner.draw_size.x, bl_corner.draw_size.y - tl_corner.draw_size.y) / 2.0, + offset: vec2( + -render_size.x + bl_corner.draw_size.x, + bl_corner.draw_size.y - tl_corner.draw_size.y, + ) / 2.0, }, // Right TextureSlice { @@ -144,7 +147,10 @@ impl TextureSlicer { br_corner.draw_size.x, render_size.y - (br_corner.draw_size.y + tr_corner.draw_size.y), ), - offset: vec2(render_size.x - br_corner.draw_size.x, br_corner.draw_size.y - tr_corner.draw_size.y) / 2.0, + offset: vec2( + render_size.x - br_corner.draw_size.x, + br_corner.draw_size.y - tr_corner.draw_size.y, + ) / 2.0, }, ] } @@ -171,7 +177,10 @@ impl TextureSlicer { 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), + offset: vec2( + (bl_corner.draw_size.x - br_corner.draw_size.x) / 2.0, + bl_corner.offset.y, + ), }, // Top TextureSlice { @@ -186,7 +195,10 @@ impl TextureSlicer { render_size.x - (tl_corner.draw_size.x + tr_corner.draw_size.x), tl_corner.draw_size.y, ), - offset: vec2((tl_corner.draw_size.x - tr_corner.draw_size.x) / 2.0, tl_corner.offset.y), + offset: vec2( + (tl_corner.draw_size.x - tr_corner.draw_size.x) / 2.0, + tl_corner.offset.y, + ), }, ] } @@ -230,14 +242,19 @@ impl TextureSlicer { let center = TextureSlice { texture_rect: Rect { min: rect.min + vec2(self.border.left, self.border.top), - max: vec2(rect.max.x - self.border.right, rect.max.y - self.border.bottom), + max: vec2( + rect.max.x - self.border.right, + rect.max.y - self.border.bottom, + ), }, draw_size: vec2( render_size.x - (corners[2].draw_size.x + corners[3].draw_size.x), render_size.y - (corners[2].draw_size.y + corners[0].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::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, + ), }; slices.extend(corners); @@ -288,8 +305,7 @@ mod test { #[test] fn test_horizontal_sizes_uniform() { let slicer = TextureSlicer { - border: - BorderRect { + border: BorderRect { left: 10., right: 10., top: 10., @@ -299,22 +315,29 @@ mod test { sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; - let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let base_rect = Rect { + min: Vec2::ZERO, + max: Vec2::splat(50.), + }; let render_rect = Vec2::splat(100.); let slices = slicer.corner_slices(base_rect, render_rect); - assert_eq!(slices[0], TextureSlice { - texture_rect: Rect { min: Vec2::ZERO, - max: Vec2::splat(10.0) }, - draw_size: Vec2::new(10.0, 10.0), - offset: Vec2::new(-45.0, 45.0), - }); + assert_eq!( + slices[0], + TextureSlice { + texture_rect: Rect { + min: Vec2::ZERO, + max: Vec2::splat(10.0) + }, + draw_size: Vec2::new(10.0, 10.0), + offset: Vec2::new(-45.0, 45.0), + } + ); } #[test] fn test_horizontal_sizes_non_uniform_bigger() { let slicer = TextureSlicer { - border: - BorderRect { + border: BorderRect { left: 20., right: 10., top: 10., @@ -324,22 +347,29 @@ mod test { sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; - let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let base_rect = Rect { + min: Vec2::ZERO, + max: Vec2::splat(50.), + }; let render_rect = Vec2::splat(100.); let slices = slicer.corner_slices(base_rect, render_rect); - assert_eq!(slices[0], TextureSlice { - texture_rect: Rect { min: Vec2::ZERO, - max: Vec2::new(20.0, 10.0) }, - draw_size: Vec2::new(20.0, 10.0), - offset: Vec2::new(-40.0, 45.0), - }); + assert_eq!( + slices[0], + TextureSlice { + texture_rect: Rect { + min: Vec2::ZERO, + max: Vec2::new(20.0, 10.0) + }, + draw_size: Vec2::new(20.0, 10.0), + offset: Vec2::new(-40.0, 45.0), + } + ); } #[test] fn test_horizontal_sizes_non_uniform_smaller() { let slicer = TextureSlicer { - border: - BorderRect { + border: BorderRect { left: 5., right: 10., top: 10., @@ -349,30 +379,42 @@ mod test { sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; - let rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let rect = Rect { + min: Vec2::ZERO, + max: Vec2::splat(50.), + }; let render_size = Vec2::splat(100.); let corners = slicer.corner_slices(rect, render_size); let vertical_sides = slicer.vertical_side_slices(&corners, rect, render_size); - assert_eq!(corners[0], TextureSlice { - texture_rect: Rect { min: Vec2::ZERO, - max: Vec2::new(5.0, 10.0) }, - draw_size: Vec2::new(5.0, 10.0), - offset: Vec2::new(-47.5, 45.0), - }); - assert_eq!(vertical_sides[1] /* top */, TextureSlice { - texture_rect: Rect { min: Vec2::new(5.0, 0.0), - max: Vec2::new(40.0, 10.0) }, - draw_size: Vec2::new(85.0, 10.0), - offset: Vec2::new(-2.5, 45.0), - }); + assert_eq!( + corners[0], + TextureSlice { + texture_rect: Rect { + min: Vec2::ZERO, + max: Vec2::new(5.0, 10.0) + }, + draw_size: Vec2::new(5.0, 10.0), + offset: Vec2::new(-47.5, 45.0), + } + ); + assert_eq!( + vertical_sides[1], /* top */ + TextureSlice { + texture_rect: Rect { + min: Vec2::new(5.0, 0.0), + max: Vec2::new(40.0, 10.0) + }, + draw_size: Vec2::new(85.0, 10.0), + offset: Vec2::new(-2.5, 45.0), + } + ); } #[test] fn test_horizontal_sizes_non_uniform_zero() { let slicer = TextureSlicer { - border: - BorderRect { + border: BorderRect { left: 0., right: 10., top: 10., @@ -382,14 +424,22 @@ mod test { sides_scale_mode: SliceScaleMode::Stretch, max_corner_scale: 1.0, }; - let base_rect = Rect { min: Vec2::ZERO, max: Vec2::splat(50.) }; + let base_rect = Rect { + min: Vec2::ZERO, + max: Vec2::splat(50.), + }; let render_rect = Vec2::splat(100.); let slices = slicer.corner_slices(base_rect, render_rect); - assert_eq!(slices[0], TextureSlice { - texture_rect: Rect { min: Vec2::ZERO, - max: Vec2::new(0.0, 10.0) }, - draw_size: Vec2::new(0.0, 10.0), - offset: Vec2::new(-50.0, 45.0), - }); + assert_eq!( + slices[0], + TextureSlice { + texture_rect: Rect { + min: Vec2::ZERO, + max: Vec2::new(0.0, 10.0) + }, + draw_size: Vec2::new(0.0, 10.0), + offset: Vec2::new(-50.0, 45.0), + } + ); } }