From 86ee8e4376b897ebfb2c689311cdaa6f41375a9f Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Sun, 27 Oct 2024 19:14:46 +0000 Subject: [PATCH] Move `UiImage` from `ui_node` to the `widget::image` module (#16084) # Objective `UiImage` isn't just a general image component now, it's the defining component for the image widget so it belongs in the image widget's module. --- crates/bevy_ui/src/accessibility.rs | 4 +- crates/bevy_ui/src/lib.rs | 4 +- crates/bevy_ui/src/render/mod.rs | 3 +- .../src/render/ui_texture_slice_pipeline.rs | 1 + crates/bevy_ui/src/ui_node.rs | 124 +---------------- crates/bevy_ui/src/widget/image.rs | 129 +++++++++++++++++- 6 files changed, 133 insertions(+), 132 deletions(-) diff --git a/crates/bevy_ui/src/accessibility.rs b/crates/bevy_ui/src/accessibility.rs index 85a8f0c547..6cf3e73d93 100644 --- a/crates/bevy_ui/src/accessibility.rs +++ b/crates/bevy_ui/src/accessibility.rs @@ -1,8 +1,8 @@ use crate::{ experimental::UiChildren, prelude::{Button, Label}, - widget::TextUiReader, - ComputedNode, UiImage, + widget::{TextUiReader, UiImage}, + ComputedNode, }; use bevy_a11y::{ accesskit::{NodeBuilder, Rect, Role}, diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index b0cdcddb83..15af4b3fe3 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -40,7 +40,7 @@ pub use measurement::*; pub use render::*; pub use ui_material::*; pub use ui_node::*; -use widget::UiImageSize; +use widget::{UiImage, UiImageSize}; /// The UI prelude. /// @@ -58,7 +58,7 @@ pub mod prelude { node_bundles::*, ui_material::*, ui_node::*, - widget::{Button, Label}, + widget::{Button, Label, UiImage}, Interaction, MaterialNode, UiMaterialPlugin, UiScale, }, // `bevy_sprite` re-exports for texture slicing diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 58369e0bc0..d9ca0eff96 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -4,10 +4,11 @@ mod render_pass; mod ui_material_pipeline; pub mod ui_texture_slice_pipeline; +use crate::widget::UiImage; use crate::{ experimental::UiChildren, BackgroundColor, BorderColor, CalculatedClip, ComputedNode, DefaultUiCamera, Outline, ResolvedBorderRadius, TargetCamera, UiAntiAlias, UiBoxShadowSamples, - UiImage, UiScale, + UiScale, }; use bevy_app::prelude::*; use bevy_asset::{load_internal_asset, AssetEvent, AssetId, Assets, Handle}; diff --git a/crates/bevy_ui/src/render/ui_texture_slice_pipeline.rs b/crates/bevy_ui/src/render/ui_texture_slice_pipeline.rs index a46dfbc6f8..afee144a2d 100644 --- a/crates/bevy_ui/src/render/ui_texture_slice_pipeline.rs +++ b/crates/bevy_ui/src/render/ui_texture_slice_pipeline.rs @@ -30,6 +30,7 @@ use bevy_transform::prelude::GlobalTransform; use bevy_utils::HashMap; use binding_types::{sampler, texture_2d}; use bytemuck::{Pod, Zeroable}; +use widget::UiImage; pub const UI_SLICER_SHADER_HANDLE: Handle = Handle::weak_from_u128(11156288772117983964); diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 88b950b7b4..20631927e1 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1,15 +1,13 @@ -use crate::{widget::UiImageSize, ContentSize, FocusPolicy, UiRect, Val}; -use bevy_asset::Handle; +use crate::{ContentSize, FocusPolicy, UiRect, Val}; use bevy_color::Color; use bevy_ecs::{prelude::*, system::SystemParam}; use bevy_math::{vec4, Rect, Vec2, Vec4Swizzles}; use bevy_reflect::prelude::*; use bevy_render::{ camera::{Camera, RenderTarget}, - texture::{Image, TRANSPARENT_IMAGE_HANDLE}, view::Visibility, }; -use bevy_sprite::{BorderRect, TextureAtlas}; +use bevy_sprite::BorderRect; use bevy_transform::components::Transform; use bevy_utils::warn_once; use bevy_window::{PrimaryWindow, WindowRef}; @@ -2040,124 +2038,6 @@ impl Outline { } } -/// The 2D texture displayed for this UI node -#[derive(Component, Clone, Debug, Reflect)] -#[reflect(Component, Default, Debug)] -#[require(Node, UiImageSize)] -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. - /// - /// This defaults to a [`TRANSPARENT_IMAGE_HANDLE`], which points to a fully transparent 1x1 texture. - pub image: Handle, - /// The (optional) texture atlas used to render the image - pub texture_atlas: Option, - /// Whether the image should be flipped along its x-axis - pub flip_x: bool, - /// Whether the image should be flipped along its y-axis - pub flip_y: bool, - /// An optional rectangle representing the region of the image to render, instead of rendering - /// the full image. This is an easy one-off alternative to using a [`TextureAtlas`]. - /// - /// When used with a [`TextureAtlas`], the rect - /// is offset by the atlas's minimal (top-left) corner position. - pub rect: Option, -} - -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`]'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, - texture_atlas: None, - // This texture needs to be transparent by default, to avoid covering the background color - image: TRANSPARENT_IMAGE_HANDLE, - flip_x: false, - flip_y: false, - rect: None, - } - } -} - -impl UiImage { - /// Create a new [`UiImage`] with the given texture. - pub fn new(texture: Handle) -> Self { - Self { - image: 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 { - image: Handle::default(), - color, - flip_x: false, - flip_y: false, - texture_atlas: None, - rect: None, - } - } - - /// Create a [`UiImage`] from an image, with an associated texture atlas - pub fn from_atlas_image(image: Handle, atlas: TextureAtlas) -> Self { - Self { - image, - texture_atlas: Some(atlas), - ..Default::default() - } - } - - /// Set the color tint - #[must_use] - pub const fn with_color(mut self, color: Color) -> Self { - self.color = color; - self - } - - /// Flip the image along its x-axis - #[must_use] - pub const fn with_flip_x(mut self) -> Self { - self.flip_x = true; - self - } - - /// Flip the image along its y-axis - #[must_use] - pub const fn with_flip_y(mut self) -> Self { - self.flip_y = true; - self - } - - #[must_use] - pub const fn with_rect(mut self, rect: Rect) -> Self { - self.rect = Some(rect); - self - } -} - -impl From> for UiImage { - fn from(texture: Handle) -> Self { - Self::new(texture) - } -} - /// The calculated clip of the node #[derive(Component, Default, Copy, Clone, Debug, Reflect)] #[reflect(Component, Default, Debug)] diff --git a/crates/bevy_ui/src/widget/image.rs b/crates/bevy_ui/src/widget/image.rs index 60a0ac5292..aaec16b869 100644 --- a/crates/bevy_ui/src/widget/image.rs +++ b/crates/bevy_ui/src/widget/image.rs @@ -1,13 +1,132 @@ -use crate::{ContentSize, Measure, MeasureArgs, Node, NodeMeasure, UiImage, UiScale}; -use bevy_asset::Assets; +use crate::{ContentSize, Measure, MeasureArgs, Node, NodeMeasure, UiScale}; +use bevy_asset::{Assets, Handle}; +use bevy_color::Color; use bevy_ecs::prelude::*; -use bevy_math::{UVec2, Vec2}; +use bevy_math::{Rect, UVec2, Vec2}; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; -use bevy_render::texture::Image; -use bevy_sprite::TextureAtlasLayout; +use bevy_render::texture::{Image, TRANSPARENT_IMAGE_HANDLE}; +use bevy_sprite::{TextureAtlas, TextureAtlasLayout}; use bevy_window::{PrimaryWindow, Window}; use taffy::{MaybeMath, MaybeResolve}; +/// The 2D texture displayed for this UI node +#[derive(Component, Clone, Debug, Reflect)] +#[reflect(Component, Default, Debug)] +#[require(Node, UiImageSize)] +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. + /// + /// This defaults to a [`TRANSPARENT_IMAGE_HANDLE`], which points to a fully transparent 1x1 texture. + pub image: Handle, + /// The (optional) texture atlas used to render the image + pub texture_atlas: Option, + /// Whether the image should be flipped along its x-axis + pub flip_x: bool, + /// Whether the image should be flipped along its y-axis + pub flip_y: bool, + /// An optional rectangle representing the region of the image to render, instead of rendering + /// the full image. This is an easy one-off alternative to using a [`TextureAtlas`]. + /// + /// When used with a [`TextureAtlas`], the rect + /// is offset by the atlas's minimal (top-left) corner position. + pub rect: Option, +} + +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`]'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, + texture_atlas: None, + // This texture needs to be transparent by default, to avoid covering the background color + image: TRANSPARENT_IMAGE_HANDLE, + flip_x: false, + flip_y: false, + rect: None, + } + } +} + +impl UiImage { + /// Create a new [`UiImage`] with the given texture. + pub fn new(texture: Handle) -> Self { + Self { + image: 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 { + image: Handle::default(), + color, + flip_x: false, + flip_y: false, + texture_atlas: None, + rect: None, + } + } + + /// Create a [`UiImage`] from an image, with an associated texture atlas + pub fn from_atlas_image(image: Handle, atlas: TextureAtlas) -> Self { + Self { + image, + texture_atlas: Some(atlas), + ..Default::default() + } + } + + /// Set the color tint + #[must_use] + pub const fn with_color(mut self, color: Color) -> Self { + self.color = color; + self + } + + /// Flip the image along its x-axis + #[must_use] + pub const fn with_flip_x(mut self) -> Self { + self.flip_x = true; + self + } + + /// Flip the image along its y-axis + #[must_use] + pub const fn with_flip_y(mut self) -> Self { + self.flip_y = true; + self + } + + #[must_use] + pub const fn with_rect(mut self, rect: Rect) -> Self { + self.rect = Some(rect); + self + } +} + +impl From> for UiImage { + fn from(texture: Handle) -> Self { + Self::new(texture) + } +} + /// The size of the image's texture /// /// This component is updated automatically by [`update_image_content_size_system`]