Replace Handle::Weak
with Handle::Uuid
. (#19896)
# Objective - Progress towards #19024. ## Solution - Remove `Handle::Weak`! If users were relying on `Handle::Weak` for some purpose, they can almost certainly replace it with raw `AssetId` instead. If they cannot, they can make their own enum that holds either a Handle or an AssetId. In either case, we don't need weak handles! Sadly we still need Uuid handles since we rely on them for "default" assets and "invalid" assets, as well as anywhere where a component wants to impl default with a non-defaulted asset handle. One step at a time though!
This commit is contained in:
parent
1a410efd24
commit
d05c435848
@ -32,7 +32,7 @@
|
|||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
#[cfg(feature = "smaa_luts")]
|
#[cfg(feature = "smaa_luts")]
|
||||||
use bevy_asset::load_internal_binary_asset;
|
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"))]
|
#[cfg(not(feature = "smaa_luts"))]
|
||||||
use bevy_core_pipeline::tonemapping::lut_placeholder;
|
use bevy_core_pipeline::tonemapping::lut_placeholder;
|
||||||
use bevy_core_pipeline::{
|
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.
|
/// The handle of the area LUT, a KTX2 format texture that SMAA uses internally.
|
||||||
const SMAA_AREA_LUT_TEXTURE_HANDLE: Handle<Image> =
|
const SMAA_AREA_LUT_TEXTURE_HANDLE: Handle<Image> =
|
||||||
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.
|
/// The handle of the search LUT, a KTX2 format texture that SMAA uses internally.
|
||||||
const SMAA_SEARCH_LUT_TEXTURE_HANDLE: Handle<Image> =
|
const SMAA_SEARCH_LUT_TEXTURE_HANDLE: Handle<Image> =
|
||||||
weak_handle!("43b97515-252e-4c8a-b9af-f2fc528a1c27");
|
uuid_handle!("43b97515-252e-4c8a-b9af-f2fc528a1c27");
|
||||||
|
|
||||||
/// Adds support for subpixel morphological antialiasing, or SMAA.
|
/// Adds support for subpixel morphological antialiasing, or SMAA.
|
||||||
pub struct SmaaPlugin;
|
pub struct SmaaPlugin;
|
||||||
|
@ -7,10 +7,12 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
|
|||||||
use core::{
|
use core::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use disqualified::ShortName;
|
use disqualified::ShortName;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
/// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_.
|
/// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_.
|
||||||
/// This should _only_ be used for one 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.
|
/// avoiding the need to store multiple copies of the same data.
|
||||||
///
|
///
|
||||||
/// If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
|
/// 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.
|
/// nor will it keep assets alive.
|
||||||
///
|
///
|
||||||
/// Modifying a *handle* will change which existing asset is referenced, but modifying the *asset*
|
/// Modifying a *handle* will change which existing asset is referenced, but modifying the *asset*
|
||||||
@ -133,16 +135,16 @@ pub enum Handle<A: Asset> {
|
|||||||
/// A "strong" reference to a live (or loading) [`Asset`]. If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
|
/// 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.
|
/// alive until the [`Handle`] is dropped. Strong handles also provide access to additional asset metadata.
|
||||||
Strong(Arc<StrongHandle>),
|
Strong(Arc<StrongHandle>),
|
||||||
/// A "weak" reference to an [`Asset`]. If a [`Handle`] is [`Handle::Weak`], it does not necessarily reference a live [`Asset`],
|
/// A reference to an [`Asset`] using a stable-across-runs / const identifier. Dropping this
|
||||||
/// nor will it keep assets alive.
|
/// handle will not result in the asset being dropped.
|
||||||
Weak(AssetId<A>),
|
Uuid(Uuid, #[reflect(ignore, clone)] PhantomData<fn() -> A>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Asset> Clone for Handle<T> {
|
impl<T: Asset> Clone for Handle<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Handle::Strong(handle) => Handle::Strong(handle.clone()),
|
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<A: Asset> Handle<A> {
|
|||||||
pub fn id(&self) -> AssetId<A> {
|
pub fn id(&self) -> AssetId<A> {
|
||||||
match self {
|
match self {
|
||||||
Handle::Strong(handle) => handle.id.typed_unchecked(),
|
Handle::Strong(handle) => handle.id.typed_unchecked(),
|
||||||
Handle::Weak(id) => *id,
|
Handle::Uuid(uuid, ..) => AssetId::Uuid { uuid: *uuid },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,14 +164,14 @@ impl<A: Asset> Handle<A> {
|
|||||||
pub fn path(&self) -> Option<&AssetPath<'static>> {
|
pub fn path(&self) -> Option<&AssetPath<'static>> {
|
||||||
match self {
|
match self {
|
||||||
Handle::Strong(handle) => handle.path.as_ref(),
|
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]
|
#[inline]
|
||||||
pub fn is_weak(&self) -> bool {
|
pub fn is_uuid(&self) -> bool {
|
||||||
matches!(self, Handle::Weak(_))
|
matches!(self, Handle::Uuid(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if this is a strong handle.
|
/// Returns `true` if this is a strong handle.
|
||||||
@ -178,18 +180,9 @@ impl<A: Asset> Handle<A> {
|
|||||||
matches!(self, Handle::Strong(_))
|
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::<A>()),
|
|
||||||
Handle::Weak(id) => Handle::Weak(*id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts this [`Handle`] to an "untyped" / "generic-less" [`UntypedHandle`], which stores the [`Asset`] type information
|
/// 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
|
/// _inside_ [`UntypedHandle`]. This will return [`UntypedHandle::Strong`] for [`Handle::Strong`] and [`UntypedHandle::Uuid`] for
|
||||||
/// [`Handle::Weak`].
|
/// [`Handle::Uuid`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn untyped(self) -> UntypedHandle {
|
pub fn untyped(self) -> UntypedHandle {
|
||||||
self.into()
|
self.into()
|
||||||
@ -198,7 +191,7 @@ impl<A: Asset> Handle<A> {
|
|||||||
|
|
||||||
impl<A: Asset> Default for Handle<A> {
|
impl<A: Asset> Default for Handle<A> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Handle::Weak(AssetId::default())
|
Handle::Uuid(AssetId::<A>::DEFAULT_UUID, PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +207,7 @@ impl<A: Asset> core::fmt::Debug for Handle<A> {
|
|||||||
handle.path
|
handle.path
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Handle::Weak(id) => write!(f, "WeakHandle<{name}>({:?})", id.internal()),
|
Handle::Uuid(uuid, ..) => write!(f, "UuidHandle<{name}>({uuid:?})"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,8 +277,13 @@ impl<A: Asset> From<&mut Handle<A>> for UntypedAssetId {
|
|||||||
pub enum UntypedHandle {
|
pub enum UntypedHandle {
|
||||||
/// A strong handle, which will keep the referenced [`Asset`] alive until all strong handles are dropped.
|
/// A strong handle, which will keep the referenced [`Asset`] alive until all strong handles are dropped.
|
||||||
Strong(Arc<StrongHandle>),
|
Strong(Arc<StrongHandle>),
|
||||||
/// A weak handle, which does not keep the referenced [`Asset`] alive.
|
/// A UUID handle, which does not keep the referenced [`Asset`] alive.
|
||||||
Weak(UntypedAssetId),
|
Uuid {
|
||||||
|
/// An identifier that records the underlying asset type.
|
||||||
|
type_id: TypeId,
|
||||||
|
/// The UUID provided during asset registration.
|
||||||
|
uuid: Uuid,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UntypedHandle {
|
impl UntypedHandle {
|
||||||
@ -294,7 +292,10 @@ impl UntypedHandle {
|
|||||||
pub fn id(&self) -> UntypedAssetId {
|
pub fn id(&self) -> UntypedAssetId {
|
||||||
match self {
|
match self {
|
||||||
UntypedHandle::Strong(handle) => handle.id,
|
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>> {
|
pub fn path(&self) -> Option<&AssetPath<'static>> {
|
||||||
match self {
|
match self {
|
||||||
UntypedHandle::Strong(handle) => handle.path.as_ref(),
|
UntypedHandle::Strong(handle) => handle.path.as_ref(),
|
||||||
UntypedHandle::Weak(_) => None,
|
UntypedHandle::Uuid { .. } => 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),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +313,7 @@ impl UntypedHandle {
|
|||||||
pub fn type_id(&self) -> TypeId {
|
pub fn type_id(&self) -> TypeId {
|
||||||
match self {
|
match self {
|
||||||
UntypedHandle::Strong(handle) => handle.id.type_id(),
|
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<A: Asset>(self) -> Handle<A> {
|
pub fn typed_unchecked<A: Asset>(self) -> Handle<A> {
|
||||||
match self {
|
match self {
|
||||||
UntypedHandle::Strong(handle) => Handle::Strong(handle),
|
UntypedHandle::Strong(handle) => Handle::Strong(handle),
|
||||||
UntypedHandle::Weak(id) => Handle::Weak(id.typed_unchecked::<A>()),
|
UntypedHandle::Uuid { uuid, .. } => Handle::Uuid(uuid, PhantomData),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,10 +337,7 @@ impl UntypedHandle {
|
|||||||
TypeId::of::<A>(),
|
TypeId::of::<A>(),
|
||||||
"The target Handle<A>'s TypeId does not match the TypeId of this UntypedHandle"
|
"The target Handle<A>'s TypeId does not match the TypeId of this UntypedHandle"
|
||||||
);
|
);
|
||||||
match self {
|
self.typed_unchecked()
|
||||||
UntypedHandle::Strong(handle) => Handle::Strong(handle),
|
|
||||||
UntypedHandle::Weak(id) => Handle::Weak(id.typed_unchecked::<A>()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts to a typed Handle. This will panic if the internal [`TypeId`] does not match the given asset type `A`
|
/// 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> {
|
pub fn meta_transform(&self) -> Option<&MetaTransform> {
|
||||||
match self {
|
match self {
|
||||||
UntypedHandle::Strong(handle) => handle.meta_transform.as_ref(),
|
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
|
handle.path
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
UntypedHandle::Weak(id) => write!(
|
UntypedHandle::Uuid { type_id, uuid } => {
|
||||||
f,
|
write!(f, "UuidHandle{{ type_id: {type_id:?}, uuid: {uuid:?} }}",)
|
||||||
"WeakHandle{{ type_id: {:?}, id: {:?} }}",
|
}
|
||||||
id.type_id(),
|
|
||||||
id.internal()
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -474,7 +460,10 @@ impl<A: Asset> From<Handle<A>> for UntypedHandle {
|
|||||||
fn from(value: Handle<A>) -> Self {
|
fn from(value: Handle<A>) -> Self {
|
||||||
match value {
|
match value {
|
||||||
Handle::Strong(handle) => UntypedHandle::Strong(handle),
|
Handle::Strong(handle) => UntypedHandle::Strong(handle),
|
||||||
Handle::Weak(id) => UntypedHandle::Weak(id.into()),
|
Handle::Uuid(uuid, _) => UntypedHandle::Uuid {
|
||||||
|
type_id: TypeId::of::<A>(),
|
||||||
|
uuid,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -490,36 +479,37 @@ impl<A: Asset> TryFrom<UntypedHandle> for Handle<A> {
|
|||||||
return Err(UntypedAssetConversionError::TypeIdMismatch { expected, found });
|
return Err(UntypedAssetConversionError::TypeIdMismatch { expected, found });
|
||||||
}
|
}
|
||||||
|
|
||||||
match value {
|
Ok(match value {
|
||||||
UntypedHandle::Strong(handle) => Ok(Handle::Strong(handle)),
|
UntypedHandle::Strong(handle) => Handle::Strong(handle),
|
||||||
UntypedHandle::Weak(id) => {
|
UntypedHandle::Uuid { uuid, .. } => Handle::Uuid(uuid, PhantomData),
|
||||||
let Ok(id) = id.try_into() else {
|
})
|
||||||
return Err(UntypedAssetConversionError::TypeIdMismatch { expected, found });
|
|
||||||
};
|
|
||||||
Ok(Handle::Weak(id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a weak [`Handle`] from a string literal containing a UUID.
|
/// Creates a [`Handle`] from a string literal containing a UUID.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_asset::{Handle, weak_handle};
|
/// # use bevy_asset::{Handle, uuid_handle};
|
||||||
/// # type Shader = ();
|
/// # type Shader = ();
|
||||||
/// const SHADER: Handle<Shader> = weak_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac");
|
/// const SHADER: Handle<Shader> = uuid_handle!("1347c9b7-c46a-48e7-b7b8-023a354b7cac");
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! weak_handle {
|
macro_rules! uuid_handle {
|
||||||
($uuid:expr) => {{
|
($uuid:expr) => {{
|
||||||
$crate::Handle::Weak($crate::AssetId::Uuid {
|
$crate::Handle::Uuid($crate::uuid::uuid!($uuid), core::marker::PhantomData)
|
||||||
uuid: $crate::uuid::uuid!($uuid),
|
|
||||||
})
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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`].
|
/// Errors preventing the conversion of to/from an [`UntypedHandle`] and a [`Handle`].
|
||||||
#[derive(Error, Debug, PartialEq, Clone)]
|
#[derive(Error, Debug, PartialEq, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@ -559,15 +549,12 @@ mod tests {
|
|||||||
/// Typed and Untyped `Handles` should be equivalent to each other and themselves
|
/// Typed and Untyped `Handles` should be equivalent to each other and themselves
|
||||||
#[test]
|
#[test]
|
||||||
fn equality() {
|
fn equality() {
|
||||||
let typed = AssetId::<TestAsset>::Uuid { uuid: UUID_1 };
|
let typed = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
|
||||||
let untyped = UntypedAssetId::Uuid {
|
let untyped = UntypedHandle::Uuid {
|
||||||
type_id: TypeId::of::<TestAsset>(),
|
type_id: TypeId::of::<TestAsset>(),
|
||||||
uuid: UUID_1,
|
uuid: UUID_1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let typed = Handle::Weak(typed);
|
|
||||||
let untyped = UntypedHandle::Weak(untyped);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok(typed.clone()),
|
Ok(typed.clone()),
|
||||||
Handle::<TestAsset>::try_from(untyped.clone())
|
Handle::<TestAsset>::try_from(untyped.clone())
|
||||||
@ -585,22 +572,17 @@ mod tests {
|
|||||||
fn ordering() {
|
fn ordering() {
|
||||||
assert!(UUID_1 < UUID_2);
|
assert!(UUID_1 < UUID_2);
|
||||||
|
|
||||||
let typed_1 = AssetId::<TestAsset>::Uuid { uuid: UUID_1 };
|
let typed_1 = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
|
||||||
let typed_2 = AssetId::<TestAsset>::Uuid { uuid: UUID_2 };
|
let typed_2 = Handle::<TestAsset>::Uuid(UUID_2, PhantomData);
|
||||||
let untyped_1 = UntypedAssetId::Uuid {
|
let untyped_1 = UntypedHandle::Uuid {
|
||||||
type_id: TypeId::of::<TestAsset>(),
|
type_id: TypeId::of::<TestAsset>(),
|
||||||
uuid: UUID_1,
|
uuid: UUID_1,
|
||||||
};
|
};
|
||||||
let untyped_2 = UntypedAssetId::Uuid {
|
let untyped_2 = UntypedHandle::Uuid {
|
||||||
type_id: TypeId::of::<TestAsset>(),
|
type_id: TypeId::of::<TestAsset>(),
|
||||||
uuid: UUID_2,
|
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!(typed_1 < typed_2);
|
||||||
assert!(untyped_1 < untyped_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
|
/// Typed and Untyped `Handles` should be equivalently hashable to each other and themselves
|
||||||
#[test]
|
#[test]
|
||||||
fn hashing() {
|
fn hashing() {
|
||||||
let typed = AssetId::<TestAsset>::Uuid { uuid: UUID_1 };
|
let typed = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
|
||||||
let untyped = UntypedAssetId::Uuid {
|
let untyped = UntypedHandle::Uuid {
|
||||||
type_id: TypeId::of::<TestAsset>(),
|
type_id: TypeId::of::<TestAsset>(),
|
||||||
uuid: UUID_1,
|
uuid: UUID_1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let typed = Handle::Weak(typed);
|
|
||||||
let untyped = UntypedHandle::Weak(untyped);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hash(&typed),
|
hash(&typed),
|
||||||
hash(&Handle::<TestAsset>::try_from(untyped.clone()).unwrap())
|
hash(&Handle::<TestAsset>::try_from(untyped.clone()).unwrap())
|
||||||
@ -637,15 +616,12 @@ mod tests {
|
|||||||
/// Typed and Untyped `Handles` should be interchangeable
|
/// Typed and Untyped `Handles` should be interchangeable
|
||||||
#[test]
|
#[test]
|
||||||
fn conversion() {
|
fn conversion() {
|
||||||
let typed = AssetId::<TestAsset>::Uuid { uuid: UUID_1 };
|
let typed = Handle::<TestAsset>::Uuid(UUID_1, PhantomData);
|
||||||
let untyped = UntypedAssetId::Uuid {
|
let untyped = UntypedHandle::Uuid {
|
||||||
type_id: TypeId::of::<TestAsset>(),
|
type_id: TypeId::of::<TestAsset>(),
|
||||||
uuid: UUID_1,
|
uuid: UUID_1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let typed = Handle::Weak(typed);
|
|
||||||
let untyped = UntypedHandle::Weak(untyped);
|
|
||||||
|
|
||||||
assert_eq!(typed, Handle::try_from(untyped.clone()).unwrap());
|
assert_eq!(typed, Handle::try_from(untyped.clone()).unwrap());
|
||||||
assert_eq!(UntypedHandle::from(typed.clone()), untyped);
|
assert_eq!(UntypedHandle::from(typed.clone()), untyped);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ use crate::core_3d::{
|
|||||||
prepare_core_3d_depth_textures,
|
prepare_core_3d_depth_textures,
|
||||||
};
|
};
|
||||||
use bevy_app::{App, Plugin};
|
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_derive::{Deref, DerefMut};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
@ -51,7 +51,7 @@ use tracing::debug;
|
|||||||
|
|
||||||
/// Identifies the `downsample_depth.wgsl` shader.
|
/// Identifies the `downsample_depth.wgsl` shader.
|
||||||
pub const DOWNSAMPLE_DEPTH_SHADER_HANDLE: Handle<Shader> =
|
pub const DOWNSAMPLE_DEPTH_SHADER_HANDLE: Handle<Shader> =
|
||||||
weak_handle!("a09a149e-5922-4fa4-9170-3c1a13065364");
|
uuid_handle!("a09a149e-5922-4fa4-9170-3c1a13065364");
|
||||||
|
|
||||||
/// The maximum number of mip levels that we can produce.
|
/// The maximum number of mip levels that we can produce.
|
||||||
///
|
///
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! Currently, this consists only of chromatic aberration.
|
//! Currently, this consists only of chromatic aberration.
|
||||||
|
|
||||||
use bevy_app::{App, Plugin};
|
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_derive::{Deref, DerefMut};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
@ -52,7 +52,7 @@ use crate::{
|
|||||||
/// This is just a 3x1 image consisting of one red pixel, one green pixel, and
|
/// This is just a 3x1 image consisting of one red pixel, one green pixel, and
|
||||||
/// one blue pixel, in that order.
|
/// one blue pixel, in that order.
|
||||||
const DEFAULT_CHROMATIC_ABERRATION_LUT_HANDLE: Handle<Image> =
|
const DEFAULT_CHROMATIC_ABERRATION_LUT_HANDLE: Handle<Image> =
|
||||||
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
|
/// The default chromatic aberration intensity amount, in a fraction of the
|
||||||
/// window size.
|
/// window size.
|
||||||
|
@ -149,7 +149,7 @@ pub(crate) fn extract_linegizmos(
|
|||||||
line_style: gizmo.line_config.style,
|
line_style: gizmo.line_config.style,
|
||||||
line_joints: gizmo.line_config.joints,
|
line_joints: gizmo.line_config.joints,
|
||||||
render_layers: render_layers.cloned().unwrap_or_default(),
|
render_layers: render_layers.cloned().unwrap_or_default(),
|
||||||
handle: gizmo.handle.clone_weak(),
|
handle: gizmo.handle.clone(),
|
||||||
},
|
},
|
||||||
MainEntity::from(entity),
|
MainEntity::from(entity),
|
||||||
TemporaryRenderEntity,
|
TemporaryRenderEntity,
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
MaterialPlugin, StandardMaterial,
|
MaterialPlugin, StandardMaterial,
|
||||||
};
|
};
|
||||||
use bevy_app::{App, Plugin};
|
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_ecs::component::Component;
|
||||||
use bevy_math::{prelude::Rectangle, Quat, Vec2, Vec3};
|
use bevy_math::{prelude::Rectangle, Quat, Vec2, Vec3};
|
||||||
use bevy_reflect::{Reflect, TypePath};
|
use bevy_reflect::{Reflect, TypePath};
|
||||||
@ -21,7 +21,7 @@ use bevy_render::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const FORWARD_DECAL_MESH_HANDLE: Handle<Mesh> =
|
const FORWARD_DECAL_MESH_HANDLE: Handle<Mesh> =
|
||||||
weak_handle!("afa817f9-1869-4e0c-ac0d-d8cd1552d38a");
|
uuid_handle!("afa817f9-1869-4e0c-ac0d-d8cd1552d38a");
|
||||||
|
|
||||||
/// Plugin to render [`ForwardDecal`]s.
|
/// Plugin to render [`ForwardDecal`]s.
|
||||||
pub struct ForwardDecalPlugin;
|
pub struct ForwardDecalPlugin;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use core::array;
|
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_color::ColorToComponents as _;
|
||||||
use bevy_core_pipeline::{
|
use bevy_core_pipeline::{
|
||||||
core_3d::Camera3d,
|
core_3d::Camera3d,
|
||||||
@ -82,14 +82,14 @@ bitflags! {
|
|||||||
///
|
///
|
||||||
/// This mesh is simply stretched to the size of the framebuffer, as when the
|
/// 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.
|
/// camera is inside a fog volume it's essentially a full-screen effect.
|
||||||
pub const PLANE_MESH: Handle<Mesh> = weak_handle!("92523617-c708-4fd0-b42f-ceb4300c930b");
|
pub const PLANE_MESH: Handle<Mesh> = uuid_handle!("92523617-c708-4fd0-b42f-ceb4300c930b");
|
||||||
|
|
||||||
/// The cube mesh, which is used to render a fog volume that the camera is
|
/// The cube mesh, which is used to render a fog volume that the camera is
|
||||||
/// outside.
|
/// outside.
|
||||||
///
|
///
|
||||||
/// Note that only the front faces of this cuboid will be rasterized in
|
/// 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.
|
/// hardware. The back faces will be calculated in the shader via raytracing.
|
||||||
pub const CUBE_MESH: Handle<Mesh> = weak_handle!("4a1dd661-2d91-4377-a17a-a914e21e277e");
|
pub const CUBE_MESH: Handle<Mesh> = uuid_handle!("4a1dd661-2d91-4377-a17a-a914e21e277e");
|
||||||
|
|
||||||
/// The total number of bind group layouts.
|
/// The total number of bind group layouts.
|
||||||
///
|
///
|
||||||
|
@ -21,7 +21,7 @@ use crate::{
|
|||||||
render_asset::RenderAssetPlugin, renderer::RenderDevice, Render, RenderApp, RenderSystems,
|
render_asset::RenderAssetPlugin, renderer::RenderDevice, Render, RenderApp, RenderSystems,
|
||||||
};
|
};
|
||||||
use bevy_app::{App, Plugin};
|
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 bevy_ecs::prelude::*;
|
||||||
use tracing::warn;
|
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.
|
/// 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.
|
// Number randomly selected by fair WolframAlpha query. Totally arbitrary.
|
||||||
pub const TRANSPARENT_IMAGE_HANDLE: Handle<Image> =
|
pub const TRANSPARENT_IMAGE_HANDLE: Handle<Image> =
|
||||||
weak_handle!("d18ad97e-a322-4981-9505-44c59a4b5e46");
|
uuid_handle!("d18ad97e-a322-4981-9505-44c59a4b5e46");
|
||||||
|
|
||||||
// TODO: replace Texture names with Image names?
|
// 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.
|
/// Adds the [`Image`] as an asset and makes sure that they are extracted and prepared for the GPU.
|
||||||
|
@ -172,8 +172,8 @@ impl FontAtlasSet {
|
|||||||
.get_glyph_index(cache_key)
|
.get_glyph_index(cache_key)
|
||||||
.map(|location| GlyphAtlasInfo {
|
.map(|location| GlyphAtlasInfo {
|
||||||
location,
|
location,
|
||||||
texture_atlas: atlas.texture_atlas.clone_weak(),
|
texture_atlas: atlas.texture_atlas.id(),
|
||||||
texture: atlas.texture.clone_weak(),
|
texture: atlas.texture.id(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This module exports types related to rendering glyphs.
|
//! This module exports types related to rendering glyphs.
|
||||||
|
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::AssetId;
|
||||||
use bevy_image::prelude::*;
|
use bevy_image::prelude::*;
|
||||||
use bevy_math::{IVec2, Vec2};
|
use bevy_math::{IVec2, Vec2};
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
@ -38,14 +38,15 @@ pub struct PositionedGlyph {
|
|||||||
#[derive(Debug, Clone, Reflect)]
|
#[derive(Debug, Clone, Reflect)]
|
||||||
#[reflect(Clone)]
|
#[reflect(Clone)]
|
||||||
pub struct GlyphAtlasInfo {
|
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).
|
/// An asset ID of the handle held by the [`FontAtlas`](crate::FontAtlas).
|
||||||
pub texture: Handle<Image>,
|
pub texture: AssetId<Image>,
|
||||||
/// A handle to the [`TextureAtlasLayout`] map for the texture atlas this glyph was placed in.
|
/// 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).
|
/// An asset ID of the handle held by the [`FontAtlas`](crate::FontAtlas).
|
||||||
pub texture_atlas: Handle<TextureAtlasLayout>,
|
pub texture_atlas: AssetId<TextureAtlasLayout>,
|
||||||
/// Location and offset of a glyph within the texture atlas.
|
/// Location and offset of a glyph within the texture atlas.
|
||||||
pub location: GlyphAtlasLocation,
|
pub location: GlyphAtlasLocation,
|
||||||
}
|
}
|
||||||
|
@ -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 location = atlas_info.location;
|
||||||
let glyph_rect = texture_atlas.textures[location.glyph_index];
|
let glyph_rect = texture_atlas.textures[location.glyph_index];
|
||||||
let left = location.offset.x as f32;
|
let left = location.offset.x as f32;
|
||||||
|
@ -213,7 +213,7 @@ pub fn extract_text2d_sprite(
|
|||||||
current_span = *span_index;
|
current_span = *span_index;
|
||||||
}
|
}
|
||||||
let rect = texture_atlases
|
let rect = texture_atlases
|
||||||
.get(&atlas_info.texture_atlas)
|
.get(atlas_info.texture_atlas)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.textures[atlas_info.location.glyph_index]
|
.textures[atlas_info.location.glyph_index]
|
||||||
.as_rect();
|
.as_rect();
|
||||||
@ -232,7 +232,7 @@ pub fn extract_text2d_sprite(
|
|||||||
render_entity,
|
render_entity,
|
||||||
transform,
|
transform,
|
||||||
color,
|
color,
|
||||||
image_handle_id: atlas_info.texture.id(),
|
image_handle_id: atlas_info.texture,
|
||||||
flip_x: false,
|
flip_x: false,
|
||||||
flip_y: false,
|
flip_y: false,
|
||||||
kind: bevy_sprite::ExtractedSpriteKind::Slices {
|
kind: bevy_sprite::ExtractedSpriteKind::Slices {
|
||||||
|
@ -865,7 +865,7 @@ pub fn extract_text_sections(
|
|||||||
) in text_layout_info.glyphs.iter().enumerate()
|
) in text_layout_info.glyphs.iter().enumerate()
|
||||||
{
|
{
|
||||||
let rect = texture_atlases
|
let rect = texture_atlases
|
||||||
.get(&atlas_info.texture_atlas)
|
.get(atlas_info.texture_atlas)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.textures[atlas_info.location.glyph_index]
|
.textures[atlas_info.location.glyph_index]
|
||||||
.as_rect();
|
.as_rect();
|
||||||
@ -891,7 +891,7 @@ pub fn extract_text_sections(
|
|||||||
z_order: uinode.stack_index as f32 + stack_z_offsets::TEXT,
|
z_order: uinode.stack_index as f32 + stack_z_offsets::TEXT,
|
||||||
render_entity: commands.spawn(TemporaryRenderEntity).id(),
|
render_entity: commands.spawn(TemporaryRenderEntity).id(),
|
||||||
color,
|
color,
|
||||||
image: atlas_info.texture.id(),
|
image: atlas_info.texture,
|
||||||
clip: clip.map(|clip| clip.clip),
|
clip: clip.map(|clip| clip.clip),
|
||||||
extracted_camera_entity,
|
extracted_camera_entity,
|
||||||
rect,
|
rect,
|
||||||
@ -956,7 +956,7 @@ pub fn extract_text_shadows(
|
|||||||
) in text_layout_info.glyphs.iter().enumerate()
|
) in text_layout_info.glyphs.iter().enumerate()
|
||||||
{
|
{
|
||||||
let rect = texture_atlases
|
let rect = texture_atlases
|
||||||
.get(&atlas_info.texture_atlas)
|
.get(atlas_info.texture_atlas)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.textures[atlas_info.location.glyph_index]
|
.textures[atlas_info.location.glyph_index]
|
||||||
.as_rect();
|
.as_rect();
|
||||||
@ -972,7 +972,7 @@ pub fn extract_text_shadows(
|
|||||||
z_order: uinode.stack_index as f32 + stack_z_offsets::TEXT,
|
z_order: uinode.stack_index as f32 + stack_z_offsets::TEXT,
|
||||||
render_entity: commands.spawn(TemporaryRenderEntity).id(),
|
render_entity: commands.spawn(TemporaryRenderEntity).id(),
|
||||||
color: shadow.color.into(),
|
color: shadow.color.into(),
|
||||||
image: atlas_info.texture.id(),
|
image: atlas_info.texture,
|
||||||
clip: clip.map(|clip| clip.clip),
|
clip: clip.map(|clip| clip.clip),
|
||||||
extracted_camera_entity,
|
extracted_camera_entity,
|
||||||
rect,
|
rect,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
//! [`Material2d`]: bevy::sprite::Material2d
|
//! [`Material2d`]: bevy::sprite::Material2d
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::weak_handle,
|
asset::uuid_handle,
|
||||||
color::palettes::basic::YELLOW,
|
color::palettes::basic::YELLOW,
|
||||||
core_pipeline::core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT},
|
core_pipeline::core_2d::{Transparent2d, CORE_2D_DEPTH_FORMAT},
|
||||||
math::{ops, FloatOrd},
|
math::{ops, FloatOrd},
|
||||||
@ -287,7 +287,7 @@ pub struct ColoredMesh2dPlugin;
|
|||||||
|
|
||||||
/// Handle to the custom shader with a unique random ID
|
/// Handle to the custom shader with a unique random ID
|
||||||
pub const COLORED_MESH2D_SHADER_HANDLE: Handle<Shader> =
|
pub const COLORED_MESH2D_SHADER_HANDLE: Handle<Shader> =
|
||||||
weak_handle!("f48b148f-7373-4638-9900-392b3b3ccc66");
|
uuid_handle!("f48b148f-7373-4638-9900-392b3b3ccc66");
|
||||||
|
|
||||||
/// Our custom pipeline needs its own instance storage
|
/// Our custom pipeline needs its own instance storage
|
||||||
#[derive(Resource, Deref, DerefMut, Default)]
|
#[derive(Resource, Deref, DerefMut, Default)]
|
||||||
|
@ -86,9 +86,9 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
|||||||
// Switch texture to display every frame to show the one that was written to most recently.
|
// Switch texture to display every frame to show the one that was written to most recently.
|
||||||
fn switch_textures(images: Res<GameOfLifeImages>, mut sprite: Single<&mut Sprite>) {
|
fn switch_textures(images: Res<GameOfLifeImages>, mut sprite: Single<&mut Sprite>) {
|
||||||
if sprite.image == images.texture_a {
|
if sprite.image == images.texture_a {
|
||||||
sprite.image = images.texture_b.clone_weak();
|
sprite.image = images.texture_b.clone();
|
||||||
} else {
|
} else {
|
||||||
sprite.image = images.texture_a.clone_weak();
|
sprite.image = images.texture_a.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +125,7 @@ fn scene_load_check(
|
|||||||
maybe_directional_light.is_some() || maybe_point_light.is_some()
|
maybe_directional_light.is_some() || maybe_point_light.is_some()
|
||||||
});
|
});
|
||||||
|
|
||||||
scene_handle.instance_id =
|
scene_handle.instance_id = Some(scene_spawner.spawn(gltf_scene_handle.clone()));
|
||||||
Some(scene_spawner.spawn(gltf_scene_handle.clone_weak()));
|
|
||||||
|
|
||||||
info!("Spawning scene...");
|
info!("Spawning scene...");
|
||||||
}
|
}
|
||||||
|
@ -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<Image> = weak_handle!("b20988e9-b1b9-4176-b5f3-a6fa73aa617f");
|
||||||
|
|
||||||
|
// After
|
||||||
|
const IMAGE: Handle<Image> = 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!
|
Loading…
Reference in New Issue
Block a user