From 21e90c83f765efb26dc5d1196b07fb7e1696bcbc Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 25 Jun 2024 13:40:42 -0400 Subject: [PATCH 01/13] Use `NONE` as the default UI image color --- crates/bevy_ui/src/ui_node.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 75852e78ee212..4aae62a67e3d6 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1,6 +1,6 @@ use crate::{UiRect, Val}; use bevy_asset::Handle; -use bevy_color::Color; +use bevy_color::{Color, LinearRgba}; use bevy_ecs::{prelude::*, system::SystemParam}; use bevy_math::{Rect, Vec2}; use bevy_reflect::prelude::*; @@ -1819,7 +1819,7 @@ 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 @@ -1832,6 +1832,19 @@ pub struct UiImage { pub flip_y: bool, } +impl Default for UiImage { + /// A solid square, with [`LinearRgba::NONE`] as its color. + fn default() -> Self { + UiImage { + // This needs to be transparent by default, to avoid covering the background color + color: Color::from(LinearRgba::NONE), + texture: Handle::default(), + flip_x: false, + flip_y: false, + } + } +} + impl UiImage { pub fn new(texture: Handle) -> Self { Self { From 09c1b1e6d417277b7e829d9a7703bf8328f2386e Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 25 Jun 2024 13:44:28 -0400 Subject: [PATCH 02/13] Default to transparent white instead --- crates/bevy_ui/src/ui_node.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 4aae62a67e3d6..e20098f99f86d 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1833,11 +1833,13 @@ pub struct UiImage { } impl Default for UiImage { - /// A solid square, with [`LinearRgba::NONE`] as its color. + /// A solid square, with a transparent white color. fn default() -> Self { UiImage { // This needs to be transparent by default, to avoid covering the background color - color: Color::from(LinearRgba::NONE), + // 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::from(LinearRgba::new(1.0, 1.0, 1.0, 0.0)), texture: Handle::default(), flip_x: false, flip_y: false, From 6f0c3ddef77c75f7f1c991303d38a8dd6811468e Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 25 Jun 2024 13:47:23 -0400 Subject: [PATCH 03/13] Refine API --- crates/bevy_ui/src/ui_node.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index e20098f99f86d..82fe3add2953f 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1822,7 +1822,12 @@ impl Outline { #[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. + /// + /// # Warning + /// + /// This defaults to transparent white, + /// so if you set a texture with the default tint it won't show up! pub color: Color, /// Handle to the texture pub texture: Handle, @@ -1848,13 +1853,27 @@ impl Default for UiImage { } impl UiImage { + /// Create a new [`UiImage`] with the given texture. pub fn new(texture: Handle) -> 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 { From a18c5e3708344fa99db738d08195cdf716a83596 Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 25 Jun 2024 13:49:15 -0400 Subject: [PATCH 04/13] Make BackgroundColor transparent by default --- crates/bevy_ui/src/ui_node.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 82fe3add2953f..90f6e96978763 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -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 { From 5811cbe1cd0ee042d1231e527e6ecbf375a418a2 Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 25 Jun 2024 14:02:14 -0400 Subject: [PATCH 05/13] Make BorderColor transparent by default --- crates/bevy_ui/src/ui_node.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 90f6e96978763..27d7bbdae7137 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1726,7 +1726,8 @@ impl> From 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 { From 305f0576eb6ceb8bc6b8a96082c0e4701c4ae06f Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 25 Jun 2024 14:04:12 -0400 Subject: [PATCH 06/13] Don't override default BorderColor and BackgroundColor --- crates/bevy_ui/src/node_bundles.rs | 51 +++--------------------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/crates/bevy_ui/src/node_bundles.rs b/crates/bevy_ui/src/node_bundles.rs index 89d4ecfced791..063719d3678c7 100644 --- a/crates/bevy_ui/src/node_bundles.rs +++ b/crates/bevy_ui/src/node_bundles.rs @@ -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 @@ -176,7 +156,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 +194,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. @@ -348,8 +305,8 @@ 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(), transform: Default::default(), global_transform: Default::default(), From c887fe9c109dd3c24419611275b196b9c0c7ec38 Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 25 Jun 2024 14:38:08 -0400 Subject: [PATCH 07/13] Add BackgroundColor to ImageBundle --- crates/bevy_ui/src/node_bundles.rs | 6 +++++- examples/ui/ui_texture_atlas.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ui/src/node_bundles.rs b/crates/bevy_ui/src/node_bundles.rs index 063719d3678c7..1190cb595dfb1 100644 --- a/crates/bevy_ui/src/node_bundles.rs +++ b/crates/bevy_ui/src/node_bundles.rs @@ -74,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 diff --git a/examples/ui/ui_texture_atlas.rs b/examples/ui/ui_texture_atlas.rs index 947cdecf90d86..3caa9d6616938 100644 --- a/examples/ui/ui_texture_atlas.rs +++ b/examples/ui/ui_texture_atlas.rs @@ -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([ From df678bf0e3a87fd976ff8930ac25a35ad6f34e0e Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 25 Jun 2024 16:01:51 -0400 Subject: [PATCH 08/13] Strengthen warning --- crates/bevy_ui/src/ui_node.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 27d7bbdae7137..d4de8408477f6 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1821,15 +1821,17 @@ impl Outline { } /// The 2D texture displayed for this UI node +/// +/// # Warning +/// +/// The default `color` which controls the tint of the image is fully transparent: +/// adding a texture with this default tint won't show up! +/// To fix this, the `color` should be set to [`Color::WHITE`], +/// or `UiImage::new` should be used. #[derive(Component, Clone, Debug, Reflect)] #[reflect(Component, Default)] pub struct UiImage { /// The tint color used to draw the image. - /// - /// # Warning - /// - /// This defaults to transparent white, - /// so if you set a texture with the default tint it won't show up! pub color: Color, /// Handle to the texture pub texture: Handle, @@ -1841,6 +1843,10 @@ pub struct UiImage { impl Default for UiImage { /// A solid square, with a transparent white color. + /// + /// # Warning + /// + /// This will be invisible by default. fn default() -> Self { UiImage { // This needs to be transparent by default, to avoid covering the background color From 9fd21e3da63bb89d1104de48b20bdb1a14592dfd Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 25 Jun 2024 16:06:19 -0400 Subject: [PATCH 09/13] Add BackgroundColor to ButtonBundle --- crates/bevy_ui/src/node_bundles.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_ui/src/node_bundles.rs b/crates/bevy_ui/src/node_bundles.rs index 1190cb595dfb1..42e7517487803 100644 --- a/crates/bevy_ui/src/node_bundles.rs +++ b/crates/bevy_ui/src/node_bundles.rs @@ -282,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. @@ -312,6 +314,7 @@ impl Default for ButtonBundle { 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(), From 63d2654f143d0b22c58246a1efce61b0385e1ceb Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 25 Jun 2024 16:13:18 -0400 Subject: [PATCH 10/13] Don't use UiImage to set background colors in examples --- examples/3d/color_grading.rs | 2 +- examples/3d/split_screen.rs | 2 +- examples/games/game_menu.rs | 16 ++++++++-------- examples/mobile/src/lib.rs | 1 - examples/state/computed_states.rs | 7 ++++--- examples/state/custom_transitions.rs | 2 +- examples/state/states.rs | 2 +- examples/state/sub_states.rs | 2 +- examples/stress_tests/many_buttons.rs | 2 +- examples/ui/button.rs | 2 +- examples/ui/display_and_visibility.rs | 2 +- examples/ui/size_constraints.rs | 5 +++-- examples/ui/transparency_ui.rs | 4 ++-- 13 files changed, 25 insertions(+), 24 deletions(-) diff --git a/examples/3d/color_grading.rs b/examples/3d/color_grading.rs index aa4ceea8cd110..42cb0ae16323c 100644 --- a/examples/3d/color_grading.rs +++ b/examples/3d/color_grading.rs @@ -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 { diff --git a/examples/3d/split_screen.rs b/examples/3d/split_screen.rs index df2b109db1fcd..a5e93fc14e8b1 100644 --- a/examples/3d/split_screen.rs +++ b/examples/3d/split_screen.rs @@ -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() }, )) diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index 60d8d5e3493f4..f93c258a62d93 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -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, diff --git a/examples/mobile/src/lib.rs b/examples/mobile/src/lib.rs index 122710733c3c6..14e929cab08e5 100644 --- a/examples/mobile/src/lib.rs +++ b/examples/mobile/src/lib.rs @@ -125,7 +125,6 @@ fn setup_scene( bottom: Val::Px(50.0), ..default() }, - image: UiImage::default().with_color(Color::NONE), ..default() }, BackgroundColor(Color::WHITE), diff --git a/examples/state/computed_states.rs b/examples/state/computed_states.rs index 38b0659d1c76f..9179cb884aaa6 100644 --- a/examples/state/computed_states.rs +++ b/examples/state/computed_states.rs @@ -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, diff --git a/examples/state/custom_transitions.rs b/examples/state/custom_transitions.rs index 0d578ea0523dd..f87d617b2e023 100644 --- a/examples/state/custom_transitions.rs +++ b/examples/state/custom_transitions.rs @@ -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| { diff --git a/examples/state/states.rs b/examples/state/states.rs index ef329b0baa6e4..4f029d8f36e9b 100644 --- a/examples/state/states.rs +++ b/examples/state/states.rs @@ -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| { diff --git a/examples/state/sub_states.rs b/examples/state/sub_states.rs index 1190315967194..64219d893a80c 100644 --- a/examples/state/sub_states.rs +++ b/examples/state/sub_states.rs @@ -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| { diff --git a/examples/stress_tests/many_buttons.rs b/examples/stress_tests/many_buttons.rs index 03fad2bc865ba..63855c17332cd 100644 --- a/examples/stress_tests/many_buttons.rs +++ b/examples/stress_tests/many_buttons.rs @@ -246,7 +246,7 @@ fn spawn_button( border, ..default() }, - image: UiImage::default().with_color(background_color), + background_color: background_color.into(), border_color, ..default() }, diff --git a/examples/ui/button.rs b/examples/ui/button.rs index c00242fc88a2a..e13eb024cd35f 100644 --- a/examples/ui/button.rs +++ b/examples/ui/button.rs @@ -75,7 +75,7 @@ fn setup(mut commands: Commands, asset_server: Res) { }, 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| { diff --git a/examples/ui/display_and_visibility.rs b/examples/ui/display_and_visibility.rs index 2f07d9b6da947..b72f016320543 100644 --- a/examples/ui/display_and_visibility.rs +++ b/examples/ui/display_and_visibility.rs @@ -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::::new(target), diff --git a/examples/ui/size_constraints.rs b/examples/ui/size_constraints.rs index d32fe9734c698..dc2890bed8f73 100644 --- a/examples/ui/size_constraints.rs +++ b/examples/ui/size_constraints.rs @@ -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, diff --git a/examples/ui/transparency_ui.rs b/examples/ui/transparency_ui.rs index 92c27059d5fc5..f83d2ba215c84 100644 --- a/examples/ui/transparency_ui.rs +++ b/examples/ui/transparency_ui.rs @@ -37,7 +37,7 @@ fn setup(mut commands: Commands, asset_server: Res) { 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) { 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| { From d62529e41e0add38b46e39596f1f1cd32422540e Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 25 Jun 2024 16:23:25 -0400 Subject: [PATCH 11/13] Balance in all things, especially backticks --- crates/bevy_ui/src/ui_node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index d4de8408477f6..1e5e5d627f9d9 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1870,7 +1870,7 @@ impl UiImage { } } - /// Create a solid color [`UiImage`]`. + /// Create a solid color [`UiImage`]. /// /// This is primarily useful for debugging / mocking the extents of your image. pub fn solid_color(color: Color) -> Self { From d308fb70ce5736d709bac6c43df2aebd4382d424 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 25 Jun 2024 17:17:00 -0400 Subject: [PATCH 12/13] Use a default transparent image --- crates/bevy_render/src/texture/image.rs | 32 +++++++++++++++++++++++++ crates/bevy_render/src/texture/mod.rs | 16 ++++++++++--- crates/bevy_ui/src/ui_node.rs | 28 +++++++++++----------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/crates/bevy_render/src/texture/image.rs b/crates/bevy_render/src/texture/image.rs index b11f7937d968a..d1a63fc817350 100644 --- a/crates/bevy_render/src/texture/image.rs +++ b/crates/bevy_render/src/texture/image.rs @@ -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. /// diff --git a/crates/bevy_render/src/texture/mod.rs b/crates/bevy_render/src/texture/mod.rs index ac5d74cdc73b8..37dad6d12eac1 100644 --- a/crates/bevy_render/src/texture/mod.rs +++ b/crates/bevy_render/src/texture/mod.rs @@ -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::default`], this is a handle to a fallaback image asset. +/// While that handle points to an opaque white 1 x 1 image, this handle points to a 1 x 1 transparent white image. +// Number randomly selected by fair WolframAlpha query. Totally arbitrary. +pub const TRANSPARENT_IMAGE_HANDLE: Handle = + 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::() .register_asset_reflect::(); - app.world_mut() - .resource_mut::>() - .insert(&Handle::default(), Image::default()); + let mut image_assets = app.world_mut().resource_mut::>(); + + 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() diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 1e5e5d627f9d9..016840a405829 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1,12 +1,12 @@ use crate::{UiRect, Val}; use bevy_asset::Handle; -use bevy_color::{Color, LinearRgba}; +use bevy_color::Color; use bevy_ecs::{prelude::*, system::SystemParam}; 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; @@ -1821,19 +1821,17 @@ impl Outline { } /// The 2D texture displayed for this UI node -/// -/// # Warning -/// -/// The default `color` which controls the tint of the image is fully transparent: -/// adding a texture with this default tint won't show up! -/// To fix this, the `color` should be set to [`Color::WHITE`], -/// or `UiImage::new` should be used. #[derive(Component, Clone, Debug, Reflect)] #[reflect(Component, Default)] pub struct UiImage { /// 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 fully transparent 1x1 texture. pub texture: Handle, /// Whether the image should be flipped along its x-axis pub flip_x: bool, @@ -1842,18 +1840,20 @@ pub struct UiImage { } impl Default for UiImage { - /// A solid square, with a transparent white color. + /// 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`]'s default 1x1 solid white texture. fn default() -> Self { UiImage { - // This needs to be transparent by default, to avoid covering the background color // 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::from(LinearRgba::new(1.0, 1.0, 1.0, 0.0)), - texture: Handle::default(), + 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, } From d2b1266b64735fe7f2c9ae2f226ae0808da1bc7a Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 25 Jun 2024 17:42:01 -0400 Subject: [PATCH 13/13] Apply suggestions from code review --- crates/bevy_render/src/texture/mod.rs | 4 ++-- crates/bevy_ui/src/ui_node.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_render/src/texture/mod.rs b/crates/bevy_render/src/texture/mod.rs index 37dad6d12eac1..9b1a592773409 100644 --- a/crates/bevy_render/src/texture/mod.rs +++ b/crates/bevy_render/src/texture/mod.rs @@ -45,8 +45,8 @@ use bevy_ecs::prelude::*; /// A handle to a 1 x 1 transparent white image. /// -/// Like [`Handle::default`], this is a handle to a fallaback image asset. -/// While that handle points to an opaque white 1 x 1 image, this handle points to a 1 x 1 transparent white image. +/// Like [`Handle::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 = Handle::weak_from_u128(154728948001857810431816125397303024160); diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 016840a405829..95166fed1c261 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1831,7 +1831,7 @@ pub struct UiImage { pub color: Color, /// Handle to the texture. /// - /// This defaults to a fully transparent 1x1 texture. + /// This defaults to a [`TRANSPARENT_IMAGE_HANDLE`], which points to a fully transparent 1x1 texture. pub texture: Handle, /// Whether the image should be flipped along its x-axis pub flip_x: bool, @@ -1846,7 +1846,7 @@ impl Default for UiImage { /// /// 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`]'s default 1x1 solid white texture. + /// or use [`Handle`]'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,