From 9aef71bd9bd9cd37b8d60409e446e0d7cd37ee1f Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 8 Oct 2024 19:07:58 +0000 Subject: [PATCH] Replace `Handle` component with `UiMaterialHandle` wrapper (#15740) # Objective - Closes #15720 ## Solution Wrap the handle in a new wrapper component: `UiMaterialHandle` It's not possible to match the naming convention of `MeshMaterial3d/2d` here with the trait already being called `UiMaterial` Should we consider renaming to `Material3d/2dHandle` and `Mesh3d/2d` to `Mesh3d/2dHandle`? - This shouldn't have any merge conflicts with #15591 ## Testing Tested the `ui_material` example ## Migration Guide Let's defer the migration guide to the required component port. I just want to yeet the `Component` impl on `Handle` in the meantime :) --- crates/bevy_ui/src/lib.rs | 2 +- crates/bevy_ui/src/node_bundles.rs | 5 +-- .../src/render/ui_material_pipeline.rs | 4 +- crates/bevy_ui/src/ui_material.rs | 42 +++++++++++++++++-- examples/ui/ui_material.rs | 6 +-- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index f0e0b58686265..af806e965aa63 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -50,7 +50,7 @@ pub mod prelude { pub use { crate::{ geometry::*, node_bundles::*, ui_material::*, ui_node::*, widget::Button, - widget::Label, Interaction, UiMaterialPlugin, UiScale, + widget::Label, Interaction, UiMaterialHandle, UiMaterialPlugin, UiScale, }, // `bevy_sprite` re-exports for texture slicing bevy_sprite::{BorderRect, ImageScaleMode, SliceScaleMode, TextureSlicer}, diff --git a/crates/bevy_ui/src/node_bundles.rs b/crates/bevy_ui/src/node_bundles.rs index faec98665dbe7..957a93024be85 100644 --- a/crates/bevy_ui/src/node_bundles.rs +++ b/crates/bevy_ui/src/node_bundles.rs @@ -3,9 +3,8 @@ use crate::{ widget::{Button, UiImageSize}, BackgroundColor, BorderColor, BorderRadius, ContentSize, FocusPolicy, Interaction, Node, - ScrollPosition, Style, UiImage, UiMaterial, ZIndex, + ScrollPosition, Style, UiImage, UiMaterial, UiMaterialHandle, ZIndex, }; -use bevy_asset::Handle; use bevy_ecs::bundle::Bundle; use bevy_render::view::{InheritedVisibility, ViewVisibility, Visibility}; use bevy_transform::prelude::{GlobalTransform, Transform}; @@ -294,7 +293,7 @@ pub struct MaterialNodeBundle { /// In some cases these styles also affect how the node drawn/painted. pub style: Style, /// The [`UiMaterial`] used to render the node. - pub material: Handle, + pub material: UiMaterialHandle, /// Whether this node should block interaction with lower nodes pub focus_policy: FocusPolicy, /// The transform of the node diff --git a/crates/bevy_ui/src/render/ui_material_pipeline.rs b/crates/bevy_ui/src/render/ui_material_pipeline.rs index 71cbb2dcb4fb0..ac2bb134e3d2c 100644 --- a/crates/bevy_ui/src/render/ui_material_pipeline.rs +++ b/crates/bevy_ui/src/render/ui_material_pipeline.rs @@ -60,7 +60,7 @@ where Shader::from_wgsl ); app.init_asset::().add_plugins(( - ExtractComponentPlugin::>::extract_visible(), + ExtractComponentPlugin::>::extract_visible(), RenderAssetPlugin::>::default(), )); @@ -364,7 +364,7 @@ pub fn extract_ui_material_nodes( ( &Node, &GlobalTransform, - &Handle, + &UiMaterialHandle, &ViewVisibility, Option<&CalculatedClip>, Option<&TargetCamera>, diff --git a/crates/bevy_ui/src/ui_material.rs b/crates/bevy_ui/src/ui_material.rs index 68d727cdb88f7..4c5a788d2fec0 100644 --- a/crates/bevy_ui/src/ui_material.rs +++ b/crates/bevy_ui/src/ui_material.rs @@ -1,7 +1,13 @@ use core::hash::Hash; -use bevy_asset::Asset; -use bevy_render::render_resource::{AsBindGroup, RenderPipelineDescriptor, ShaderRef}; +use bevy_asset::{Asset, AssetId, Handle}; +use bevy_derive::{Deref, DerefMut}; +use bevy_ecs::{component::Component, reflect::ReflectComponent}; +use bevy_reflect::{prelude::ReflectDefault, Reflect}; +use bevy_render::{ + extract_component::ExtractComponent, + render_resource::{AsBindGroup, RenderPipelineDescriptor, ShaderRef}, +}; /// Materials are used alongside [`UiMaterialPlugin`](crate::UiMaterialPlugin) and [`MaterialNodeBundle`](crate::prelude::MaterialNodeBundle) /// to spawn entities that are rendered with a specific [`UiMaterial`] type. They serve as an easy to use high level @@ -56,10 +62,10 @@ use bevy_render::render_resource::{AsBindGroup, RenderPipelineDescriptor, Shader /// width: Val::Percent(100.0), /// ..Default::default() /// }, -/// material: materials.add(CustomMaterial { +/// material: UiMaterialHandle(materials.add(CustomMaterial { /// color: LinearRgba::RED, /// color_texture: asset_server.load("some_image.png"), -/// }), +/// })), /// ..Default::default() /// }); /// } @@ -145,3 +151,31 @@ where self.bind_group_data.hash(state); } } + +#[derive(Component, Clone, Debug, Deref, DerefMut, Reflect, PartialEq, Eq, ExtractComponent)] +#[reflect(Component, Default)] +pub struct UiMaterialHandle(pub Handle); + +impl Default for UiMaterialHandle { + fn default() -> Self { + Self(Handle::default()) + } +} + +impl From> for UiMaterialHandle { + fn from(handle: Handle) -> Self { + Self(handle) + } +} + +impl From> for AssetId { + fn from(material: UiMaterialHandle) -> Self { + material.id() + } +} + +impl From<&UiMaterialHandle> for AssetId { + fn from(material: &UiMaterialHandle) -> Self { + material.id() + } +} diff --git a/examples/ui/ui_material.rs b/examples/ui/ui_material.rs index 7ab11f39bb625..5a8cf3fdeb915 100644 --- a/examples/ui/ui_material.rs +++ b/examples/ui/ui_material.rs @@ -43,12 +43,12 @@ fn setup( border: UiRect::all(Val::Px(10.)), ..default() }, - material: ui_materials.add(CustomUiMaterial { + material: UiMaterialHandle(ui_materials.add(CustomUiMaterial { color: LinearRgba::WHITE.to_f32_array().into(), slider: 0.5, color_texture: asset_server.load("branding/banner.png"), border_color: LinearRgba::WHITE.to_f32_array().into(), - }), + })), ..default() }); }); @@ -82,7 +82,7 @@ impl UiMaterial for CustomUiMaterial { // Also updates the color of the image to a rainbow color fn animate( mut materials: ResMut>, - q: Query<&Handle>, + q: Query<&UiMaterialHandle>, time: Res