diff --git a/crates/bevy_anti_aliasing/src/smaa/mod.rs b/crates/bevy_anti_aliasing/src/smaa/mod.rs index 3996f389d0..bc6feca267 100644 --- a/crates/bevy_anti_aliasing/src/smaa/mod.rs +++ b/crates/bevy_anti_aliasing/src/smaa/mod.rs @@ -32,7 +32,7 @@ use bevy_app::{App, Plugin}; #[cfg(feature = "smaa_luts")] use bevy_asset::load_internal_binary_asset; -use bevy_asset::{embedded_asset, load_embedded_asset, weak_handle, Handle}; +use bevy_asset::{embedded_asset, load_embedded_asset, uuid_handle, Handle}; #[cfg(not(feature = "smaa_luts"))] use bevy_core_pipeline::tonemapping::lut_placeholder; use bevy_core_pipeline::{ @@ -81,10 +81,10 @@ use bevy_utils::prelude::default; /// The handle of the area LUT, a KTX2 format texture that SMAA uses internally. const SMAA_AREA_LUT_TEXTURE_HANDLE: Handle = - weak_handle!("569c4d67-c7fa-4958-b1af-0836023603c0"); + uuid_handle!("569c4d67-c7fa-4958-b1af-0836023603c0"); /// The handle of the search LUT, a KTX2 format texture that SMAA uses internally. const SMAA_SEARCH_LUT_TEXTURE_HANDLE: Handle = - weak_handle!("43b97515-252e-4c8a-b9af-f2fc528a1c27"); + uuid_handle!("43b97515-252e-4c8a-b9af-f2fc528a1c27"); /// Adds support for subpixel morphological antialiasing, or SMAA. pub struct SmaaPlugin; diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index e6f00c7da5..b9a20a7af8 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -7,10 +7,12 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath}; use core::{ any::TypeId, hash::{Hash, Hasher}, + marker::PhantomData, }; use crossbeam_channel::{Receiver, Sender}; use disqualified::ShortName; use thiserror::Error; +use uuid::Uuid; /// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_. /// This should _only_ be used for one specific asset type. @@ -117,7 +119,7 @@ impl core::fmt::Debug for StrongHandle { /// avoiding the need to store multiple copies of the same data. /// /// If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept -/// alive until the [`Handle`] is dropped. If a [`Handle`] is [`Handle::Weak`], it does not necessarily reference a live [`Asset`], +/// alive until the [`Handle`] is dropped. If a [`Handle`] is [`Handle::Uuid`], it does not necessarily reference a live [`Asset`], /// nor will it keep assets alive. /// /// Modifying a *handle* will change which existing asset is referenced, but modifying the *asset* @@ -133,16 +135,16 @@ pub enum Handle { /// A "strong" reference to a live (or loading) [`Asset`]. If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept /// alive until the [`Handle`] is dropped. Strong handles also provide access to additional asset metadata. Strong(Arc), - /// A "weak" reference to an [`Asset`]. If a [`Handle`] is [`Handle::Weak`], it does not necessarily reference a live [`Asset`], - /// nor will it keep assets alive. - Weak(AssetId), + /// A reference to an [`Asset`] using a stable-across-runs / const identifier. Dropping this + /// handle will not result in the asset being dropped. + Uuid(Uuid, #[reflect(ignore, clone)] PhantomData A>), } impl Clone for Handle { fn clone(&self) -> Self { match self { Handle::Strong(handle) => Handle::Strong(handle.clone()), - Handle::Weak(id) => Handle::Weak(*id), + Handle::Uuid(uuid, ..) => Handle::Uuid(*uuid, PhantomData), } } } @@ -153,7 +155,7 @@ impl Handle { pub fn id(&self) -> AssetId { match self { Handle::Strong(handle) => handle.id.typed_unchecked(), - Handle::Weak(id) => *id, + Handle::Uuid(uuid, ..) => AssetId::Uuid { uuid: *uuid }, } } @@ -162,14 +164,14 @@ impl Handle { pub fn path(&self) -> Option<&AssetPath<'static>> { match self { Handle::Strong(handle) => handle.path.as_ref(), - Handle::Weak(_) => None, + Handle::Uuid(..) => None, } } - /// Returns `true` if this is a weak handle. + /// Returns `true` if this is a uuid handle. #[inline] - pub fn is_weak(&self) -> bool { - matches!(self, Handle::Weak(_)) + pub fn is_uuid(&self) -> bool { + matches!(self, Handle::Uuid(..)) } /// Returns `true` if this is a strong handle. @@ -178,18 +180,9 @@ impl Handle { matches!(self, Handle::Strong(_)) } - /// Creates a [`Handle::Weak`] clone of this [`Handle`], which will not keep the referenced [`Asset`] alive. - #[inline] - pub fn clone_weak(&self) -> Self { - match self { - Handle::Strong(handle) => Handle::Weak(handle.id.typed_unchecked::()), - Handle::Weak(id) => Handle::Weak(*id), - } - } - /// Converts this [`Handle`] to an "untyped" / "generic-less" [`UntypedHandle`], which stores the [`Asset`] type information - /// _inside_ [`UntypedHandle`]. This will return [`UntypedHandle::Strong`] for [`Handle::Strong`] and [`UntypedHandle::Weak`] for - /// [`Handle::Weak`]. + /// _inside_ [`UntypedHandle`]. This will return [`UntypedHandle::Strong`] for [`Handle::Strong`] and [`UntypedHandle::Uuid`] for + /// [`Handle::Uuid`]. #[inline] pub fn untyped(self) -> UntypedHandle { self.into() @@ -198,7 +191,7 @@ impl Handle { impl Default for Handle { fn default() -> Self { - Handle::Weak(AssetId::default()) + Handle::Uuid(AssetId::::DEFAULT_UUID, PhantomData) } } @@ -214,7 +207,7 @@ impl core::fmt::Debug for Handle { handle.path ) } - Handle::Weak(id) => write!(f, "WeakHandle<{name}>({:?})", id.internal()), + Handle::Uuid(uuid, ..) => write!(f, "UuidHandle<{name}>({uuid:?})"), } } } @@ -284,8 +277,13 @@ impl From<&mut Handle> for UntypedAssetId { pub enum UntypedHandle { /// A strong handle, which will keep the referenced [`Asset`] alive until all strong handles are dropped. Strong(Arc), - /// A weak handle, which does not keep the referenced [`Asset`] alive. - Weak(UntypedAssetId), + /// A UUID handle, which does not keep the referenced [`Asset`] alive. + Uuid { + /// An identifier that records the underlying asset type. + type_id: TypeId, + /// The UUID provided during asset registration. + uuid: Uuid, + }, } impl UntypedHandle { @@ -294,7 +292,10 @@ impl UntypedHandle { pub fn id(&self) -> UntypedAssetId { match self { UntypedHandle::Strong(handle) => handle.id, - UntypedHandle::Weak(id) => *id, + UntypedHandle::Uuid { type_id, uuid } => UntypedAssetId::Uuid { + uuid: *uuid, + type_id: *type_id, + }, } } @@ -303,16 +304,7 @@ impl UntypedHandle { pub fn path(&self) -> Option<&AssetPath<'static>> { match self { UntypedHandle::Strong(handle) => handle.path.as_ref(), - UntypedHandle::Weak(_) => None, - } - } - - /// Creates an [`UntypedHandle::Weak`] clone of this [`UntypedHandle`], which will not keep the referenced [`Asset`] alive. - #[inline] - pub fn clone_weak(&self) -> UntypedHandle { - match self { - UntypedHandle::Strong(handle) => UntypedHandle::Weak(handle.id), - UntypedHandle::Weak(id) => UntypedHandle::Weak(*id), + UntypedHandle::Uuid { .. } => None, } } @@ -321,7 +313,7 @@ impl UntypedHandle { pub fn type_id(&self) -> TypeId { match self { UntypedHandle::Strong(handle) => handle.id.type_id(), - UntypedHandle::Weak(id) => id.type_id(), + UntypedHandle::Uuid { type_id, .. } => *type_id, } } @@ -330,7 +322,7 @@ impl UntypedHandle { pub fn typed_unchecked(self) -> Handle { match self { UntypedHandle::Strong(handle) => Handle::Strong(handle), - UntypedHandle::Weak(id) => Handle::Weak(id.typed_unchecked::()), + UntypedHandle::Uuid { uuid, .. } => Handle::Uuid(uuid, PhantomData), } } @@ -345,10 +337,7 @@ impl UntypedHandle { TypeId::of::(), "The target Handle's TypeId does not match the TypeId of this UntypedHandle" ); - match self { - UntypedHandle::Strong(handle) => Handle::Strong(handle), - UntypedHandle::Weak(id) => Handle::Weak(id.typed_unchecked::()), - } + self.typed_unchecked() } /// Converts to a typed Handle. This will panic if the internal [`TypeId`] does not match the given asset type `A` @@ -376,7 +365,7 @@ impl UntypedHandle { pub fn meta_transform(&self) -> Option<&MetaTransform> { match self { UntypedHandle::Strong(handle) => handle.meta_transform.as_ref(), - UntypedHandle::Weak(_) => None, + UntypedHandle::Uuid { .. } => None, } } } @@ -409,12 +398,9 @@ impl core::fmt::Debug for UntypedHandle { handle.path ) } - UntypedHandle::Weak(id) => write!( - f, - "WeakHandle{{ type_id: {:?}, id: {:?} }}", - id.type_id(), - id.internal() - ), + UntypedHandle::Uuid { type_id, uuid } => { + write!(f, "UuidHandle{{ type_id: {type_id:?}, uuid: {uuid:?} }}",) + } } } } @@ -474,7 +460,10 @@ impl From> for UntypedHandle { fn from(value: Handle) -> Self { match value { Handle::Strong(handle) => UntypedHandle::Strong(handle), - Handle::Weak(id) => UntypedHandle::Weak(id.into()), + Handle::Uuid(uuid, _) => UntypedHandle::Uuid { + type_id: TypeId::of::(), + uuid, + }, } } } @@ -490,36 +479,37 @@ impl TryFrom for Handle { return Err(UntypedAssetConversionError::TypeIdMismatch { expected, found }); } - match value { - UntypedHandle::Strong(handle) => Ok(Handle::Strong(handle)), - UntypedHandle::Weak(id) => { - let Ok(id) = id.try_into() else { - return Err(UntypedAssetConversionError::TypeIdMismatch { expected, found }); - }; - Ok(Handle::Weak(id)) - } - } + Ok(match value { + UntypedHandle::Strong(handle) => Handle::Strong(handle), + UntypedHandle::Uuid { uuid, .. } => Handle::Uuid(uuid, PhantomData), + }) } } -/// Creates a weak [`Handle`] from a string literal containing a UUID. +/// Creates a [`Handle`] from a string literal containing a UUID. /// /// # Examples /// /// ``` -/// # use bevy_asset::{Handle, weak_handle}; +/// # use bevy_asset::{Handle, uuid_handle}; /// # type Shader = (); -/// const SHADER: Handle = weak_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac"); +/// const SHADER: Handle = uuid_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac"); /// ``` #[macro_export] -macro_rules! weak_handle { +macro_rules! uuid_handle { ($uuid:expr) => {{ - $crate::Handle::Weak($crate::AssetId::Uuid { - uuid: $crate::uuid::uuid!($uuid), - }) + $crate::Handle::Uuid($crate::uuid::uuid!($uuid), core::marker::PhantomData) }}; } +#[deprecated = "Use uuid_handle! instead"] +#[macro_export] +macro_rules! weak_handle { + ($uuid:expr) => { + uuid_handle!($uuid) + }; +} + /// Errors preventing the conversion of to/from an [`UntypedHandle`] and a [`Handle`]. #[derive(Error, Debug, PartialEq, Clone)] #[non_exhaustive] @@ -559,15 +549,12 @@ mod tests { /// Typed and Untyped `Handles` should be equivalent to each other and themselves #[test] fn equality() { - let typed = AssetId::::Uuid { uuid: UUID_1 }; - let untyped = UntypedAssetId::Uuid { + let typed = Handle::::Uuid(UUID_1, PhantomData); + let untyped = UntypedHandle::Uuid { type_id: TypeId::of::(), uuid: UUID_1, }; - let typed = Handle::Weak(typed); - let untyped = UntypedHandle::Weak(untyped); - assert_eq!( Ok(typed.clone()), Handle::::try_from(untyped.clone()) @@ -585,22 +572,17 @@ mod tests { fn ordering() { assert!(UUID_1 < UUID_2); - let typed_1 = AssetId::::Uuid { uuid: UUID_1 }; - let typed_2 = AssetId::::Uuid { uuid: UUID_2 }; - let untyped_1 = UntypedAssetId::Uuid { + let typed_1 = Handle::::Uuid(UUID_1, PhantomData); + let typed_2 = Handle::::Uuid(UUID_2, PhantomData); + let untyped_1 = UntypedHandle::Uuid { type_id: TypeId::of::(), uuid: UUID_1, }; - let untyped_2 = UntypedAssetId::Uuid { + let untyped_2 = UntypedHandle::Uuid { type_id: TypeId::of::(), uuid: UUID_2, }; - let typed_1 = Handle::Weak(typed_1); - let typed_2 = Handle::Weak(typed_2); - let untyped_1 = UntypedHandle::Weak(untyped_1); - let untyped_2 = UntypedHandle::Weak(untyped_2); - assert!(typed_1 < typed_2); assert!(untyped_1 < untyped_2); @@ -617,15 +599,12 @@ mod tests { /// Typed and Untyped `Handles` should be equivalently hashable to each other and themselves #[test] fn hashing() { - let typed = AssetId::::Uuid { uuid: UUID_1 }; - let untyped = UntypedAssetId::Uuid { + let typed = Handle::::Uuid(UUID_1, PhantomData); + let untyped = UntypedHandle::Uuid { type_id: TypeId::of::(), uuid: UUID_1, }; - let typed = Handle::Weak(typed); - let untyped = UntypedHandle::Weak(untyped); - assert_eq!( hash(&typed), hash(&Handle::::try_from(untyped.clone()).unwrap()) @@ -637,15 +616,12 @@ mod tests { /// Typed and Untyped `Handles` should be interchangeable #[test] fn conversion() { - let typed = AssetId::::Uuid { uuid: UUID_1 }; - let untyped = UntypedAssetId::Uuid { + let typed = Handle::::Uuid(UUID_1, PhantomData); + let untyped = UntypedHandle::Uuid { type_id: TypeId::of::(), uuid: UUID_1, }; - let typed = Handle::Weak(typed); - let untyped = UntypedHandle::Weak(untyped); - assert_eq!(typed, Handle::try_from(untyped.clone()).unwrap()); assert_eq!(UntypedHandle::from(typed.clone()), untyped); } diff --git a/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs b/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs index f7df3ad1b6..8bd7d92393 100644 --- a/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs +++ b/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs @@ -12,7 +12,7 @@ use crate::core_3d::{ prepare_core_3d_depth_textures, }; use bevy_app::{App, Plugin}; -use bevy_asset::{load_internal_asset, weak_handle, Handle}; +use bevy_asset::{load_internal_asset, uuid_handle, Handle}; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ component::Component, @@ -51,7 +51,7 @@ use tracing::debug; /// Identifies the `downsample_depth.wgsl` shader. pub const DOWNSAMPLE_DEPTH_SHADER_HANDLE: Handle = - weak_handle!("a09a149e-5922-4fa4-9170-3c1a13065364"); + uuid_handle!("a09a149e-5922-4fa4-9170-3c1a13065364"); /// The maximum number of mip levels that we can produce. /// diff --git a/crates/bevy_core_pipeline/src/post_process/mod.rs b/crates/bevy_core_pipeline/src/post_process/mod.rs index f7d2501b41..350ee1cfdd 100644 --- a/crates/bevy_core_pipeline/src/post_process/mod.rs +++ b/crates/bevy_core_pipeline/src/post_process/mod.rs @@ -3,7 +3,7 @@ //! Currently, this consists only of chromatic aberration. use bevy_app::{App, Plugin}; -use bevy_asset::{embedded_asset, load_embedded_asset, weak_handle, Assets, Handle}; +use bevy_asset::{embedded_asset, load_embedded_asset, uuid_handle, Assets, Handle}; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ component::Component, @@ -52,7 +52,7 @@ use crate::{ /// This is just a 3x1 image consisting of one red pixel, one green pixel, and /// one blue pixel, in that order. const DEFAULT_CHROMATIC_ABERRATION_LUT_HANDLE: Handle = - weak_handle!("dc3e3307-40a1-49bb-be6d-e0634e8836b2"); + uuid_handle!("dc3e3307-40a1-49bb-be6d-e0634e8836b2"); /// The default chromatic aberration intensity amount, in a fraction of the /// window size. diff --git a/crates/bevy_gizmos/src/retained.rs b/crates/bevy_gizmos/src/retained.rs index 88610b9744..4cc75f236d 100644 --- a/crates/bevy_gizmos/src/retained.rs +++ b/crates/bevy_gizmos/src/retained.rs @@ -149,7 +149,7 @@ pub(crate) fn extract_linegizmos( line_style: gizmo.line_config.style, line_joints: gizmo.line_config.joints, render_layers: render_layers.cloned().unwrap_or_default(), - handle: gizmo.handle.clone_weak(), + handle: gizmo.handle.clone(), }, MainEntity::from(entity), TemporaryRenderEntity, diff --git a/crates/bevy_pbr/src/decal/forward.rs b/crates/bevy_pbr/src/decal/forward.rs index 757ecff2c3..49767557e1 100644 --- a/crates/bevy_pbr/src/decal/forward.rs +++ b/crates/bevy_pbr/src/decal/forward.rs @@ -3,7 +3,7 @@ use crate::{ MaterialPlugin, StandardMaterial, }; use bevy_app::{App, Plugin}; -use bevy_asset::{weak_handle, Asset, Assets, Handle}; +use bevy_asset::{uuid_handle, Asset, Assets, Handle}; use bevy_ecs::component::Component; use bevy_math::{prelude::Rectangle, Quat, Vec2, Vec3}; use bevy_reflect::{Reflect, TypePath}; @@ -21,7 +21,7 @@ use bevy_render::{ }; const FORWARD_DECAL_MESH_HANDLE: Handle = - weak_handle!("afa817f9-1869-4e0c-ac0d-d8cd1552d38a"); + uuid_handle!("afa817f9-1869-4e0c-ac0d-d8cd1552d38a"); /// Plugin to render [`ForwardDecal`]s. pub struct ForwardDecalPlugin; diff --git a/crates/bevy_pbr/src/volumetric_fog/render.rs b/crates/bevy_pbr/src/volumetric_fog/render.rs index a5cd8e56f3..e15966e5e0 100644 --- a/crates/bevy_pbr/src/volumetric_fog/render.rs +++ b/crates/bevy_pbr/src/volumetric_fog/render.rs @@ -2,7 +2,7 @@ use core::array; -use bevy_asset::{load_embedded_asset, weak_handle, AssetId, Handle}; +use bevy_asset::{load_embedded_asset, uuid_handle, AssetId, Handle}; use bevy_color::ColorToComponents as _; use bevy_core_pipeline::{ core_3d::Camera3d, @@ -82,14 +82,14 @@ bitflags! { /// /// This mesh is simply stretched to the size of the framebuffer, as when the /// camera is inside a fog volume it's essentially a full-screen effect. -pub const PLANE_MESH: Handle = weak_handle!("92523617-c708-4fd0-b42f-ceb4300c930b"); +pub const PLANE_MESH: Handle = uuid_handle!("92523617-c708-4fd0-b42f-ceb4300c930b"); /// The cube mesh, which is used to render a fog volume that the camera is /// outside. /// /// Note that only the front faces of this cuboid will be rasterized in /// hardware. The back faces will be calculated in the shader via raytracing. -pub const CUBE_MESH: Handle = weak_handle!("4a1dd661-2d91-4377-a17a-a914e21e277e"); +pub const CUBE_MESH: Handle = uuid_handle!("4a1dd661-2d91-4377-a17a-a914e21e277e"); /// The total number of bind group layouts. /// diff --git a/crates/bevy_render/src/texture/mod.rs b/crates/bevy_render/src/texture/mod.rs index fe37dd4310..006ac2e5e8 100644 --- a/crates/bevy_render/src/texture/mod.rs +++ b/crates/bevy_render/src/texture/mod.rs @@ -21,7 +21,7 @@ use crate::{ render_asset::RenderAssetPlugin, renderer::RenderDevice, Render, RenderApp, RenderSystems, }; use bevy_app::{App, Plugin}; -use bevy_asset::{weak_handle, AssetApp, Assets, Handle}; +use bevy_asset::{uuid_handle, AssetApp, Assets, Handle}; use bevy_ecs::prelude::*; use tracing::warn; @@ -31,7 +31,7 @@ use tracing::warn; /// 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 = - weak_handle!("d18ad97e-a322-4981-9505-44c59a4b5e46"); + uuid_handle!("d18ad97e-a322-4981-9505-44c59a4b5e46"); // 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. diff --git a/crates/bevy_text/src/font_atlas_set.rs b/crates/bevy_text/src/font_atlas_set.rs index 8d32127c38..8f0dd91168 100644 --- a/crates/bevy_text/src/font_atlas_set.rs +++ b/crates/bevy_text/src/font_atlas_set.rs @@ -172,8 +172,8 @@ impl FontAtlasSet { .get_glyph_index(cache_key) .map(|location| GlyphAtlasInfo { location, - texture_atlas: atlas.texture_atlas.clone_weak(), - texture: atlas.texture.clone_weak(), + texture_atlas: atlas.texture_atlas.id(), + texture: atlas.texture.id(), }) }) }) diff --git a/crates/bevy_text/src/glyph.rs b/crates/bevy_text/src/glyph.rs index ebae713af4..5bc2111dbd 100644 --- a/crates/bevy_text/src/glyph.rs +++ b/crates/bevy_text/src/glyph.rs @@ -1,6 +1,6 @@ //! This module exports types related to rendering glyphs. -use bevy_asset::Handle; +use bevy_asset::AssetId; use bevy_image::prelude::*; use bevy_math::{IVec2, Vec2}; use bevy_reflect::Reflect; @@ -38,14 +38,15 @@ pub struct PositionedGlyph { #[derive(Debug, Clone, Reflect)] #[reflect(Clone)] pub struct GlyphAtlasInfo { - /// A handle to the [`Image`] data for the texture atlas this glyph was placed in. + /// An asset ID to the [`Image`] data for the texture atlas this glyph was placed in. /// - /// A (weak) clone of the handle held by the [`FontAtlas`](crate::FontAtlas). - pub texture: Handle, - /// A handle to the [`TextureAtlasLayout`] map for the texture atlas this glyph was placed in. + /// An asset ID of the handle held by the [`FontAtlas`](crate::FontAtlas). + pub texture: AssetId, + /// An asset ID to the [`TextureAtlasLayout`] map for the texture atlas this glyph was placed + /// in. /// - /// A (weak) clone of the handle held by the [`FontAtlas`](crate::FontAtlas). - pub texture_atlas: Handle, + /// An asset ID of the handle held by the [`FontAtlas`](crate::FontAtlas). + pub texture_atlas: AssetId, /// Location and offset of a glyph within the texture atlas. pub location: GlyphAtlasLocation, } diff --git a/crates/bevy_text/src/pipeline.rs b/crates/bevy_text/src/pipeline.rs index dd6ca77246..8c1136c063 100644 --- a/crates/bevy_text/src/pipeline.rs +++ b/crates/bevy_text/src/pipeline.rs @@ -340,7 +340,7 @@ impl TextPipeline { ) })?; - let texture_atlas = texture_atlases.get(&atlas_info.texture_atlas).unwrap(); + let texture_atlas = texture_atlases.get(atlas_info.texture_atlas).unwrap(); let location = atlas_info.location; let glyph_rect = texture_atlas.textures[location.glyph_index]; let left = location.offset.x as f32; diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index 8d4a926e1b..7fa3202d18 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -213,7 +213,7 @@ pub fn extract_text2d_sprite( current_span = *span_index; } let rect = texture_atlases - .get(&atlas_info.texture_atlas) + .get(atlas_info.texture_atlas) .unwrap() .textures[atlas_info.location.glyph_index] .as_rect(); @@ -232,7 +232,7 @@ pub fn extract_text2d_sprite( render_entity, transform, color, - image_handle_id: atlas_info.texture.id(), + image_handle_id: atlas_info.texture, flip_x: false, flip_y: false, kind: bevy_sprite::ExtractedSpriteKind::Slices { diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index dfff318f46..58de0c766a 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -865,7 +865,7 @@ pub fn extract_text_sections( ) in text_layout_info.glyphs.iter().enumerate() { let rect = texture_atlases - .get(&atlas_info.texture_atlas) + .get(atlas_info.texture_atlas) .unwrap() .textures[atlas_info.location.glyph_index] .as_rect(); @@ -891,7 +891,7 @@ pub fn extract_text_sections( z_order: uinode.stack_index as f32 + stack_z_offsets::TEXT, render_entity: commands.spawn(TemporaryRenderEntity).id(), color, - image: atlas_info.texture.id(), + image: atlas_info.texture, clip: clip.map(|clip| clip.clip), extracted_camera_entity, rect, @@ -956,7 +956,7 @@ pub fn extract_text_shadows( ) in text_layout_info.glyphs.iter().enumerate() { let rect = texture_atlases - .get(&atlas_info.texture_atlas) + .get(atlas_info.texture_atlas) .unwrap() .textures[atlas_info.location.glyph_index] .as_rect(); @@ -972,7 +972,7 @@ pub fn extract_text_shadows( z_order: uinode.stack_index as f32 + stack_z_offsets::TEXT, render_entity: commands.spawn(TemporaryRenderEntity).id(), color: shadow.color.into(), - image: atlas_info.texture.id(), + image: atlas_info.texture, clip: clip.map(|clip| clip.clip), extracted_camera_entity, rect, diff --git a/examples/2d/mesh2d_manual.rs b/examples/2d/mesh2d_manual.rs index 6354aa468c..80faa1a16c 100644 --- a/examples/2d/mesh2d_manual.rs +++ b/examples/2d/mesh2d_manual.rs @@ -6,7 +6,7 @@ //! [`Material2d`]: bevy::sprite::Material2d use bevy::{ - asset::weak_handle, + asset::uuid_handle, color::palettes::basic::YELLOW, core_pipeline::core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT}, math::{ops, FloatOrd}, @@ -287,7 +287,7 @@ pub struct ColoredMesh2dPlugin; /// Handle to the custom shader with a unique random ID pub const COLORED_MESH2D_SHADER_HANDLE: Handle = - weak_handle!("f48b148f-7373-4638-9900-392b3b3ccc66"); + uuid_handle!("f48b148f-7373-4638-9900-392b3b3ccc66"); /// Our custom pipeline needs its own instance storage #[derive(Resource, Deref, DerefMut, Default)] diff --git a/examples/shader/compute_shader_game_of_life.rs b/examples/shader/compute_shader_game_of_life.rs index cb7d283d1e..a4e255c67d 100644 --- a/examples/shader/compute_shader_game_of_life.rs +++ b/examples/shader/compute_shader_game_of_life.rs @@ -86,9 +86,9 @@ fn setup(mut commands: Commands, mut images: ResMut>) { // Switch texture to display every frame to show the one that was written to most recently. fn switch_textures(images: Res, mut sprite: Single<&mut Sprite>) { if sprite.image == images.texture_a { - sprite.image = images.texture_b.clone_weak(); + sprite.image = images.texture_b.clone(); } else { - sprite.image = images.texture_a.clone_weak(); + sprite.image = images.texture_a.clone(); } } diff --git a/examples/tools/scene_viewer/scene_viewer_plugin.rs b/examples/tools/scene_viewer/scene_viewer_plugin.rs index 49f4805d06..d3c5d2d74d 100644 --- a/examples/tools/scene_viewer/scene_viewer_plugin.rs +++ b/examples/tools/scene_viewer/scene_viewer_plugin.rs @@ -125,8 +125,7 @@ fn scene_load_check( maybe_directional_light.is_some() || maybe_point_light.is_some() }); - scene_handle.instance_id = - Some(scene_spawner.spawn(gltf_scene_handle.clone_weak())); + scene_handle.instance_id = Some(scene_spawner.spawn(gltf_scene_handle.clone())); info!("Spawning scene..."); } diff --git a/release-content/migration-guides/handle_weak_replaced_with_handle_uuid.md b/release-content/migration-guides/handle_weak_replaced_with_handle_uuid.md new file mode 100644 index 0000000000..d6bd6b9890 --- /dev/null +++ b/release-content/migration-guides/handle_weak_replaced_with_handle_uuid.md @@ -0,0 +1,40 @@ +--- +title: `Handle::Weak` has been replaced by `Handle::Uuid`. +pull_requests: [19896] +--- + +`Handle::Weak` had some weird behavior. It allowed for a sprite to be given a handle that is dropped +**while the sprite is still using it**. This also resulted in more complexity in the asset system. +The primary remaining use for `Handle::Weak` is to store asset UUIDs initialized through the +`weak_handle!` macro. To address this, `Handle::Weak` has been replaced by `Handle::Uuid`! + +Users using the `weak_handle!` macro should switch to the `uuid_handle!` macro. + +```rust +// Before +const IMAGE: Handle = weak_handle!("b20988e9-b1b9-4176-b5f3-a6fa73aa617f"); + +// After +const IMAGE: Handle = uuid_handle!("b20988e9-b1b9-4176-b5f3-a6fa73aa617f"); +``` + +Users using `Handle::clone_weak` can (most likely) just call `Handle::clone` instead. + +```rust +// Somewhere in some startup system. +let my_sprite_image = asset_server.load("monster.png"); + +// In game code... +// This sprite could be unloaded even if the sprite is still using it! +commands.spawn(Sprite::from_image(my_sprite_image.clone_weak())); + +// Just do this instead! +commands.spawn(Sprite::from_image(my_sprite_image.clone())); +``` + +Users using the `Handle::Weak` variant directly should consider replacing it with `AssetId` instead, +accessible through `Handle::id`. These situations are very case-by-case migrations. + +P.S., for users of the `weak_handle!` macro: If you are using it for shaders, consider switching to +`load_shader_library`/`load_embedded_asset` instead (especially replacing `load_internal_asset`). +This enables hot reloading for your shaders - which Bevy internally has done this cycle!