diff --git a/crates/bevy_sprite/src/lib.rs b/crates/bevy_sprite/src/lib.rs index ae204dcfd0..e7e60ff7a2 100644 --- a/crates/bevy_sprite/src/lib.rs +++ b/crates/bevy_sprite/src/lib.rs @@ -331,7 +331,7 @@ mod test { .world_mut() .spawn(Sprite { rect: Some(Rect::new(0., 0., 0.5, 1.)), - anchor: Anchor::TopRight, + anchor: Anchor::TOP_RIGHT, image: image_handle, ..default() }) diff --git a/crates/bevy_sprite/src/sprite.rs b/crates/bevy_sprite/src/sprite.rs index 17b24f975c..32b8ebb49e 100644 --- a/crates/bevy_sprite/src/sprite.rs +++ b/crates/bevy_sprite/src/sprite.rs @@ -1,5 +1,6 @@ use bevy_asset::{Assets, Handle}; use bevy_color::Color; +use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{component::Component, reflect::ReflectComponent}; use bevy_image::{Image, TextureAtlas, TextureAtlasLayout}; use bevy_math::{Rect, UVec2, Vec2}; @@ -240,41 +241,37 @@ pub enum ScalingMode { FitEnd, } -/// How a sprite is positioned relative to its [`Transform`]. -/// It defaults to `Anchor::Center`. -#[derive(Component, Debug, Clone, Copy, PartialEq, Default, Reflect)] +/// Normalized (relative to its size) offset of a 2d renderable entity from its [`Transform`]. +#[derive(Component, Debug, Clone, Copy, PartialEq, Deref, DerefMut, Reflect)] #[reflect(Component, Default, Debug, PartialEq, Clone)] #[doc(alias = "pivot")] -pub enum Anchor { - #[default] - Center, - BottomLeft, - BottomCenter, - BottomRight, - CenterLeft, - CenterRight, - TopLeft, - TopCenter, - TopRight, - /// Custom anchor point. Top left is `(-0.5, 0.5)`, center is `(0.0, 0.0)`. The value will - /// be scaled with the sprite size. - Custom(Vec2), -} +pub struct Anchor(pub Vec2); impl Anchor { + pub const BOTTOM_LEFT: Self = Self(Vec2::new(-0.5, -0.5)); + pub const BOTTOM_CENTER: Self = Self(Vec2::new(0.0, -0.5)); + pub const BOTTOM_RIGHT: Self = Self(Vec2::new(0.5, -0.5)); + pub const CENTER_LEFT: Self = Self(Vec2::new(-0.5, 0.0)); + pub const CENTER: Self = Self(Vec2::ZERO); + pub const CENTER_RIGHT: Self = Self(Vec2::new(0.5, 0.0)); + pub const TOP_LEFT: Self = Self(Vec2::new(-0.5, 0.5)); + pub const TOP_CENTER: Self = Self(Vec2::new(0.0, 0.5)); + pub const TOP_RIGHT: Self = Self(Vec2::new(0.5, 0.5)); + pub fn as_vec(&self) -> Vec2 { - match self { - Anchor::Center => Vec2::ZERO, - Anchor::BottomLeft => Vec2::new(-0.5, -0.5), - Anchor::BottomCenter => Vec2::new(0.0, -0.5), - Anchor::BottomRight => Vec2::new(0.5, -0.5), - Anchor::CenterLeft => Vec2::new(-0.5, 0.0), - Anchor::CenterRight => Vec2::new(0.5, 0.0), - Anchor::TopLeft => Vec2::new(-0.5, 0.5), - Anchor::TopCenter => Vec2::new(0.0, 0.5), - Anchor::TopRight => Vec2::new(0.5, 0.5), - Anchor::Custom(point) => *point, - } + self.0 + } +} + +impl Default for Anchor { + fn default() -> Self { + Self::CENTER + } +} + +impl From for Anchor { + fn from(value: Vec2) -> Self { + Self(value) } } @@ -358,7 +355,7 @@ mod tests { let sprite = Sprite { image, - anchor: Anchor::BottomLeft, + anchor: Anchor::BOTTOM_LEFT, ..Default::default() }; @@ -380,7 +377,7 @@ mod tests { let sprite = Sprite { image, - anchor: Anchor::TopRight, + anchor: Anchor::TOP_RIGHT, ..Default::default() }; @@ -402,7 +399,7 @@ mod tests { let sprite = Sprite { image, - anchor: Anchor::BottomLeft, + anchor: Anchor::BOTTOM_LEFT, flip_x: true, ..Default::default() }; @@ -425,7 +422,7 @@ mod tests { let sprite = Sprite { image, - anchor: Anchor::TopRight, + anchor: Anchor::TOP_RIGHT, flip_y: true, ..Default::default() }; @@ -449,7 +446,7 @@ mod tests { let sprite = Sprite { image, rect: Some(Rect::new(1.5, 3.0, 3.0, 9.5)), - anchor: Anchor::BottomLeft, + anchor: Anchor::BOTTOM_LEFT, ..Default::default() }; @@ -473,7 +470,7 @@ mod tests { let sprite = Sprite { image, - anchor: Anchor::BottomLeft, + anchor: Anchor::BOTTOM_LEFT, texture_atlas: Some(TextureAtlas { layout: texture_atlas, index: 0, @@ -501,7 +498,7 @@ mod tests { let sprite = Sprite { image, - anchor: Anchor::BottomLeft, + anchor: Anchor::BOTTOM_LEFT, texture_atlas: Some(TextureAtlas { layout: texture_atlas, index: 0, diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index fc750c5ec1..28eac9cef8 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -213,7 +213,7 @@ pub fn extract_text2d_sprite( image_handle_id: atlas_info.texture.id(), flip_x: false, flip_y: false, - anchor: Anchor::Center.as_vec(), + anchor: Anchor::CENTER.as_vec(), original_entity, scaling_mode: None, }); diff --git a/examples/2d/sprite_scale.rs b/examples/2d/sprite_scale.rs index 036ff841b5..c549134419 100644 --- a/examples/2d/sprite_scale.rs +++ b/examples/2d/sprite_scale.rs @@ -132,7 +132,7 @@ fn setup_sprites(mut commands: Commands, asset_server: Res) { TextLayout::new_with_justify(JustifyText::Center), TextFont::from_font_size(15.), Transform::from_xyz(0., -0.5 * rect.size.y - 10., 0.), - bevy::sprite::Anchor::TopCenter, + bevy::sprite::Anchor::TOP_CENTER, )); }); } @@ -278,7 +278,7 @@ fn setup_texture_atlas( TextLayout::new_with_justify(JustifyText::Center), TextFont::from_font_size(15.), Transform::from_xyz(0., -0.5 * sprite_sheet.size.y - 10., 0.), - bevy::sprite::Anchor::TopCenter, + bevy::sprite::Anchor::TOP_CENTER, )); }); } diff --git a/examples/2d/sprite_slice.rs b/examples/2d/sprite_slice.rs index 499341e344..94f4fe809f 100644 --- a/examples/2d/sprite_slice.rs +++ b/examples/2d/sprite_slice.rs @@ -96,7 +96,7 @@ fn spawn_sprites( text_style, TextLayout::new_with_justify(JustifyText::Center), Transform::from_xyz(0., -0.5 * size.y - 10., 0.0), - bevy::sprite::Anchor::TopCenter, + bevy::sprite::Anchor::TOP_CENTER, )], )); position.x += 0.5 * size.x + gap; diff --git a/examples/2d/text2d.rs b/examples/2d/text2d.rs index 9fb13b0eb2..d7cd4e3d56 100644 --- a/examples/2d/text2d.rs +++ b/examples/2d/text2d.rs @@ -129,10 +129,10 @@ fn setup(mut commands: Commands, asset_server: Res) { )) .with_children(|commands| { for (text_anchor, color) in [ - (Anchor::TopLeft, Color::Srgba(LIGHT_SALMON)), - (Anchor::TopRight, Color::Srgba(LIGHT_GREEN)), - (Anchor::BottomRight, Color::Srgba(LIGHT_BLUE)), - (Anchor::BottomLeft, Color::Srgba(LIGHT_YELLOW)), + (Anchor::TOP_LEFT, Color::Srgba(LIGHT_SALMON)), + (Anchor::TOP_RIGHT, Color::Srgba(LIGHT_GREEN)), + (Anchor::BOTTOM_RIGHT, Color::Srgba(LIGHT_BLUE)), + (Anchor::BOTTOM_LEFT, Color::Srgba(LIGHT_YELLOW)), ] { commands .spawn(( diff --git a/examples/picking/sprite_picking.rs b/examples/picking/sprite_picking.rs index 7b6b2d1582..126336bf29 100644 --- a/examples/picking/sprite_picking.rs +++ b/examples/picking/sprite_picking.rs @@ -38,16 +38,15 @@ fn setup(mut commands: Commands, asset_server: Res) { .spawn((Transform::default(), Visibility::default())) .with_children(|commands| { for (anchor_index, anchor) in [ - Anchor::TopLeft, - Anchor::TopCenter, - Anchor::TopRight, - Anchor::CenterLeft, - Anchor::Center, - Anchor::CenterRight, - Anchor::BottomLeft, - Anchor::BottomCenter, - Anchor::BottomRight, - Anchor::Custom(Vec2::new(0.5, 0.5)), + Anchor::TOP_LEFT, + Anchor::TOP_CENTER, + Anchor::TOP_RIGHT, + Anchor::CENTER_LEFT, + Anchor::CENTER, + Anchor::CENTER_RIGHT, + Anchor::BOTTOM_LEFT, + Anchor::BOTTOM_CENTER, + Anchor::BOTTOM_RIGHT, ] .iter() .enumerate() diff --git a/examples/stress_tests/many_glyphs.rs b/examples/stress_tests/many_glyphs.rs index fe29bc933e..d6629fa80c 100644 --- a/examples/stress_tests/many_glyphs.rs +++ b/examples/stress_tests/many_glyphs.rs @@ -101,7 +101,7 @@ fn setup(mut commands: Commands, args: Res) { Text2d::new(text_string), text_font.clone(), TextColor(RED.into()), - bevy::sprite::Anchor::Center, + bevy::sprite::Anchor::CENTER, TextBounds::new_horizontal(1000.), text_block, )); diff --git a/examples/testbed/2d.rs b/examples/testbed/2d.rs index e1c42ebf95..d3e7d46217 100644 --- a/examples/testbed/2d.rs +++ b/examples/testbed/2d.rs @@ -215,10 +215,10 @@ mod text { )); for anchor in [ - Anchor::TopLeft, - Anchor::TopRight, - Anchor::BottomRight, - Anchor::BottomLeft, + Anchor::TOP_LEFT, + Anchor::TOP_RIGHT, + Anchor::BOTTOM_RIGHT, + Anchor::BOTTOM_LEFT, ] { let mut text = commands.spawn(( Text2d::new("L R\n"), @@ -229,7 +229,7 @@ mod text { )); text.with_children(|parent| { parent.spawn(( - TextSpan::new(format!("{anchor:?}\n")), + TextSpan::new(format!("{}, {}\n", anchor.x, anchor.y)), TextFont::from_font_size(14.0), TextColor(palettes::tailwind::BLUE_400.into()), )); diff --git a/examples/tools/gamepad_viewer.rs b/examples/tools/gamepad_viewer.rs index c8092c2ebe..fc4d2d4c40 100644 --- a/examples/tools/gamepad_viewer.rs +++ b/examples/tools/gamepad_viewer.rs @@ -287,7 +287,7 @@ fn setup_sticks( ( Text2d::default(), Transform::from_xyz(0., STICK_BOUNDS_SIZE + 2., 4.), - Anchor::BottomCenter, + Anchor::BOTTOM_CENTER, TextWithAxes { x_axis, y_axis }, children![ (TextSpan(format!("{:.3}", 0.)), style.clone()),