Make default behavior for BackgroundColor
and BorderColor
more intuitive (#14017)
# Objective In Bevy 0.13, `BackgroundColor` simply tinted the image of any `UiImage`. This was confusing: in every other case (e.g. Text), this added a solid square behind the element. #11165 changed this, but removed `BackgroundColor` from `ImageBundle` to avoid confusion, since the semantic meaning had changed. However, this resulted in a serious UX downgrade / inconsistency, as this behavior was no longer part of the bundle (unlike for `TextBundle` or `NodeBundle`), leaving users with a relatively frustrating upgrade path. Additionally, adding both `BackgroundColor` and `UiImage` resulted in a bizarre effect, where the background color was seemingly ignored as it was covered by a solid white placeholder image. Fixes #13969. ## Solution Per @viridia's design: > - if you don't specify a background color, it's transparent. > - if you don't specify an image color, it's white (because it's a multiplier). > - if you don't specify an image, no image is drawn. > - if you specify both a background color and an image color, they are independent. > - the background color is drawn behind the image (in whatever pixels are transparent) As laid out by @benfrankel, this involves: 1. Changing the default `UiImage` to use a transparent texture but a pure white tint. 2. Adding `UiImage::solid_color` to quickly set placeholder images. 3. Changing the default `BorderColor` and `BackgroundColor` to transparent. 4. Removing the default overrides for these values in the other assorted UI bundles. 5. Adding `BackgroundColor` back to `ImageBundle` and `ButtonBundle`. 6. Adding a 1x1 `Image::transparent`, which can be accessed from `Assets<Image>` via the `TRANSPARENT_IMAGE_HANDLE` constant. Huge thanks to everyone who helped out with the design in the linked issue and [the Discord thread](https://discord.com/channels/691052431525675048/1255209923890118697/1255209999278280844): this was very much a joint design. @cart helped me figure out how to set the UiImage's default texture to a transparent 1x1 image, which is a much nicer fix. ## Testing I've checked the examples modified by this PR, and the `ui` example as well just to be sure. ## Migration Guide - `BackgroundColor` no longer tints the color of images in `ImageBundle` or `ButtonBundle`. Set `UiImage::color` to tint images instead. - The default texture for `UiImage` is now a transparent white square. Use `UiImage::solid_color` to quickly draw debug images. - The default value for `BackgroundColor` and `BorderColor` is now transparent. Set the color to white manually to return to previous behavior.
This commit is contained in:
parent
65daab8517
commit
82f01569e8
@ -531,6 +531,38 @@ impl Image {
|
|||||||
image
|
image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A transparent white 1x1x1 image.
|
||||||
|
///
|
||||||
|
/// Contrast to [`Image::default`], which is opaque.
|
||||||
|
pub fn transparent() -> Image {
|
||||||
|
// We rely on the default texture format being RGBA8UnormSrgb
|
||||||
|
// when constructing a transparent color from bytes.
|
||||||
|
// If this changes, this function will need to be updated.
|
||||||
|
let format = TextureFormat::bevy_default();
|
||||||
|
debug_assert!(format.pixel_size() == 4);
|
||||||
|
let data = vec![255, 255, 255, 0];
|
||||||
|
Image {
|
||||||
|
data,
|
||||||
|
texture_descriptor: wgpu::TextureDescriptor {
|
||||||
|
size: Extent3d {
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
format,
|
||||||
|
dimension: TextureDimension::D2,
|
||||||
|
label: None,
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
|
view_formats: &[],
|
||||||
|
},
|
||||||
|
sampler: ImageSampler::Default,
|
||||||
|
texture_view_descriptor: None,
|
||||||
|
asset_usage: RenderAssetUsages::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new image from raw binary data and the corresponding metadata, by filling
|
/// Creates a new image from raw binary data and the corresponding metadata, by filling
|
||||||
/// the image data with the `pixel` data repeated multiple times.
|
/// the image data with the `pixel` data repeated multiple times.
|
||||||
///
|
///
|
||||||
|
@ -43,6 +43,14 @@ use bevy_app::{App, Plugin};
|
|||||||
use bevy_asset::{AssetApp, Assets, Handle};
|
use bevy_asset::{AssetApp, Assets, Handle};
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
|
|
||||||
|
/// A handle to a 1 x 1 transparent white image.
|
||||||
|
///
|
||||||
|
/// Like [`Handle<Image>::default`], this is a handle to a fallback image asset.
|
||||||
|
/// While that handle points to an opaque white 1 x 1 image, this handle points to a transparent 1 x 1 white image.
|
||||||
|
// Number randomly selected by fair WolframAlpha query. Totally arbitrary.
|
||||||
|
pub const TRANSPARENT_IMAGE_HANDLE: Handle<Image> =
|
||||||
|
Handle::weak_from_u128(154728948001857810431816125397303024160);
|
||||||
|
|
||||||
// TODO: replace Texture names with Image names?
|
// TODO: replace Texture names with Image names?
|
||||||
/// Adds the [`Image`] as an asset and makes sure that they are extracted and prepared for the GPU.
|
/// Adds the [`Image`] as an asset and makes sure that they are extracted and prepared for the GPU.
|
||||||
pub struct ImagePlugin {
|
pub struct ImagePlugin {
|
||||||
@ -89,9 +97,11 @@ impl Plugin for ImagePlugin {
|
|||||||
.init_asset::<Image>()
|
.init_asset::<Image>()
|
||||||
.register_asset_reflect::<Image>();
|
.register_asset_reflect::<Image>();
|
||||||
|
|
||||||
app.world_mut()
|
let mut image_assets = app.world_mut().resource_mut::<Assets<Image>>();
|
||||||
.resource_mut::<Assets<Image>>()
|
|
||||||
.insert(&Handle::default(), Image::default());
|
image_assets.insert(&Handle::default(), Image::default());
|
||||||
|
image_assets.insert(&TRANSPARENT_IMAGE_HANDLE, Image::transparent());
|
||||||
|
|
||||||
#[cfg(feature = "basis-universal")]
|
#[cfg(feature = "basis-universal")]
|
||||||
if let Some(processor) = app
|
if let Some(processor) = app
|
||||||
.world()
|
.world()
|
||||||
|
@ -23,7 +23,7 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
|
|||||||
/// Contains the [`Node`] component and other components required to make a container.
|
/// Contains the [`Node`] component and other components required to make a container.
|
||||||
///
|
///
|
||||||
/// See [`node_bundles`](crate::node_bundles) for more specialized bundles like [`TextBundle`].
|
/// See [`node_bundles`](crate::node_bundles) for more specialized bundles like [`TextBundle`].
|
||||||
#[derive(Bundle, Clone, Debug)]
|
#[derive(Bundle, Clone, Debug, Default)]
|
||||||
pub struct NodeBundle {
|
pub struct NodeBundle {
|
||||||
/// Describes the logical size of the node
|
/// Describes the logical size of the node
|
||||||
pub node: Node,
|
pub node: Node,
|
||||||
@ -58,26 +58,6 @@ pub struct NodeBundle {
|
|||||||
pub z_index: ZIndex,
|
pub z_index: ZIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NodeBundle {
|
|
||||||
fn default() -> Self {
|
|
||||||
NodeBundle {
|
|
||||||
// Transparent background
|
|
||||||
background_color: Color::NONE.into(),
|
|
||||||
border_color: Color::NONE.into(),
|
|
||||||
border_radius: BorderRadius::default(),
|
|
||||||
node: Default::default(),
|
|
||||||
style: Default::default(),
|
|
||||||
focus_policy: Default::default(),
|
|
||||||
transform: Default::default(),
|
|
||||||
global_transform: Default::default(),
|
|
||||||
visibility: Default::default(),
|
|
||||||
inherited_visibility: Default::default(),
|
|
||||||
view_visibility: Default::default(),
|
|
||||||
z_index: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A UI node that is an image
|
/// A UI node that is an image
|
||||||
///
|
///
|
||||||
/// # Extra behaviours
|
/// # Extra behaviours
|
||||||
@ -94,8 +74,12 @@ pub struct ImageBundle {
|
|||||||
pub style: Style,
|
pub style: Style,
|
||||||
/// The calculated size based on the given image
|
/// The calculated size based on the given image
|
||||||
pub calculated_size: ContentSize,
|
pub calculated_size: ContentSize,
|
||||||
/// The image of the node
|
/// The image of the node.
|
||||||
|
///
|
||||||
|
/// To tint the image, change the `color` field of this component.
|
||||||
pub image: UiImage,
|
pub image: UiImage,
|
||||||
|
/// The color of the background that will fill the containing node.
|
||||||
|
pub background_color: BackgroundColor,
|
||||||
/// The size of the image in pixels
|
/// The size of the image in pixels
|
||||||
///
|
///
|
||||||
/// This component is set automatically
|
/// This component is set automatically
|
||||||
@ -176,7 +160,7 @@ pub struct AtlasImageBundle {
|
|||||||
///
|
///
|
||||||
/// The positioning of this node is controlled by the UI layout system. If you need manual control,
|
/// The positioning of this node is controlled by the UI layout system. If you need manual control,
|
||||||
/// use [`Text2dBundle`](bevy_text::Text2dBundle).
|
/// use [`Text2dBundle`](bevy_text::Text2dBundle).
|
||||||
#[derive(Bundle, Debug)]
|
#[derive(Bundle, Debug, Default)]
|
||||||
pub struct TextBundle {
|
pub struct TextBundle {
|
||||||
/// Describes the logical size of the node
|
/// Describes the logical size of the node
|
||||||
pub node: Node,
|
pub node: Node,
|
||||||
@ -214,29 +198,6 @@ pub struct TextBundle {
|
|||||||
pub background_color: BackgroundColor,
|
pub background_color: BackgroundColor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "bevy_text")]
|
|
||||||
impl Default for TextBundle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
text: Default::default(),
|
|
||||||
text_layout_info: Default::default(),
|
|
||||||
text_flags: Default::default(),
|
|
||||||
calculated_size: Default::default(),
|
|
||||||
node: Default::default(),
|
|
||||||
style: Default::default(),
|
|
||||||
focus_policy: Default::default(),
|
|
||||||
transform: Default::default(),
|
|
||||||
global_transform: Default::default(),
|
|
||||||
visibility: Default::default(),
|
|
||||||
inherited_visibility: Default::default(),
|
|
||||||
view_visibility: Default::default(),
|
|
||||||
z_index: Default::default(),
|
|
||||||
// Transparent background
|
|
||||||
background_color: BackgroundColor(Color::NONE),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "bevy_text")]
|
#[cfg(feature = "bevy_text")]
|
||||||
impl TextBundle {
|
impl TextBundle {
|
||||||
/// Create a [`TextBundle`] from a single section.
|
/// Create a [`TextBundle`] from a single section.
|
||||||
@ -321,6 +282,8 @@ pub struct ButtonBundle {
|
|||||||
pub border_radius: BorderRadius,
|
pub border_radius: BorderRadius,
|
||||||
/// The image of the node
|
/// The image of the node
|
||||||
pub image: UiImage,
|
pub image: UiImage,
|
||||||
|
/// The background color that will fill the containing node
|
||||||
|
pub background_color: BackgroundColor,
|
||||||
/// 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.
|
||||||
@ -348,9 +311,10 @@ impl Default for ButtonBundle {
|
|||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
interaction: Default::default(),
|
interaction: Default::default(),
|
||||||
focus_policy: FocusPolicy::Block,
|
focus_policy: FocusPolicy::Block,
|
||||||
border_color: BorderColor(Color::NONE),
|
border_color: Default::default(),
|
||||||
border_radius: BorderRadius::default(),
|
border_radius: Default::default(),
|
||||||
image: Default::default(),
|
image: Default::default(),
|
||||||
|
background_color: Default::default(),
|
||||||
transform: Default::default(),
|
transform: Default::default(),
|
||||||
global_transform: Default::default(),
|
global_transform: Default::default(),
|
||||||
visibility: Default::default(),
|
visibility: Default::default(),
|
||||||
|
@ -6,7 +6,7 @@ use bevy_math::{Rect, Vec2};
|
|||||||
use bevy_reflect::prelude::*;
|
use bevy_reflect::prelude::*;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::{Camera, RenderTarget},
|
camera::{Camera, RenderTarget},
|
||||||
texture::Image,
|
texture::{Image, TRANSPARENT_IMAGE_HANDLE},
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::GlobalTransform;
|
use bevy_transform::prelude::GlobalTransform;
|
||||||
use bevy_utils::warn_once;
|
use bevy_utils::warn_once;
|
||||||
@ -1693,7 +1693,8 @@ pub enum GridPlacementError {
|
|||||||
pub struct BackgroundColor(pub Color);
|
pub struct BackgroundColor(pub Color);
|
||||||
|
|
||||||
impl BackgroundColor {
|
impl BackgroundColor {
|
||||||
pub const DEFAULT: Self = Self(Color::WHITE);
|
/// Background color is transparent by default.
|
||||||
|
pub const DEFAULT: Self = Self(Color::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BackgroundColor {
|
impl Default for BackgroundColor {
|
||||||
@ -1725,7 +1726,8 @@ impl<T: Into<Color>> From<T> for BorderColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BorderColor {
|
impl BorderColor {
|
||||||
pub const DEFAULT: Self = BorderColor(Color::WHITE);
|
/// Border color is transparent by default.
|
||||||
|
pub const DEFAULT: Self = BorderColor(Color::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BorderColor {
|
impl Default for BorderColor {
|
||||||
@ -1819,12 +1821,17 @@ impl Outline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The 2D texture displayed for this UI node
|
/// The 2D texture displayed for this UI node
|
||||||
#[derive(Component, Clone, Debug, Reflect, Default)]
|
#[derive(Component, Clone, Debug, Reflect)]
|
||||||
#[reflect(Component, Default)]
|
#[reflect(Component, Default)]
|
||||||
pub struct UiImage {
|
pub struct UiImage {
|
||||||
/// The tint color used to draw the image
|
/// The tint color used to draw the image.
|
||||||
|
///
|
||||||
|
/// This is multiplied by the color of each pixel in the image.
|
||||||
|
/// The field value defaults to solid white, which will pass the image through unmodified.
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
/// Handle to the texture
|
/// Handle to the texture.
|
||||||
|
///
|
||||||
|
/// This defaults to a [`TRANSPARENT_IMAGE_HANDLE`], which points to a fully transparent 1x1 texture.
|
||||||
pub texture: Handle<Image>,
|
pub texture: Handle<Image>,
|
||||||
/// Whether the image should be flipped along its x-axis
|
/// Whether the image should be flipped along its x-axis
|
||||||
pub flip_x: bool,
|
pub flip_x: bool,
|
||||||
@ -1832,14 +1839,49 @@ pub struct UiImage {
|
|||||||
pub flip_y: bool,
|
pub flip_y: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for UiImage {
|
||||||
|
/// A transparent 1x1 image with a solid white tint.
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// This will be invisible by default.
|
||||||
|
/// To set this to a visible image, you need to set the `texture` field to a valid image handle,
|
||||||
|
/// or use [`Handle<Image>`]'s default 1x1 solid white texture (as is done in [`UiImage::solid_color`]).
|
||||||
|
fn default() -> Self {
|
||||||
|
UiImage {
|
||||||
|
// This should be white because the tint is multiplied with the image,
|
||||||
|
// so if you set an actual image with default tint you'd want its original colors
|
||||||
|
color: Color::WHITE,
|
||||||
|
// This texture needs to be transparent by default, to avoid covering the background color
|
||||||
|
texture: TRANSPARENT_IMAGE_HANDLE,
|
||||||
|
flip_x: false,
|
||||||
|
flip_y: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl UiImage {
|
impl UiImage {
|
||||||
|
/// Create a new [`UiImage`] with the given texture.
|
||||||
pub fn new(texture: Handle<Image>) -> Self {
|
pub fn new(texture: Handle<Image>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
texture,
|
texture,
|
||||||
|
color: Color::WHITE,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a solid color [`UiImage`].
|
||||||
|
///
|
||||||
|
/// This is primarily useful for debugging / mocking the extents of your image.
|
||||||
|
pub fn solid_color(color: Color) -> Self {
|
||||||
|
Self {
|
||||||
|
texture: Handle::default(),
|
||||||
|
color,
|
||||||
|
flip_x: false,
|
||||||
|
flip_y: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the color tint
|
/// Set the color tint
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn with_color(mut self, color: Color) -> Self {
|
pub const fn with_color(mut self, color: Color) -> Self {
|
||||||
|
@ -267,7 +267,7 @@ fn add_button_for_value(
|
|||||||
},
|
},
|
||||||
border_color: BorderColor(Color::WHITE),
|
border_color: BorderColor(Color::WHITE),
|
||||||
border_radius: BorderRadius::MAX,
|
border_radius: BorderRadius::MAX,
|
||||||
image: UiImage::default().with_color(Color::BLACK),
|
background_color: Color::BLACK.into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.insert(ColorGradingOptionWidget {
|
.insert(ColorGradingOptionWidget {
|
||||||
|
@ -140,7 +140,7 @@ fn setup(
|
|||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
border_color: Color::WHITE.into(),
|
border_color: Color::WHITE.into(),
|
||||||
image: UiImage::default().with_color(Color::srgb(0.25, 0.25, 0.25)),
|
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -456,7 +456,7 @@ mod menu {
|
|||||||
.spawn((
|
.spawn((
|
||||||
ButtonBundle {
|
ButtonBundle {
|
||||||
style: button_style.clone(),
|
style: button_style.clone(),
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
MenuButtonAction::Play,
|
MenuButtonAction::Play,
|
||||||
@ -477,7 +477,7 @@ mod menu {
|
|||||||
.spawn((
|
.spawn((
|
||||||
ButtonBundle {
|
ButtonBundle {
|
||||||
style: button_style.clone(),
|
style: button_style.clone(),
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
MenuButtonAction::Settings,
|
MenuButtonAction::Settings,
|
||||||
@ -498,7 +498,7 @@ mod menu {
|
|||||||
.spawn((
|
.spawn((
|
||||||
ButtonBundle {
|
ButtonBundle {
|
||||||
style: button_style,
|
style: button_style,
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
MenuButtonAction::Quit,
|
MenuButtonAction::Quit,
|
||||||
@ -567,7 +567,7 @@ mod menu {
|
|||||||
.spawn((
|
.spawn((
|
||||||
ButtonBundle {
|
ButtonBundle {
|
||||||
style: button_style.clone(),
|
style: button_style.clone(),
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
action,
|
action,
|
||||||
@ -654,7 +654,7 @@ mod menu {
|
|||||||
height: Val::Px(65.0),
|
height: Val::Px(65.0),
|
||||||
..button_style.clone()
|
..button_style.clone()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
quality_setting,
|
quality_setting,
|
||||||
@ -675,7 +675,7 @@ mod menu {
|
|||||||
.spawn((
|
.spawn((
|
||||||
ButtonBundle {
|
ButtonBundle {
|
||||||
style: button_style,
|
style: button_style,
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
MenuButtonAction::BackToSettings,
|
MenuButtonAction::BackToSettings,
|
||||||
@ -750,7 +750,7 @@ mod menu {
|
|||||||
height: Val::Px(65.0),
|
height: Val::Px(65.0),
|
||||||
..button_style.clone()
|
..button_style.clone()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
Volume(volume_setting),
|
Volume(volume_setting),
|
||||||
@ -764,7 +764,7 @@ mod menu {
|
|||||||
.spawn((
|
.spawn((
|
||||||
ButtonBundle {
|
ButtonBundle {
|
||||||
style: button_style,
|
style: button_style,
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
MenuButtonAction::BackToSettings,
|
MenuButtonAction::BackToSettings,
|
||||||
|
@ -125,7 +125,6 @@ fn setup_scene(
|
|||||||
bottom: Val::Px(50.0),
|
bottom: Val::Px(50.0),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(Color::NONE),
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
BackgroundColor(Color::WHITE),
|
BackgroundColor(Color::WHITE),
|
||||||
|
@ -363,7 +363,7 @@ mod ui {
|
|||||||
align_items: AlignItems::Center,
|
align_items: AlignItems::Center,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
MenuButton::Play,
|
MenuButton::Play,
|
||||||
@ -391,10 +391,11 @@ mod ui {
|
|||||||
align_items: AlignItems::Center,
|
align_items: AlignItems::Center,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(match tutorial_state.get() {
|
background_color: match tutorial_state.get() {
|
||||||
TutorialState::Active => ACTIVE_BUTTON,
|
TutorialState::Active => ACTIVE_BUTTON,
|
||||||
TutorialState::Inactive => NORMAL_BUTTON,
|
TutorialState::Inactive => NORMAL_BUTTON,
|
||||||
}),
|
}
|
||||||
|
.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
MenuButton::Tutorial,
|
MenuButton::Tutorial,
|
||||||
|
@ -270,7 +270,7 @@ fn setup_menu(mut commands: Commands) {
|
|||||||
align_items: AlignItems::Center,
|
align_items: AlignItems::Center,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
|
@ -74,7 +74,7 @@ fn setup_menu(mut commands: Commands) {
|
|||||||
align_items: AlignItems::Center,
|
align_items: AlignItems::Center,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
|
@ -180,7 +180,7 @@ mod ui {
|
|||||||
align_items: AlignItems::Center,
|
align_items: AlignItems::Center,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
|
@ -246,7 +246,7 @@ fn spawn_button(
|
|||||||
border,
|
border,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(background_color),
|
background_color: background_color.into(),
|
||||||
border_color,
|
border_color,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
@ -75,7 +75,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
},
|
},
|
||||||
border_color: BorderColor(Color::BLACK),
|
border_color: BorderColor(Color::BLACK),
|
||||||
border_radius: BorderRadius::MAX,
|
border_radius: BorderRadius::MAX,
|
||||||
image: UiImage::default().with_color(NORMAL_BUTTON),
|
background_color: NORMAL_BUTTON.into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
|
@ -416,7 +416,7 @@ where
|
|||||||
padding: UiRect::axes(Val::Px(5.), Val::Px(1.)),
|
padding: UiRect::axes(Val::Px(5.), Val::Px(1.)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(Color::BLACK.with_alpha(0.5)),
|
background_color: Color::BLACK.with_alpha(0.5).into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Target::<T>::new(target),
|
Target::<T>::new(target),
|
||||||
|
@ -245,11 +245,12 @@ fn spawn_button(
|
|||||||
margin: UiRect::horizontal(Val::Px(2.)),
|
margin: UiRect::horizontal(Val::Px(2.)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(if active {
|
background_color: if active {
|
||||||
ACTIVE_BORDER_COLOR
|
ACTIVE_BORDER_COLOR
|
||||||
} else {
|
} else {
|
||||||
INACTIVE_BORDER_COLOR
|
INACTIVE_BORDER_COLOR
|
||||||
}),
|
}
|
||||||
|
.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
constraint,
|
constraint,
|
||||||
|
@ -37,7 +37,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
align_items: AlignItems::Center,
|
align_items: AlignItems::Center,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(Color::srgb(0.1, 0.5, 0.1)),
|
background_color: Color::srgb(0.1, 0.5, 0.1).into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
@ -63,7 +63,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
align_items: AlignItems::Center,
|
align_items: AlignItems::Center,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::default().with_color(Color::srgb(0.5, 0.1, 0.5)),
|
background_color: Color::srgb(0.5, 0.1, 0.5).into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
|
@ -54,10 +54,10 @@ fn setup(
|
|||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
image: UiImage::new(texture_handle),
|
image: UiImage::new(texture_handle),
|
||||||
|
background_color: BackgroundColor(ANTIQUE_WHITE.into()),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
TextureAtlas::from(texture_atlas_handle),
|
TextureAtlas::from(texture_atlas_handle),
|
||||||
BackgroundColor(ANTIQUE_WHITE.into()),
|
|
||||||
Outline::new(Val::Px(8.0), Val::ZERO, CRIMSON.into()),
|
Outline::new(Val::Px(8.0), Val::ZERO, CRIMSON.into()),
|
||||||
));
|
));
|
||||||
parent.spawn(TextBundle::from_sections([
|
parent.spawn(TextBundle::from_sections([
|
||||||
|
Loading…
Reference in New Issue
Block a user