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
							
								
									dbffb41e50
								
							
						
					
					
						commit
						336fddb101
					
				@ -531,6 +531,38 @@ impl 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
 | 
			
		||||
    /// 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_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?
 | 
			
		||||
/// Adds the [`Image`] as an asset and makes sure that they are extracted and prepared for the GPU.
 | 
			
		||||
pub struct ImagePlugin {
 | 
			
		||||
@ -89,9 +97,11 @@ impl Plugin for ImagePlugin {
 | 
			
		||||
            .init_asset::<Image>()
 | 
			
		||||
            .register_asset_reflect::<Image>();
 | 
			
		||||
 | 
			
		||||
        app.world_mut()
 | 
			
		||||
            .resource_mut::<Assets<Image>>()
 | 
			
		||||
            .insert(&Handle::default(), Image::default());
 | 
			
		||||
        let mut image_assets = app.world_mut().resource_mut::<Assets<Image>>();
 | 
			
		||||
 | 
			
		||||
        image_assets.insert(&Handle::default(), Image::default());
 | 
			
		||||
        image_assets.insert(&TRANSPARENT_IMAGE_HANDLE, Image::transparent());
 | 
			
		||||
 | 
			
		||||
        #[cfg(feature = "basis-universal")]
 | 
			
		||||
        if let Some(processor) = app
 | 
			
		||||
            .world()
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
 | 
			
		||||
/// Contains the [`Node`] component and other components required to make a container.
 | 
			
		||||
///
 | 
			
		||||
/// See [`node_bundles`](crate::node_bundles) for more specialized bundles like [`TextBundle`].
 | 
			
		||||
#[derive(Bundle, Clone, Debug)]
 | 
			
		||||
#[derive(Bundle, Clone, Debug, Default)]
 | 
			
		||||
pub struct NodeBundle {
 | 
			
		||||
    /// Describes the logical size of the node
 | 
			
		||||
    pub node: Node,
 | 
			
		||||
@ -58,26 +58,6 @@ pub struct NodeBundle {
 | 
			
		||||
    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
 | 
			
		||||
///
 | 
			
		||||
/// # Extra behaviours
 | 
			
		||||
@ -94,8 +74,12 @@ pub struct ImageBundle {
 | 
			
		||||
    pub style: Style,
 | 
			
		||||
    /// The calculated size based on the given image
 | 
			
		||||
    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,
 | 
			
		||||
    /// The color of the background that will fill the containing node.
 | 
			
		||||
    pub background_color: BackgroundColor,
 | 
			
		||||
    /// The size of the image in pixels
 | 
			
		||||
    ///
 | 
			
		||||
    /// 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,
 | 
			
		||||
/// use [`Text2dBundle`](bevy_text::Text2dBundle).
 | 
			
		||||
#[derive(Bundle, Debug)]
 | 
			
		||||
#[derive(Bundle, Debug, Default)]
 | 
			
		||||
pub struct TextBundle {
 | 
			
		||||
    /// Describes the logical size of the node
 | 
			
		||||
    pub node: Node,
 | 
			
		||||
@ -214,29 +198,6 @@ pub struct TextBundle {
 | 
			
		||||
    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")]
 | 
			
		||||
impl TextBundle {
 | 
			
		||||
    /// Create a [`TextBundle`] from a single section.
 | 
			
		||||
@ -321,6 +282,8 @@ pub struct ButtonBundle {
 | 
			
		||||
    pub border_radius: BorderRadius,
 | 
			
		||||
    /// The image of the node
 | 
			
		||||
    pub image: UiImage,
 | 
			
		||||
    /// The background color that will fill the containing node
 | 
			
		||||
    pub background_color: BackgroundColor,
 | 
			
		||||
    /// The transform of the node
 | 
			
		||||
    ///
 | 
			
		||||
    /// This component is automatically managed by the UI layout system.
 | 
			
		||||
@ -348,9 +311,10 @@ impl Default for ButtonBundle {
 | 
			
		||||
            style: Default::default(),
 | 
			
		||||
            interaction: Default::default(),
 | 
			
		||||
            focus_policy: FocusPolicy::Block,
 | 
			
		||||
            border_color: BorderColor(Color::NONE),
 | 
			
		||||
            border_radius: BorderRadius::default(),
 | 
			
		||||
            border_color: Default::default(),
 | 
			
		||||
            border_radius: Default::default(),
 | 
			
		||||
            image: Default::default(),
 | 
			
		||||
            background_color: Default::default(),
 | 
			
		||||
            transform: Default::default(),
 | 
			
		||||
            global_transform: Default::default(),
 | 
			
		||||
            visibility: Default::default(),
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ use bevy_math::{Rect, Vec2};
 | 
			
		||||
use bevy_reflect::prelude::*;
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    camera::{Camera, RenderTarget},
 | 
			
		||||
    texture::Image,
 | 
			
		||||
    texture::{Image, TRANSPARENT_IMAGE_HANDLE},
 | 
			
		||||
};
 | 
			
		||||
use bevy_transform::prelude::GlobalTransform;
 | 
			
		||||
use bevy_utils::warn_once;
 | 
			
		||||
@ -1693,7 +1693,8 @@ pub enum GridPlacementError {
 | 
			
		||||
pub struct BackgroundColor(pub Color);
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
@ -1725,7 +1726,8 @@ impl<T: Into<Color>> From<T> for 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 {
 | 
			
		||||
@ -1819,12 +1821,17 @@ impl Outline {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The 2D texture displayed for this UI node
 | 
			
		||||
#[derive(Component, Clone, Debug, Reflect, Default)]
 | 
			
		||||
#[derive(Component, Clone, Debug, Reflect)]
 | 
			
		||||
#[reflect(Component, Default)]
 | 
			
		||||
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,
 | 
			
		||||
    /// 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>,
 | 
			
		||||
    /// Whether the image should be flipped along its x-axis
 | 
			
		||||
    pub flip_x: bool,
 | 
			
		||||
@ -1832,14 +1839,49 @@ pub struct UiImage {
 | 
			
		||||
    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 {
 | 
			
		||||
    /// Create a new [`UiImage`] with the given texture.
 | 
			
		||||
    pub fn new(texture: Handle<Image>) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            texture,
 | 
			
		||||
            color: Color::WHITE,
 | 
			
		||||
            ..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
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    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_radius: BorderRadius::MAX,
 | 
			
		||||
            image: UiImage::default().with_color(Color::BLACK),
 | 
			
		||||
            background_color: Color::BLACK.into(),
 | 
			
		||||
            ..default()
 | 
			
		||||
        })
 | 
			
		||||
        .insert(ColorGradingOptionWidget {
 | 
			
		||||
 | 
			
		||||
@ -140,7 +140,7 @@ fn setup(
 | 
			
		||||
                        ..default()
 | 
			
		||||
                    },
 | 
			
		||||
                    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()
 | 
			
		||||
                },
 | 
			
		||||
            ))
 | 
			
		||||
 | 
			
		||||
@ -456,7 +456,7 @@ mod menu {
 | 
			
		||||
                            .spawn((
 | 
			
		||||
                                ButtonBundle {
 | 
			
		||||
                                    style: button_style.clone(),
 | 
			
		||||
                                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                    ..default()
 | 
			
		||||
                                },
 | 
			
		||||
                                MenuButtonAction::Play,
 | 
			
		||||
@ -477,7 +477,7 @@ mod menu {
 | 
			
		||||
                            .spawn((
 | 
			
		||||
                                ButtonBundle {
 | 
			
		||||
                                    style: button_style.clone(),
 | 
			
		||||
                                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                    ..default()
 | 
			
		||||
                                },
 | 
			
		||||
                                MenuButtonAction::Settings,
 | 
			
		||||
@ -498,7 +498,7 @@ mod menu {
 | 
			
		||||
                            .spawn((
 | 
			
		||||
                                ButtonBundle {
 | 
			
		||||
                                    style: button_style,
 | 
			
		||||
                                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                    ..default()
 | 
			
		||||
                                },
 | 
			
		||||
                                MenuButtonAction::Quit,
 | 
			
		||||
@ -567,7 +567,7 @@ mod menu {
 | 
			
		||||
                                .spawn((
 | 
			
		||||
                                    ButtonBundle {
 | 
			
		||||
                                        style: button_style.clone(),
 | 
			
		||||
                                        image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                        background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                        ..default()
 | 
			
		||||
                                    },
 | 
			
		||||
                                    action,
 | 
			
		||||
@ -654,7 +654,7 @@ mod menu {
 | 
			
		||||
                                                height: Val::Px(65.0),
 | 
			
		||||
                                                ..button_style.clone()
 | 
			
		||||
                                            },
 | 
			
		||||
                                            image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                            background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                            ..default()
 | 
			
		||||
                                        },
 | 
			
		||||
                                        quality_setting,
 | 
			
		||||
@ -675,7 +675,7 @@ mod menu {
 | 
			
		||||
                            .spawn((
 | 
			
		||||
                                ButtonBundle {
 | 
			
		||||
                                    style: button_style,
 | 
			
		||||
                                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                    ..default()
 | 
			
		||||
                                },
 | 
			
		||||
                                MenuButtonAction::BackToSettings,
 | 
			
		||||
@ -750,7 +750,7 @@ mod menu {
 | 
			
		||||
                                                height: Val::Px(65.0),
 | 
			
		||||
                                                ..button_style.clone()
 | 
			
		||||
                                            },
 | 
			
		||||
                                            image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                            background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                            ..default()
 | 
			
		||||
                                        },
 | 
			
		||||
                                        Volume(volume_setting),
 | 
			
		||||
@ -764,7 +764,7 @@ mod menu {
 | 
			
		||||
                            .spawn((
 | 
			
		||||
                                ButtonBundle {
 | 
			
		||||
                                    style: button_style,
 | 
			
		||||
                                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                                    ..default()
 | 
			
		||||
                                },
 | 
			
		||||
                                MenuButtonAction::BackToSettings,
 | 
			
		||||
 | 
			
		||||
@ -125,7 +125,6 @@ fn setup_scene(
 | 
			
		||||
                    bottom: Val::Px(50.0),
 | 
			
		||||
                    ..default()
 | 
			
		||||
                },
 | 
			
		||||
                image: UiImage::default().with_color(Color::NONE),
 | 
			
		||||
                ..default()
 | 
			
		||||
            },
 | 
			
		||||
            BackgroundColor(Color::WHITE),
 | 
			
		||||
 | 
			
		||||
@ -363,7 +363,7 @@ mod ui {
 | 
			
		||||
                                align_items: AlignItems::Center,
 | 
			
		||||
                                ..default()
 | 
			
		||||
                            },
 | 
			
		||||
                            image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                            background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                            ..default()
 | 
			
		||||
                        },
 | 
			
		||||
                        MenuButton::Play,
 | 
			
		||||
@ -391,10 +391,11 @@ mod ui {
 | 
			
		||||
                                align_items: AlignItems::Center,
 | 
			
		||||
                                ..default()
 | 
			
		||||
                            },
 | 
			
		||||
                            image: UiImage::default().with_color(match tutorial_state.get() {
 | 
			
		||||
                            background_color: match tutorial_state.get() {
 | 
			
		||||
                                TutorialState::Active => ACTIVE_BUTTON,
 | 
			
		||||
                                TutorialState::Inactive => NORMAL_BUTTON,
 | 
			
		||||
                            }),
 | 
			
		||||
                            }
 | 
			
		||||
                            .into(),
 | 
			
		||||
                            ..default()
 | 
			
		||||
                        },
 | 
			
		||||
                        MenuButton::Tutorial,
 | 
			
		||||
 | 
			
		||||
@ -270,7 +270,7 @@ fn setup_menu(mut commands: Commands) {
 | 
			
		||||
                        align_items: AlignItems::Center,
 | 
			
		||||
                        ..default()
 | 
			
		||||
                    },
 | 
			
		||||
                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                    ..default()
 | 
			
		||||
                })
 | 
			
		||||
                .with_children(|parent| {
 | 
			
		||||
 | 
			
		||||
@ -74,7 +74,7 @@ fn setup_menu(mut commands: Commands) {
 | 
			
		||||
                        align_items: AlignItems::Center,
 | 
			
		||||
                        ..default()
 | 
			
		||||
                    },
 | 
			
		||||
                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                    ..default()
 | 
			
		||||
                })
 | 
			
		||||
                .with_children(|parent| {
 | 
			
		||||
 | 
			
		||||
@ -180,7 +180,7 @@ mod ui {
 | 
			
		||||
                            align_items: AlignItems::Center,
 | 
			
		||||
                            ..default()
 | 
			
		||||
                        },
 | 
			
		||||
                        image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                        background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                        ..default()
 | 
			
		||||
                    })
 | 
			
		||||
                    .with_children(|parent| {
 | 
			
		||||
 | 
			
		||||
@ -246,7 +246,7 @@ fn spawn_button(
 | 
			
		||||
                border,
 | 
			
		||||
                ..default()
 | 
			
		||||
            },
 | 
			
		||||
            image: UiImage::default().with_color(background_color),
 | 
			
		||||
            background_color: background_color.into(),
 | 
			
		||||
            border_color,
 | 
			
		||||
            ..default()
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
@ -75,7 +75,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
 | 
			
		||||
                    },
 | 
			
		||||
                    border_color: BorderColor(Color::BLACK),
 | 
			
		||||
                    border_radius: BorderRadius::MAX,
 | 
			
		||||
                    image: UiImage::default().with_color(NORMAL_BUTTON),
 | 
			
		||||
                    background_color: NORMAL_BUTTON.into(),
 | 
			
		||||
                    ..default()
 | 
			
		||||
                })
 | 
			
		||||
                .with_children(|parent| {
 | 
			
		||||
 | 
			
		||||
@ -415,7 +415,7 @@ where
 | 
			
		||||
                    padding: UiRect::axes(Val::Px(5.), Val::Px(1.)),
 | 
			
		||||
                    ..Default::default()
 | 
			
		||||
                },
 | 
			
		||||
                image: UiImage::default().with_color(Color::BLACK.with_alpha(0.5)),
 | 
			
		||||
                background_color: Color::BLACK.with_alpha(0.5).into(),
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            },
 | 
			
		||||
            Target::<T>::new(target),
 | 
			
		||||
 | 
			
		||||
@ -245,11 +245,12 @@ fn spawn_button(
 | 
			
		||||
                    margin: UiRect::horizontal(Val::Px(2.)),
 | 
			
		||||
                    ..Default::default()
 | 
			
		||||
                },
 | 
			
		||||
                image: UiImage::default().with_color(if active {
 | 
			
		||||
                background_color: if active {
 | 
			
		||||
                    ACTIVE_BORDER_COLOR
 | 
			
		||||
                } else {
 | 
			
		||||
                    INACTIVE_BORDER_COLOR
 | 
			
		||||
                }),
 | 
			
		||||
                }
 | 
			
		||||
                .into(),
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            },
 | 
			
		||||
            constraint,
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
 | 
			
		||||
                        align_items: AlignItems::Center,
 | 
			
		||||
                        ..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()
 | 
			
		||||
                })
 | 
			
		||||
                .with_children(|parent| {
 | 
			
		||||
@ -63,7 +63,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
 | 
			
		||||
                        align_items: AlignItems::Center,
 | 
			
		||||
                        ..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()
 | 
			
		||||
                })
 | 
			
		||||
                .with_children(|parent| {
 | 
			
		||||
 | 
			
		||||
@ -54,10 +54,10 @@ fn setup(
 | 
			
		||||
                        ..default()
 | 
			
		||||
                    },
 | 
			
		||||
                    image: UiImage::new(texture_handle),
 | 
			
		||||
                    background_color: BackgroundColor(ANTIQUE_WHITE.into()),
 | 
			
		||||
                    ..default()
 | 
			
		||||
                },
 | 
			
		||||
                TextureAtlas::from(texture_atlas_handle),
 | 
			
		||||
                BackgroundColor(ANTIQUE_WHITE.into()),
 | 
			
		||||
                Outline::new(Val::Px(8.0), Val::ZERO, CRIMSON.into()),
 | 
			
		||||
            ));
 | 
			
		||||
            parent.spawn(TextBundle::from_sections([
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user