Optional ImageScaleMode (#11780)
> Follow up to #11600 and #10588 @mockersf expressed some [valid concerns](https://github.com/bevyengine/bevy/pull/11600#issuecomment-1932796498) about the current system this PR attempts to fix: The `ComputedTextureSlices` reacts to asset change in both `bevy_sprite` and `bevy_ui`, meaning that if the `ImageScaleMode` is inserted by default in the bundles, we will iterate through most 2d items every time an asset is updated. # Solution - `ImageScaleMode` only has two variants: `Sliced` and `Tiled`. I removed the `Stretched` default - `ImageScaleMode` is no longer part of any bundle, but the relevant bundles explain that this additional component can be inserted This way, the *absence* of `ImageScaleMode` means the image will be stretched, and its *presence* will include the entity to the various slicing systems Optional components in bundles would make this more straigthfoward # Additional work Should I add new bundles with the `ImageScaleMode` component ?
This commit is contained in:
parent
0ebba278f7
commit
e0c296ee14
@ -1,4 +1,4 @@
|
|||||||
use crate::{texture_atlas::TextureAtlas, ImageScaleMode, Sprite};
|
use crate::{Sprite, TextureAtlas};
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_ecs::bundle::Bundle;
|
use bevy_ecs::bundle::Bundle;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
@ -8,12 +8,16 @@ use bevy_render::{
|
|||||||
use bevy_transform::components::{GlobalTransform, Transform};
|
use bevy_transform::components::{GlobalTransform, Transform};
|
||||||
|
|
||||||
/// A [`Bundle`] of components for drawing a single sprite from an image.
|
/// A [`Bundle`] of components for drawing a single sprite from an image.
|
||||||
|
///
|
||||||
|
/// # Extra behaviours
|
||||||
|
///
|
||||||
|
/// You may add the following components to enable additional behaviours
|
||||||
|
/// - [`ImageScaleMode`](crate::ImageScaleMode) to enable either slicing or tiling of the texture
|
||||||
|
/// - [`TextureAtlas`] to draw specific sections of a sprite sheet, (See [`SpriteSheetBundle`])
|
||||||
#[derive(Bundle, Clone, Default)]
|
#[derive(Bundle, Clone, Default)]
|
||||||
pub struct SpriteBundle {
|
pub struct SpriteBundle {
|
||||||
/// Specifies the rendering properties of the sprite, such as color tint and flip.
|
/// Specifies the rendering properties of the sprite, such as color tint and flip.
|
||||||
pub sprite: Sprite,
|
pub sprite: Sprite,
|
||||||
/// Controls how the image is altered when scaled.
|
|
||||||
pub scale_mode: ImageScaleMode,
|
|
||||||
/// The local transform of the sprite, relative to its parent.
|
/// The local transform of the sprite, relative to its parent.
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
/// The absolute transform of the sprite. This should generally not be written to directly.
|
/// The absolute transform of the sprite. This should generally not be written to directly.
|
||||||
@ -41,8 +45,6 @@ pub struct SpriteBundle {
|
|||||||
pub struct SpriteSheetBundle {
|
pub struct SpriteSheetBundle {
|
||||||
/// Specifies the rendering properties of the sprite, such as color tint and flip.
|
/// Specifies the rendering properties of the sprite, such as color tint and flip.
|
||||||
pub sprite: Sprite,
|
pub sprite: Sprite,
|
||||||
/// Controls how the image is altered when scaled.
|
|
||||||
pub scale_mode: ImageScaleMode,
|
|
||||||
/// The local transform of the sprite, relative to its parent.
|
/// The local transform of the sprite, relative to its parent.
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
/// The absolute transform of the sprite. This should generally not be written to directly.
|
/// The absolute transform of the sprite. This should generally not be written to directly.
|
||||||
|
@ -32,12 +32,9 @@ pub struct Sprite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Controls how the image is altered when scaled.
|
/// Controls how the image is altered when scaled.
|
||||||
#[derive(Component, Debug, Default, Clone, Reflect)]
|
#[derive(Component, Debug, Clone, Reflect)]
|
||||||
#[reflect(Component, Default)]
|
#[reflect(Component)]
|
||||||
pub enum ImageScaleMode {
|
pub enum ImageScaleMode {
|
||||||
/// The entire texture stretches when its dimensions change. This is the default option.
|
|
||||||
#[default]
|
|
||||||
Stretched,
|
|
||||||
/// The texture will be cut in 9 slices, keeping the texture in proportions on resize
|
/// The texture will be cut in 9 slices, keeping the texture in proportions on resize
|
||||||
Sliced(TextureSlicer),
|
Sliced(TextureSlicer),
|
||||||
/// The texture will be repeated if stretched beyond `stretched_value`
|
/// The texture will be repeated if stretched beyond `stretched_value`
|
||||||
|
@ -8,7 +8,7 @@ use bevy_render::texture::Image;
|
|||||||
use bevy_transform::prelude::*;
|
use bevy_transform::prelude::*;
|
||||||
use bevy_utils::HashSet;
|
use bevy_utils::HashSet;
|
||||||
|
|
||||||
/// Component storing texture slices for sprite entities with a tiled or sliced [`ImageScaleMode`]
|
/// Component storing texture slices for sprite entities with a [`ImageScaleMode`]
|
||||||
///
|
///
|
||||||
/// This component is automatically inserted and updated
|
/// This component is automatically inserted and updated
|
||||||
#[derive(Debug, Clone, Component)]
|
#[derive(Debug, Clone, Component)]
|
||||||
@ -62,9 +62,7 @@ impl ComputedTextureSlices {
|
|||||||
/// Generates sprite slices for a `sprite` given a `scale_mode`. The slices
|
/// Generates sprite slices for a `sprite` given a `scale_mode`. The slices
|
||||||
/// will be computed according to the `image_handle` dimensions or the sprite rect.
|
/// will be computed according to the `image_handle` dimensions or the sprite rect.
|
||||||
///
|
///
|
||||||
/// Returns `None` if either:
|
/// Returns `None` if the image asset is not loaded
|
||||||
/// - The scale mode is [`ImageScaleMode::Stretched`]
|
|
||||||
/// - The image asset is not loaded
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn compute_sprite_slices(
|
fn compute_sprite_slices(
|
||||||
sprite: &Sprite,
|
sprite: &Sprite,
|
||||||
@ -72,9 +70,6 @@ fn compute_sprite_slices(
|
|||||||
image_handle: &Handle<Image>,
|
image_handle: &Handle<Image>,
|
||||||
images: &Assets<Image>,
|
images: &Assets<Image>,
|
||||||
) -> Option<ComputedTextureSlices> {
|
) -> Option<ComputedTextureSlices> {
|
||||||
if let ImageScaleMode::Stretched = scale_mode {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let image_size = images.get(image_handle).map(|i| {
|
let image_size = images.get(image_handle).map(|i| {
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
i.texture_descriptor.size.width as f32,
|
i.texture_descriptor.size.width as f32,
|
||||||
@ -82,7 +77,6 @@ fn compute_sprite_slices(
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let slices = match scale_mode {
|
let slices = match scale_mode {
|
||||||
ImageScaleMode::Stretched => unreachable!(),
|
|
||||||
ImageScaleMode::Sliced(slicer) => slicer.compute_slices(
|
ImageScaleMode::Sliced(slicer) => slicer.compute_slices(
|
||||||
sprite.rect.unwrap_or(Rect {
|
sprite.rect.unwrap_or(Rect {
|
||||||
min: Vec2::ZERO,
|
min: Vec2::ZERO,
|
||||||
@ -110,7 +104,7 @@ fn compute_sprite_slices(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// System reacting to added or modified [`Image`] handles, and recompute sprite slices
|
/// System reacting to added or modified [`Image`] handles, and recompute sprite slices
|
||||||
/// on matching sprite entities
|
/// on matching sprite entities with a [`ImageScaleMode`] component
|
||||||
pub(crate) fn compute_slices_on_asset_event(
|
pub(crate) fn compute_slices_on_asset_event(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut events: EventReader<AssetEvent<Image>>,
|
mut events: EventReader<AssetEvent<Image>>,
|
||||||
@ -140,6 +134,7 @@ pub(crate) fn compute_slices_on_asset_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// System reacting to changes on relevant sprite bundle components to compute the sprite slices
|
/// System reacting to changes on relevant sprite bundle components to compute the sprite slices
|
||||||
|
/// on matching sprite entities with a [`ImageScaleMode`] component
|
||||||
pub(crate) fn compute_slices_on_sprite_change(
|
pub(crate) fn compute_slices_on_sprite_change(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
images: Res<Assets<Image>>,
|
images: Res<Assets<Image>>,
|
||||||
|
@ -13,7 +13,7 @@ use bevy_render::{
|
|||||||
prelude::Color,
|
prelude::Color,
|
||||||
view::{InheritedVisibility, ViewVisibility, Visibility},
|
view::{InheritedVisibility, ViewVisibility, Visibility},
|
||||||
};
|
};
|
||||||
use bevy_sprite::{ImageScaleMode, TextureAtlas};
|
use bevy_sprite::TextureAtlas;
|
||||||
#[cfg(feature = "bevy_text")]
|
#[cfg(feature = "bevy_text")]
|
||||||
use bevy_text::{BreakLineOn, JustifyText, Text, TextLayoutInfo, TextSection, TextStyle};
|
use bevy_text::{BreakLineOn, JustifyText, Text, TextLayoutInfo, TextSection, TextStyle};
|
||||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||||
@ -76,6 +76,11 @@ impl Default for NodeBundle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A UI node that is an image
|
/// A UI node that is an image
|
||||||
|
///
|
||||||
|
/// # Extra behaviours
|
||||||
|
///
|
||||||
|
/// You may add the following components to enable additional behaviours
|
||||||
|
/// - [`ImageScaleMode`](bevy_sprite::ImageScaleMode) to enable either slicing or tiling of the texture
|
||||||
#[derive(Bundle, Debug, Default)]
|
#[derive(Bundle, Debug, Default)]
|
||||||
pub struct ImageBundle {
|
pub struct ImageBundle {
|
||||||
/// Describes the logical size of the node
|
/// Describes the logical size of the node
|
||||||
@ -95,8 +100,6 @@ pub struct ImageBundle {
|
|||||||
///
|
///
|
||||||
/// This component is set automatically
|
/// This component is set automatically
|
||||||
pub image_size: UiImageSize,
|
pub image_size: UiImageSize,
|
||||||
/// Controls how the image is altered when scaled.
|
|
||||||
pub scale_mode: ImageScaleMode,
|
|
||||||
/// Whether this node should block interaction with lower nodes
|
/// Whether this node should block interaction with lower nodes
|
||||||
pub focus_policy: FocusPolicy,
|
pub focus_policy: FocusPolicy,
|
||||||
/// The transform of the node
|
/// The transform of the node
|
||||||
@ -288,6 +291,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A UI node that is a button
|
/// A UI node that is a button
|
||||||
|
///
|
||||||
|
/// # Extra behaviours
|
||||||
|
///
|
||||||
|
/// You may add the following components to enable additional behaviours
|
||||||
|
/// - [`ImageScaleMode`](bevy_sprite::ImageScaleMode) to enable either slicing or tiling of the texture
|
||||||
#[derive(Bundle, Clone, Debug)]
|
#[derive(Bundle, Clone, Debug)]
|
||||||
pub struct ButtonBundle {
|
pub struct ButtonBundle {
|
||||||
/// Describes the logical size of the node
|
/// Describes the logical size of the node
|
||||||
@ -309,8 +317,6 @@ pub struct ButtonBundle {
|
|||||||
pub border_color: BorderColor,
|
pub border_color: BorderColor,
|
||||||
/// The image of the node
|
/// The image of the node
|
||||||
pub image: UiImage,
|
pub image: UiImage,
|
||||||
/// Controls how the image is altered when scaled.
|
|
||||||
pub scale_mode: ImageScaleMode,
|
|
||||||
/// The transform of the node
|
/// The transform of the node
|
||||||
///
|
///
|
||||||
/// This component is automatically managed by the UI layout system.
|
/// This component is automatically managed by the UI layout system.
|
||||||
@ -347,7 +353,6 @@ impl Default for ButtonBundle {
|
|||||||
inherited_visibility: Default::default(),
|
inherited_visibility: Default::default(),
|
||||||
view_visibility: Default::default(),
|
view_visibility: Default::default(),
|
||||||
z_index: Default::default(),
|
z_index: Default::default(),
|
||||||
scale_mode: ImageScaleMode::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,9 +77,7 @@ impl ComputedTextureSlices {
|
|||||||
/// Generates sprite slices for a `sprite` given a `scale_mode`. The slices
|
/// Generates sprite slices for a `sprite` given a `scale_mode`. The slices
|
||||||
/// will be computed according to the `image_handle` dimensions or the sprite rect.
|
/// will be computed according to the `image_handle` dimensions or the sprite rect.
|
||||||
///
|
///
|
||||||
/// Returns `None` if either:
|
/// Returns `None` if the image asset is not loaded
|
||||||
/// - The scale mode is [`ImageScaleMode::Stretched`]
|
|
||||||
/// - The image asset is not loaded
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn compute_texture_slices(
|
fn compute_texture_slices(
|
||||||
draw_area: Vec2,
|
draw_area: Vec2,
|
||||||
@ -87,9 +85,6 @@ fn compute_texture_slices(
|
|||||||
image_handle: &UiImage,
|
image_handle: &UiImage,
|
||||||
images: &Assets<Image>,
|
images: &Assets<Image>,
|
||||||
) -> Option<ComputedTextureSlices> {
|
) -> Option<ComputedTextureSlices> {
|
||||||
if let ImageScaleMode::Stretched = scale_mode {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let image_size = images.get(&image_handle.texture).map(|i| {
|
let image_size = images.get(&image_handle.texture).map(|i| {
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
i.texture_descriptor.size.width as f32,
|
i.texture_descriptor.size.width as f32,
|
||||||
@ -101,7 +96,6 @@ fn compute_texture_slices(
|
|||||||
max: image_size,
|
max: image_size,
|
||||||
};
|
};
|
||||||
let slices = match scale_mode {
|
let slices = match scale_mode {
|
||||||
ImageScaleMode::Stretched => unreachable!(),
|
|
||||||
ImageScaleMode::Sliced(slicer) => slicer.compute_slices(texture_rect, Some(draw_area)),
|
ImageScaleMode::Sliced(slicer) => slicer.compute_slices(texture_rect, Some(draw_area)),
|
||||||
ImageScaleMode::Tiled {
|
ImageScaleMode::Tiled {
|
||||||
tile_x,
|
tile_x,
|
||||||
@ -120,7 +114,7 @@ fn compute_texture_slices(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// System reacting to added or modified [`Image`] handles, and recompute sprite slices
|
/// System reacting to added or modified [`Image`] handles, and recompute sprite slices
|
||||||
/// on matching sprite entities
|
/// on matching sprite entities with a [`ImageScaleMode`] component
|
||||||
pub(crate) fn compute_slices_on_asset_event(
|
pub(crate) fn compute_slices_on_asset_event(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut events: EventReader<AssetEvent<Image>>,
|
mut events: EventReader<AssetEvent<Image>>,
|
||||||
@ -157,6 +151,7 @@ pub(crate) fn compute_slices_on_asset_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// System reacting to changes on relevant sprite bundle components to compute the sprite slices
|
/// System reacting to changes on relevant sprite bundle components to compute the sprite slices
|
||||||
|
/// on matching sprite entities with a [`ImageScaleMode`] component
|
||||||
pub(crate) fn compute_slices_on_image_change(
|
pub(crate) fn compute_slices_on_image_change(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
images: Res<Assets<Image>>,
|
images: Res<Assets<Image>>,
|
||||||
|
@ -25,89 +25,85 @@ fn spawn_sprites(
|
|||||||
) {
|
) {
|
||||||
let cases = [
|
let cases = [
|
||||||
// Reference sprite
|
// Reference sprite
|
||||||
(
|
("Original texture", style.clone(), Vec2::splat(100.0), None),
|
||||||
"Original texture",
|
|
||||||
style.clone(),
|
|
||||||
Vec2::splat(100.0),
|
|
||||||
ImageScaleMode::default(),
|
|
||||||
),
|
|
||||||
// Scaled regular sprite
|
// Scaled regular sprite
|
||||||
(
|
(
|
||||||
"Stretched texture",
|
"Stretched texture",
|
||||||
style.clone(),
|
style.clone(),
|
||||||
Vec2::new(100.0, 200.0),
|
Vec2::new(100.0, 200.0),
|
||||||
ImageScaleMode::default(),
|
None,
|
||||||
),
|
),
|
||||||
// Stretched Scaled sliced sprite
|
// Stretched Scaled sliced sprite
|
||||||
(
|
(
|
||||||
"Stretched and sliced",
|
"Stretched and sliced",
|
||||||
style.clone(),
|
style.clone(),
|
||||||
Vec2::new(100.0, 200.0),
|
Vec2::new(100.0, 200.0),
|
||||||
ImageScaleMode::Sliced(TextureSlicer {
|
Some(ImageScaleMode::Sliced(TextureSlicer {
|
||||||
border: BorderRect::square(slice_border),
|
border: BorderRect::square(slice_border),
|
||||||
center_scale_mode: SliceScaleMode::Stretch,
|
center_scale_mode: SliceScaleMode::Stretch,
|
||||||
..default()
|
..default()
|
||||||
}),
|
})),
|
||||||
),
|
),
|
||||||
// Scaled sliced sprite
|
// Scaled sliced sprite
|
||||||
(
|
(
|
||||||
"Sliced and Tiled",
|
"Sliced and Tiled",
|
||||||
style.clone(),
|
style.clone(),
|
||||||
Vec2::new(100.0, 200.0),
|
Vec2::new(100.0, 200.0),
|
||||||
ImageScaleMode::Sliced(TextureSlicer {
|
Some(ImageScaleMode::Sliced(TextureSlicer {
|
||||||
border: BorderRect::square(slice_border),
|
border: BorderRect::square(slice_border),
|
||||||
center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.5 },
|
center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.5 },
|
||||||
sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
|
sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
|
||||||
..default()
|
..default()
|
||||||
}),
|
})),
|
||||||
),
|
),
|
||||||
// Scaled sliced sprite horizontally
|
// Scaled sliced sprite horizontally
|
||||||
(
|
(
|
||||||
"Sliced and Tiled",
|
"Sliced and Tiled",
|
||||||
style.clone(),
|
style.clone(),
|
||||||
Vec2::new(300.0, 200.0),
|
Vec2::new(300.0, 200.0),
|
||||||
ImageScaleMode::Sliced(TextureSlicer {
|
Some(ImageScaleMode::Sliced(TextureSlicer {
|
||||||
border: BorderRect::square(slice_border),
|
border: BorderRect::square(slice_border),
|
||||||
center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
|
center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
|
||||||
sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.3 },
|
sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.3 },
|
||||||
..default()
|
..default()
|
||||||
}),
|
})),
|
||||||
),
|
),
|
||||||
// Scaled sliced sprite horizontally with max scale
|
// Scaled sliced sprite horizontally with max scale
|
||||||
(
|
(
|
||||||
"Sliced and Tiled with corner constraint",
|
"Sliced and Tiled with corner constraint",
|
||||||
style,
|
style,
|
||||||
Vec2::new(300.0, 200.0),
|
Vec2::new(300.0, 200.0),
|
||||||
ImageScaleMode::Sliced(TextureSlicer {
|
Some(ImageScaleMode::Sliced(TextureSlicer {
|
||||||
border: BorderRect::square(slice_border),
|
border: BorderRect::square(slice_border),
|
||||||
center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.1 },
|
center_scale_mode: SliceScaleMode::Tile { stretch_value: 0.1 },
|
||||||
sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
|
sides_scale_mode: SliceScaleMode::Tile { stretch_value: 0.2 },
|
||||||
max_corner_scale: 0.2,
|
max_corner_scale: 0.2,
|
||||||
}),
|
})),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (label, text_style, size, scale_mode) in cases {
|
for (label, text_style, size, scale_mode) in cases {
|
||||||
position.x += 0.5 * size.x;
|
position.x += 0.5 * size.x;
|
||||||
commands
|
let mut cmd = commands.spawn(SpriteBundle {
|
||||||
.spawn(SpriteBundle {
|
transform: Transform::from_translation(position),
|
||||||
transform: Transform::from_translation(position),
|
texture: texture_handle.clone(),
|
||||||
texture: texture_handle.clone(),
|
sprite: Sprite {
|
||||||
sprite: Sprite {
|
custom_size: Some(size),
|
||||||
custom_size: Some(size),
|
..default()
|
||||||
..default()
|
},
|
||||||
},
|
..default()
|
||||||
scale_mode,
|
});
|
||||||
|
if let Some(scale_mode) = scale_mode {
|
||||||
|
cmd.insert(scale_mode);
|
||||||
|
}
|
||||||
|
cmd.with_children(|builder| {
|
||||||
|
builder.spawn(Text2dBundle {
|
||||||
|
text: Text::from_section(label, text_style).with_justify(JustifyText::Center),
|
||||||
|
transform: Transform::from_xyz(0., -0.5 * size.y - 10., 0.0),
|
||||||
|
text_anchor: bevy::sprite::Anchor::TopCenter,
|
||||||
..default()
|
..default()
|
||||||
})
|
|
||||||
.with_children(|builder| {
|
|
||||||
builder.spawn(Text2dBundle {
|
|
||||||
text: Text::from_section(label, text_style).with_justify(JustifyText::Center),
|
|
||||||
transform: Transform::from_xyz(0., -0.5 * size.y - 10., 0.0),
|
|
||||||
text_anchor: bevy::sprite::Anchor::TopCenter,
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
position.x += 0.5 * size.x + gap;
|
position.x += 0.5 * size.x + gap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,17 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
current: 128.0,
|
current: 128.0,
|
||||||
speed: 50.0,
|
speed: 50.0,
|
||||||
});
|
});
|
||||||
commands.spawn(SpriteBundle {
|
commands.spawn((
|
||||||
texture: asset_server.load("branding/icon.png"),
|
SpriteBundle {
|
||||||
scale_mode: ImageScaleMode::Tiled {
|
texture: asset_server.load("branding/icon.png"),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
ImageScaleMode::Tiled {
|
||||||
tile_x: true,
|
tile_x: true,
|
||||||
tile_y: true,
|
tile_y: true,
|
||||||
stretch_value: 0.5, // The image will tile every 128px
|
stretch_value: 0.5, // The image will tile every 128px
|
||||||
},
|
},
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn animate(mut sprites: Query<&mut Sprite>, mut state: ResMut<AnimationState>, time: Res<Time>) {
|
fn animate(mut sprites: Query<&mut Sprite>, mut state: ResMut<AnimationState>, time: Res<Time>) {
|
||||||
|
@ -58,21 +58,23 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
for [w, h] in [[150.0, 150.0], [300.0, 150.0], [150.0, 300.0]] {
|
for [w, h] in [[150.0, 150.0], [300.0, 150.0], [150.0, 300.0]] {
|
||||||
parent
|
parent
|
||||||
.spawn(ButtonBundle {
|
.spawn((
|
||||||
style: Style {
|
ButtonBundle {
|
||||||
width: Val::Px(w),
|
style: Style {
|
||||||
height: Val::Px(h),
|
width: Val::Px(w),
|
||||||
// horizontally center child text
|
height: Val::Px(h),
|
||||||
justify_content: JustifyContent::Center,
|
// horizontally center child text
|
||||||
// vertically center child text
|
justify_content: JustifyContent::Center,
|
||||||
align_items: AlignItems::Center,
|
// vertically center child text
|
||||||
margin: UiRect::all(Val::Px(20.0)),
|
align_items: AlignItems::Center,
|
||||||
|
margin: UiRect::all(Val::Px(20.0)),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
image: image.clone().into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: image.clone().into(),
|
ImageScaleMode::Sliced(slicer.clone()),
|
||||||
scale_mode: ImageScaleMode::Sliced(slicer.clone()),
|
))
|
||||||
..default()
|
|
||||||
})
|
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent.spawn(TextBundle::from_section(
|
parent.spawn(TextBundle::from_section(
|
||||||
"Button",
|
"Button",
|
||||||
|
Loading…
Reference in New Issue
Block a user