@@ -7,10 +7,12 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
7
7
use core:: {
8
8
any:: TypeId ,
9
9
hash:: { Hash , Hasher } ,
10
+ marker:: PhantomData ,
10
11
} ;
11
12
use crossbeam_channel:: { Receiver , Sender } ;
12
13
use disqualified:: ShortName ;
13
14
use thiserror:: Error ;
15
+ use uuid:: Uuid ;
14
16
15
17
/// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_.
16
18
/// This should _only_ be used for one specific asset type.
@@ -117,7 +119,7 @@ impl core::fmt::Debug for StrongHandle {
117
119
/// avoiding the need to store multiple copies of the same data.
118
120
///
119
121
/// If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
120
- /// alive until the [`Handle`] is dropped. If a [`Handle`] is [`Handle::Weak `], it does not necessarily reference a live [`Asset`],
122
+ /// alive until the [`Handle`] is dropped. If a [`Handle`] is [`Handle::Uuid `], it does not necessarily reference a live [`Asset`],
121
123
/// nor will it keep assets alive.
122
124
///
123
125
/// Modifying a *handle* will change which existing asset is referenced, but modifying the *asset*
@@ -133,16 +135,16 @@ pub enum Handle<A: Asset> {
133
135
/// A "strong" reference to a live (or loading) [`Asset`]. If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
134
136
/// alive until the [`Handle`] is dropped. Strong handles also provide access to additional asset metadata.
135
137
Strong ( Arc < StrongHandle > ) ,
136
- /// A "weak" reference to an [`Asset`]. If a [`Handle`] is [`Handle::Weak`], it does not necessarily reference a live [`Asset`],
137
- /// nor will it keep assets alive .
138
- Weak ( AssetId < A > ) ,
138
+ /// A reference to an [`Asset`] using a stable-across-runs / const identifier. Dropping this
139
+ /// handle will not result in the asset being dropped .
140
+ Uuid ( Uuid , # [ reflect ( ignore , clone ) ] PhantomData < fn ( ) -> A > ) ,
139
141
}
140
142
141
143
impl < T : Asset > Clone for Handle < T > {
142
144
fn clone ( & self ) -> Self {
143
145
match self {
144
146
Handle :: Strong ( handle) => Handle :: Strong ( handle. clone ( ) ) ,
145
- Handle :: Weak ( id ) => Handle :: Weak ( * id ) ,
147
+ Handle :: Uuid ( uuid , .. ) => Handle :: Uuid ( * uuid , PhantomData ) ,
146
148
}
147
149
}
148
150
}
@@ -153,7 +155,7 @@ impl<A: Asset> Handle<A> {
153
155
pub fn id ( & self ) -> AssetId < A > {
154
156
match self {
155
157
Handle :: Strong ( handle) => handle. id . typed_unchecked ( ) ,
156
- Handle :: Weak ( id ) => * id ,
158
+ Handle :: Uuid ( uuid , .. ) => AssetId :: Uuid { uuid : * uuid } ,
157
159
}
158
160
}
159
161
@@ -162,14 +164,14 @@ impl<A: Asset> Handle<A> {
162
164
pub fn path ( & self ) -> Option < & AssetPath < ' static > > {
163
165
match self {
164
166
Handle :: Strong ( handle) => handle. path . as_ref ( ) ,
165
- Handle :: Weak ( _ ) => None ,
167
+ Handle :: Uuid ( .. ) => None ,
166
168
}
167
169
}
168
170
169
- /// Returns `true` if this is a weak handle.
171
+ /// Returns `true` if this is a uuid handle.
170
172
#[ inline]
171
- pub fn is_weak ( & self ) -> bool {
172
- matches ! ( self , Handle :: Weak ( _ ) )
173
+ pub fn is_uuid ( & self ) -> bool {
174
+ matches ! ( self , Handle :: Uuid ( .. ) )
173
175
}
174
176
175
177
/// Returns `true` if this is a strong handle.
@@ -178,18 +180,9 @@ impl<A: Asset> Handle<A> {
178
180
matches ! ( self , Handle :: Strong ( _) )
179
181
}
180
182
181
- /// Creates a [`Handle::Weak`] clone of this [`Handle`], which will not keep the referenced [`Asset`] alive.
182
- #[ inline]
183
- pub fn clone_weak ( & self ) -> Self {
184
- match self {
185
- Handle :: Strong ( handle) => Handle :: Weak ( handle. id . typed_unchecked :: < A > ( ) ) ,
186
- Handle :: Weak ( id) => Handle :: Weak ( * id) ,
187
- }
188
- }
189
-
190
183
/// Converts this [`Handle`] to an "untyped" / "generic-less" [`UntypedHandle`], which stores the [`Asset`] type information
191
- /// _inside_ [`UntypedHandle`]. This will return [`UntypedHandle::Strong`] for [`Handle::Strong`] and [`UntypedHandle::Weak `] for
192
- /// [`Handle::Weak `].
184
+ /// _inside_ [`UntypedHandle`]. This will return [`UntypedHandle::Strong`] for [`Handle::Strong`] and [`UntypedHandle::Uuid `] for
185
+ /// [`Handle::Uuid `].
193
186
#[ inline]
194
187
pub fn untyped ( self ) -> UntypedHandle {
195
188
self . into ( )
@@ -198,7 +191,7 @@ impl<A: Asset> Handle<A> {
198
191
199
192
impl < A : Asset > Default for Handle < A > {
200
193
fn default ( ) -> Self {
201
- Handle :: Weak ( AssetId :: default ( ) )
194
+ Handle :: Uuid ( AssetId :: < A > :: DEFAULT_UUID , PhantomData )
202
195
}
203
196
}
204
197
@@ -214,7 +207,7 @@ impl<A: Asset> core::fmt::Debug for Handle<A> {
214
207
handle. path
215
208
)
216
209
}
217
- Handle :: Weak ( id ) => write ! ( f, "WeakHandle <{name}>({:?})" , id . internal ( ) ) ,
210
+ Handle :: Uuid ( uuid , .. ) => write ! ( f, "UuidHandle <{name}>({uuid :?})" ) ,
218
211
}
219
212
}
220
213
}
@@ -284,8 +277,13 @@ impl<A: Asset> From<&mut Handle<A>> for UntypedAssetId {
284
277
pub enum UntypedHandle {
285
278
/// A strong handle, which will keep the referenced [`Asset`] alive until all strong handles are dropped.
286
279
Strong ( Arc < StrongHandle > ) ,
287
- /// A weak handle, which does not keep the referenced [`Asset`] alive.
288
- Weak ( UntypedAssetId ) ,
280
+ /// A UUID handle, which does not keep the referenced [`Asset`] alive.
281
+ Uuid {
282
+ /// An identifier that records the underlying asset type.
283
+ type_id : TypeId ,
284
+ /// The UUID provided during asset registration.
285
+ uuid : Uuid ,
286
+ } ,
289
287
}
290
288
291
289
impl UntypedHandle {
@@ -294,7 +292,10 @@ impl UntypedHandle {
294
292
pub fn id ( & self ) -> UntypedAssetId {
295
293
match self {
296
294
UntypedHandle :: Strong ( handle) => handle. id ,
297
- UntypedHandle :: Weak ( id) => * id,
295
+ UntypedHandle :: Uuid { type_id, uuid } => UntypedAssetId :: Uuid {
296
+ uuid : * uuid,
297
+ type_id : * type_id,
298
+ } ,
298
299
}
299
300
}
300
301
@@ -303,16 +304,7 @@ impl UntypedHandle {
303
304
pub fn path ( & self ) -> Option < & AssetPath < ' static > > {
304
305
match self {
305
306
UntypedHandle :: Strong ( handle) => handle. path . as_ref ( ) ,
306
- UntypedHandle :: Weak ( _) => None ,
307
- }
308
- }
309
-
310
- /// Creates an [`UntypedHandle::Weak`] clone of this [`UntypedHandle`], which will not keep the referenced [`Asset`] alive.
311
- #[ inline]
312
- pub fn clone_weak ( & self ) -> UntypedHandle {
313
- match self {
314
- UntypedHandle :: Strong ( handle) => UntypedHandle :: Weak ( handle. id ) ,
315
- UntypedHandle :: Weak ( id) => UntypedHandle :: Weak ( * id) ,
307
+ UntypedHandle :: Uuid { .. } => None ,
316
308
}
317
309
}
318
310
@@ -321,7 +313,7 @@ impl UntypedHandle {
321
313
pub fn type_id ( & self ) -> TypeId {
322
314
match self {
323
315
UntypedHandle :: Strong ( handle) => handle. id . type_id ( ) ,
324
- UntypedHandle :: Weak ( id ) => id . type_id ( ) ,
316
+ UntypedHandle :: Uuid { type_id , .. } => * type_id,
325
317
}
326
318
}
327
319
@@ -330,7 +322,7 @@ impl UntypedHandle {
330
322
pub fn typed_unchecked < A : Asset > ( self ) -> Handle < A > {
331
323
match self {
332
324
UntypedHandle :: Strong ( handle) => Handle :: Strong ( handle) ,
333
- UntypedHandle :: Weak ( id ) => Handle :: Weak ( id . typed_unchecked :: < A > ( ) ) ,
325
+ UntypedHandle :: Uuid { uuid , .. } => Handle :: Uuid ( uuid , PhantomData ) ,
334
326
}
335
327
}
336
328
@@ -345,10 +337,7 @@ impl UntypedHandle {
345
337
TypeId :: of:: <A >( ) ,
346
338
"The target Handle<A>'s TypeId does not match the TypeId of this UntypedHandle"
347
339
) ;
348
- match self {
349
- UntypedHandle :: Strong ( handle) => Handle :: Strong ( handle) ,
350
- UntypedHandle :: Weak ( id) => Handle :: Weak ( id. typed_unchecked :: < A > ( ) ) ,
351
- }
340
+ self . typed_unchecked ( )
352
341
}
353
342
354
343
/// 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 {
376
365
pub fn meta_transform ( & self ) -> Option < & MetaTransform > {
377
366
match self {
378
367
UntypedHandle :: Strong ( handle) => handle. meta_transform . as_ref ( ) ,
379
- UntypedHandle :: Weak ( _ ) => None ,
368
+ UntypedHandle :: Uuid { .. } => None ,
380
369
}
381
370
}
382
371
}
@@ -409,12 +398,9 @@ impl core::fmt::Debug for UntypedHandle {
409
398
handle. path
410
399
)
411
400
}
412
- UntypedHandle :: Weak ( id) => write ! (
413
- f,
414
- "WeakHandle{{ type_id: {:?}, id: {:?} }}" ,
415
- id. type_id( ) ,
416
- id. internal( )
417
- ) ,
401
+ UntypedHandle :: Uuid { type_id, uuid } => {
402
+ write ! ( f, "UuidHandle{{ type_id: {type_id:?}, uuid: {uuid:?} }}" , )
403
+ }
418
404
}
419
405
}
420
406
}
@@ -474,7 +460,10 @@ impl<A: Asset> From<Handle<A>> for UntypedHandle {
474
460
fn from ( value : Handle < A > ) -> Self {
475
461
match value {
476
462
Handle :: Strong ( handle) => UntypedHandle :: Strong ( handle) ,
477
- Handle :: Weak ( id) => UntypedHandle :: Weak ( id. into ( ) ) ,
463
+ Handle :: Uuid ( uuid, _) => UntypedHandle :: Uuid {
464
+ type_id : TypeId :: of :: < A > ( ) ,
465
+ uuid,
466
+ } ,
478
467
}
479
468
}
480
469
}
@@ -490,36 +479,37 @@ impl<A: Asset> TryFrom<UntypedHandle> for Handle<A> {
490
479
return Err ( UntypedAssetConversionError :: TypeIdMismatch { expected, found } ) ;
491
480
}
492
481
493
- match value {
494
- UntypedHandle :: Strong ( handle) => Ok ( Handle :: Strong ( handle) ) ,
495
- UntypedHandle :: Weak ( id) => {
496
- let Ok ( id) = id. try_into ( ) else {
497
- return Err ( UntypedAssetConversionError :: TypeIdMismatch { expected, found } ) ;
498
- } ;
499
- Ok ( Handle :: Weak ( id) )
500
- }
501
- }
482
+ Ok ( match value {
483
+ UntypedHandle :: Strong ( handle) => Handle :: Strong ( handle) ,
484
+ UntypedHandle :: Uuid { uuid, .. } => Handle :: Uuid ( uuid, PhantomData ) ,
485
+ } )
502
486
}
503
487
}
504
488
505
- /// Creates a weak [`Handle`] from a string literal containing a UUID.
489
+ /// Creates a [`Handle`] from a string literal containing a UUID.
506
490
///
507
491
/// # Examples
508
492
///
509
493
/// ```
510
- /// # use bevy_asset::{Handle, weak_handle };
494
+ /// # use bevy_asset::{Handle, uuid_handle };
511
495
/// # type Shader = ();
512
- /// const SHADER: Handle<Shader> = weak_handle !("1347c9b7-c46a-48e7-b7b8-023a354b7cac");
496
+ /// const SHADER: Handle<Shader> = uuid_handle !("1347c9b7-c46a-48e7-b7b8-023a354b7cac");
513
497
/// ```
514
498
#[ macro_export]
515
- macro_rules! weak_handle {
499
+ macro_rules! uuid_handle {
516
500
( $uuid: expr) => { {
517
- $crate:: Handle :: Weak ( $crate:: AssetId :: Uuid {
518
- uuid: $crate:: uuid:: uuid!( $uuid) ,
519
- } )
501
+ $crate:: Handle :: Uuid ( $crate:: uuid:: uuid!( $uuid) , core:: marker:: PhantomData )
520
502
} } ;
521
503
}
522
504
505
+ #[ deprecated = "Use uuid_handle! instead" ]
506
+ #[ macro_export]
507
+ macro_rules! weak_handle {
508
+ ( $uuid: expr) => {
509
+ uuid_handle!( $uuid)
510
+ } ;
511
+ }
512
+
523
513
/// Errors preventing the conversion of to/from an [`UntypedHandle`] and a [`Handle`].
524
514
#[ derive( Error , Debug , PartialEq , Clone ) ]
525
515
#[ non_exhaustive]
@@ -559,15 +549,12 @@ mod tests {
559
549
/// Typed and Untyped `Handles` should be equivalent to each other and themselves
560
550
#[ test]
561
551
fn equality ( ) {
562
- let typed = AssetId :: < TestAsset > :: Uuid { uuid : UUID_1 } ;
563
- let untyped = UntypedAssetId :: Uuid {
552
+ let typed = Handle :: < TestAsset > :: Uuid ( UUID_1 , PhantomData ) ;
553
+ let untyped = UntypedHandle :: Uuid {
564
554
type_id : TypeId :: of :: < TestAsset > ( ) ,
565
555
uuid : UUID_1 ,
566
556
} ;
567
557
568
- let typed = Handle :: Weak ( typed) ;
569
- let untyped = UntypedHandle :: Weak ( untyped) ;
570
-
571
558
assert_eq ! (
572
559
Ok ( typed. clone( ) ) ,
573
560
Handle :: <TestAsset >:: try_from( untyped. clone( ) )
@@ -585,22 +572,17 @@ mod tests {
585
572
fn ordering ( ) {
586
573
assert ! ( UUID_1 < UUID_2 ) ;
587
574
588
- let typed_1 = AssetId :: < TestAsset > :: Uuid { uuid : UUID_1 } ;
589
- let typed_2 = AssetId :: < TestAsset > :: Uuid { uuid : UUID_2 } ;
590
- let untyped_1 = UntypedAssetId :: Uuid {
575
+ let typed_1 = Handle :: < TestAsset > :: Uuid ( UUID_1 , PhantomData ) ;
576
+ let typed_2 = Handle :: < TestAsset > :: Uuid ( UUID_2 , PhantomData ) ;
577
+ let untyped_1 = UntypedHandle :: Uuid {
591
578
type_id : TypeId :: of :: < TestAsset > ( ) ,
592
579
uuid : UUID_1 ,
593
580
} ;
594
- let untyped_2 = UntypedAssetId :: Uuid {
581
+ let untyped_2 = UntypedHandle :: Uuid {
595
582
type_id : TypeId :: of :: < TestAsset > ( ) ,
596
583
uuid : UUID_2 ,
597
584
} ;
598
585
599
- let typed_1 = Handle :: Weak ( typed_1) ;
600
- let typed_2 = Handle :: Weak ( typed_2) ;
601
- let untyped_1 = UntypedHandle :: Weak ( untyped_1) ;
602
- let untyped_2 = UntypedHandle :: Weak ( untyped_2) ;
603
-
604
586
assert ! ( typed_1 < typed_2) ;
605
587
assert ! ( untyped_1 < untyped_2) ;
606
588
@@ -617,15 +599,12 @@ mod tests {
617
599
/// Typed and Untyped `Handles` should be equivalently hashable to each other and themselves
618
600
#[ test]
619
601
fn hashing ( ) {
620
- let typed = AssetId :: < TestAsset > :: Uuid { uuid : UUID_1 } ;
621
- let untyped = UntypedAssetId :: Uuid {
602
+ let typed = Handle :: < TestAsset > :: Uuid ( UUID_1 , PhantomData ) ;
603
+ let untyped = UntypedHandle :: Uuid {
622
604
type_id : TypeId :: of :: < TestAsset > ( ) ,
623
605
uuid : UUID_1 ,
624
606
} ;
625
607
626
- let typed = Handle :: Weak ( typed) ;
627
- let untyped = UntypedHandle :: Weak ( untyped) ;
628
-
629
608
assert_eq ! (
630
609
hash( & typed) ,
631
610
hash( & Handle :: <TestAsset >:: try_from( untyped. clone( ) ) . unwrap( ) )
@@ -637,15 +616,12 @@ mod tests {
637
616
/// Typed and Untyped `Handles` should be interchangeable
638
617
#[ test]
639
618
fn conversion ( ) {
640
- let typed = AssetId :: < TestAsset > :: Uuid { uuid : UUID_1 } ;
641
- let untyped = UntypedAssetId :: Uuid {
619
+ let typed = Handle :: < TestAsset > :: Uuid ( UUID_1 , PhantomData ) ;
620
+ let untyped = UntypedHandle :: Uuid {
642
621
type_id : TypeId :: of :: < TestAsset > ( ) ,
643
622
uuid : UUID_1 ,
644
623
} ;
645
624
646
- let typed = Handle :: Weak ( typed) ;
647
- let untyped = UntypedHandle :: Weak ( untyped) ;
648
-
649
625
assert_eq ! ( typed, Handle :: try_from( untyped. clone( ) ) . unwrap( ) ) ;
650
626
assert_eq ! ( UntypedHandle :: from( typed. clone( ) ) , untyped) ;
651
627
}
0 commit comments