Newtype Anchor
(#18439)
# Objective The `Anchor` component doesn't need to be a enum. The variants are just mapped to `Vec2`s so it could be changed to a newtype with associated const values, saving the space needed for the discriminator by the enum. Also there was no benefit I think in hiding the underlying `Vec2` representation of `Anchor`s. Suggested by @atlv24. Fixes #18459 Fixes #18460 ## Solution Change `Anchor` to a struct newtyping a `Vec2`, and its variants into associated constants. ## Migration Guide The anchor component has been changed from an enum to a struct newtyping a `Vec2`. The `Custom` variant has been removed, instead to construct a custom `Anchor` use its tuple constructor: ```rust Sprite { anchor: Anchor(Vec2::new(0.25, 0.4)), ..default() } ``` The other enum variants have been replaced with corresponding constants: * `Anchor::BottomLeft` to `Anchor::BOTTOM_LEFT` * `Anchor::Center` to `Anchor::CENTER` * `Anchor::TopRight` to `Anchor::TOP_RIGHT` * .. and so on for the remaining variants
This commit is contained in:
parent
9ae7aa4399
commit
84b09b9398
@ -331,7 +331,7 @@ mod test {
|
|||||||
.world_mut()
|
.world_mut()
|
||||||
.spawn(Sprite {
|
.spawn(Sprite {
|
||||||
rect: Some(Rect::new(0., 0., 0.5, 1.)),
|
rect: Some(Rect::new(0., 0., 0.5, 1.)),
|
||||||
anchor: Anchor::TopRight,
|
anchor: Anchor::TOP_RIGHT,
|
||||||
image: image_handle,
|
image: image_handle,
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_color::Color;
|
use bevy_color::Color;
|
||||||
|
use bevy_derive::{Deref, DerefMut};
|
||||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||||
use bevy_image::{Image, TextureAtlas, TextureAtlasLayout};
|
use bevy_image::{Image, TextureAtlas, TextureAtlasLayout};
|
||||||
use bevy_math::{Rect, UVec2, Vec2};
|
use bevy_math::{Rect, UVec2, Vec2};
|
||||||
@ -240,41 +241,37 @@ pub enum ScalingMode {
|
|||||||
FitEnd,
|
FitEnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How a sprite is positioned relative to its [`Transform`].
|
/// Normalized (relative to its size) offset of a 2d renderable entity from its [`Transform`].
|
||||||
/// It defaults to `Anchor::Center`.
|
#[derive(Component, Debug, Clone, Copy, PartialEq, Deref, DerefMut, Reflect)]
|
||||||
#[derive(Component, Debug, Clone, Copy, PartialEq, Default, Reflect)]
|
|
||||||
#[reflect(Component, Default, Debug, PartialEq, Clone)]
|
#[reflect(Component, Default, Debug, PartialEq, Clone)]
|
||||||
#[doc(alias = "pivot")]
|
#[doc(alias = "pivot")]
|
||||||
pub enum Anchor {
|
pub struct Anchor(pub Vec2);
|
||||||
#[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),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Anchor {
|
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 {
|
pub fn as_vec(&self) -> Vec2 {
|
||||||
match self {
|
self.0
|
||||||
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),
|
impl Default for Anchor {
|
||||||
Anchor::CenterLeft => Vec2::new(-0.5, 0.0),
|
fn default() -> Self {
|
||||||
Anchor::CenterRight => Vec2::new(0.5, 0.0),
|
Self::CENTER
|
||||||
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,
|
impl From<Vec2> for Anchor {
|
||||||
}
|
fn from(value: Vec2) -> Self {
|
||||||
|
Self(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +355,7 @@ mod tests {
|
|||||||
|
|
||||||
let sprite = Sprite {
|
let sprite = Sprite {
|
||||||
image,
|
image,
|
||||||
anchor: Anchor::BottomLeft,
|
anchor: Anchor::BOTTOM_LEFT,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -380,7 +377,7 @@ mod tests {
|
|||||||
|
|
||||||
let sprite = Sprite {
|
let sprite = Sprite {
|
||||||
image,
|
image,
|
||||||
anchor: Anchor::TopRight,
|
anchor: Anchor::TOP_RIGHT,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -402,7 +399,7 @@ mod tests {
|
|||||||
|
|
||||||
let sprite = Sprite {
|
let sprite = Sprite {
|
||||||
image,
|
image,
|
||||||
anchor: Anchor::BottomLeft,
|
anchor: Anchor::BOTTOM_LEFT,
|
||||||
flip_x: true,
|
flip_x: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -425,7 +422,7 @@ mod tests {
|
|||||||
|
|
||||||
let sprite = Sprite {
|
let sprite = Sprite {
|
||||||
image,
|
image,
|
||||||
anchor: Anchor::TopRight,
|
anchor: Anchor::TOP_RIGHT,
|
||||||
flip_y: true,
|
flip_y: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -449,7 +446,7 @@ mod tests {
|
|||||||
let sprite = Sprite {
|
let sprite = Sprite {
|
||||||
image,
|
image,
|
||||||
rect: Some(Rect::new(1.5, 3.0, 3.0, 9.5)),
|
rect: Some(Rect::new(1.5, 3.0, 3.0, 9.5)),
|
||||||
anchor: Anchor::BottomLeft,
|
anchor: Anchor::BOTTOM_LEFT,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -473,7 +470,7 @@ mod tests {
|
|||||||
|
|
||||||
let sprite = Sprite {
|
let sprite = Sprite {
|
||||||
image,
|
image,
|
||||||
anchor: Anchor::BottomLeft,
|
anchor: Anchor::BOTTOM_LEFT,
|
||||||
texture_atlas: Some(TextureAtlas {
|
texture_atlas: Some(TextureAtlas {
|
||||||
layout: texture_atlas,
|
layout: texture_atlas,
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -501,7 +498,7 @@ mod tests {
|
|||||||
|
|
||||||
let sprite = Sprite {
|
let sprite = Sprite {
|
||||||
image,
|
image,
|
||||||
anchor: Anchor::BottomLeft,
|
anchor: Anchor::BOTTOM_LEFT,
|
||||||
texture_atlas: Some(TextureAtlas {
|
texture_atlas: Some(TextureAtlas {
|
||||||
layout: texture_atlas,
|
layout: texture_atlas,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
@ -213,7 +213,7 @@ pub fn extract_text2d_sprite(
|
|||||||
image_handle_id: atlas_info.texture.id(),
|
image_handle_id: atlas_info.texture.id(),
|
||||||
flip_x: false,
|
flip_x: false,
|
||||||
flip_y: false,
|
flip_y: false,
|
||||||
anchor: Anchor::Center.as_vec(),
|
anchor: Anchor::CENTER.as_vec(),
|
||||||
original_entity,
|
original_entity,
|
||||||
scaling_mode: None,
|
scaling_mode: None,
|
||||||
});
|
});
|
||||||
|
@ -132,7 +132,7 @@ fn setup_sprites(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
TextLayout::new_with_justify(JustifyText::Center),
|
TextLayout::new_with_justify(JustifyText::Center),
|
||||||
TextFont::from_font_size(15.),
|
TextFont::from_font_size(15.),
|
||||||
Transform::from_xyz(0., -0.5 * rect.size.y - 10., 0.),
|
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),
|
TextLayout::new_with_justify(JustifyText::Center),
|
||||||
TextFont::from_font_size(15.),
|
TextFont::from_font_size(15.),
|
||||||
Transform::from_xyz(0., -0.5 * sprite_sheet.size.y - 10., 0.),
|
Transform::from_xyz(0., -0.5 * sprite_sheet.size.y - 10., 0.),
|
||||||
bevy::sprite::Anchor::TopCenter,
|
bevy::sprite::Anchor::TOP_CENTER,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ fn spawn_sprites(
|
|||||||
text_style,
|
text_style,
|
||||||
TextLayout::new_with_justify(JustifyText::Center),
|
TextLayout::new_with_justify(JustifyText::Center),
|
||||||
Transform::from_xyz(0., -0.5 * size.y - 10., 0.0),
|
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;
|
position.x += 0.5 * size.x + gap;
|
||||||
|
@ -129,10 +129,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
))
|
))
|
||||||
.with_children(|commands| {
|
.with_children(|commands| {
|
||||||
for (text_anchor, color) in [
|
for (text_anchor, color) in [
|
||||||
(Anchor::TopLeft, Color::Srgba(LIGHT_SALMON)),
|
(Anchor::TOP_LEFT, Color::Srgba(LIGHT_SALMON)),
|
||||||
(Anchor::TopRight, Color::Srgba(LIGHT_GREEN)),
|
(Anchor::TOP_RIGHT, Color::Srgba(LIGHT_GREEN)),
|
||||||
(Anchor::BottomRight, Color::Srgba(LIGHT_BLUE)),
|
(Anchor::BOTTOM_RIGHT, Color::Srgba(LIGHT_BLUE)),
|
||||||
(Anchor::BottomLeft, Color::Srgba(LIGHT_YELLOW)),
|
(Anchor::BOTTOM_LEFT, Color::Srgba(LIGHT_YELLOW)),
|
||||||
] {
|
] {
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
|
@ -38,16 +38,15 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
.spawn((Transform::default(), Visibility::default()))
|
.spawn((Transform::default(), Visibility::default()))
|
||||||
.with_children(|commands| {
|
.with_children(|commands| {
|
||||||
for (anchor_index, anchor) in [
|
for (anchor_index, anchor) in [
|
||||||
Anchor::TopLeft,
|
Anchor::TOP_LEFT,
|
||||||
Anchor::TopCenter,
|
Anchor::TOP_CENTER,
|
||||||
Anchor::TopRight,
|
Anchor::TOP_RIGHT,
|
||||||
Anchor::CenterLeft,
|
Anchor::CENTER_LEFT,
|
||||||
Anchor::Center,
|
Anchor::CENTER,
|
||||||
Anchor::CenterRight,
|
Anchor::CENTER_RIGHT,
|
||||||
Anchor::BottomLeft,
|
Anchor::BOTTOM_LEFT,
|
||||||
Anchor::BottomCenter,
|
Anchor::BOTTOM_CENTER,
|
||||||
Anchor::BottomRight,
|
Anchor::BOTTOM_RIGHT,
|
||||||
Anchor::Custom(Vec2::new(0.5, 0.5)),
|
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
@ -101,7 +101,7 @@ fn setup(mut commands: Commands, args: Res<Args>) {
|
|||||||
Text2d::new(text_string),
|
Text2d::new(text_string),
|
||||||
text_font.clone(),
|
text_font.clone(),
|
||||||
TextColor(RED.into()),
|
TextColor(RED.into()),
|
||||||
bevy::sprite::Anchor::Center,
|
bevy::sprite::Anchor::CENTER,
|
||||||
TextBounds::new_horizontal(1000.),
|
TextBounds::new_horizontal(1000.),
|
||||||
text_block,
|
text_block,
|
||||||
));
|
));
|
||||||
|
@ -215,10 +215,10 @@ mod text {
|
|||||||
));
|
));
|
||||||
|
|
||||||
for anchor in [
|
for anchor in [
|
||||||
Anchor::TopLeft,
|
Anchor::TOP_LEFT,
|
||||||
Anchor::TopRight,
|
Anchor::TOP_RIGHT,
|
||||||
Anchor::BottomRight,
|
Anchor::BOTTOM_RIGHT,
|
||||||
Anchor::BottomLeft,
|
Anchor::BOTTOM_LEFT,
|
||||||
] {
|
] {
|
||||||
let mut text = commands.spawn((
|
let mut text = commands.spawn((
|
||||||
Text2d::new("L R\n"),
|
Text2d::new("L R\n"),
|
||||||
@ -229,7 +229,7 @@ mod text {
|
|||||||
));
|
));
|
||||||
text.with_children(|parent| {
|
text.with_children(|parent| {
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
TextSpan::new(format!("{anchor:?}\n")),
|
TextSpan::new(format!("{}, {}\n", anchor.x, anchor.y)),
|
||||||
TextFont::from_font_size(14.0),
|
TextFont::from_font_size(14.0),
|
||||||
TextColor(palettes::tailwind::BLUE_400.into()),
|
TextColor(palettes::tailwind::BLUE_400.into()),
|
||||||
));
|
));
|
||||||
|
@ -287,7 +287,7 @@ fn setup_sticks(
|
|||||||
(
|
(
|
||||||
Text2d::default(),
|
Text2d::default(),
|
||||||
Transform::from_xyz(0., STICK_BOUNDS_SIZE + 2., 4.),
|
Transform::from_xyz(0., STICK_BOUNDS_SIZE + 2., 4.),
|
||||||
Anchor::BottomCenter,
|
Anchor::BOTTOM_CENTER,
|
||||||
TextWithAxes { x_axis, y_axis },
|
TextWithAxes { x_axis, y_axis },
|
||||||
children![
|
children![
|
||||||
(TextSpan(format!("{:.3}", 0.)), style.clone()),
|
(TextSpan(format!("{:.3}", 0.)), style.clone()),
|
||||||
|
Loading…
Reference in New Issue
Block a user