1+ use core:: any:: TypeId ;
2+
13use alloc:: sync:: Arc ;
24
35use bevy_ecs:: resource:: Resource ;
46use bevy_platform:: {
5- collections:: HashMap ,
7+ collections:: { hash_map :: Entry , HashMap , HashSet } ,
68 sync:: { PoisonError , RwLock , RwLockReadGuard } ,
79} ;
810use bevy_utils:: TypeIdMap ;
@@ -15,21 +17,43 @@ use crate::{
1517
1618/// Maps asset UUIDs to the asset handle assigned to it.
1719#[ derive( Resource , Clone , Default ) ]
18- pub struct AssetUuidMap ( Arc < RwLock < TypeIdMap < HashMap < Uuid , UntypedEntityHandle > > > > ) ;
20+ pub struct AssetUuidMap ( Arc < RwLock < TypeIdMap < AssetUuidMapInner > > > ) ;
21+
22+ #[ derive( Default ) ]
23+ pub ( crate ) struct AssetUuidMapInner {
24+ pub ( crate ) uuid_to_handle : HashMap < Uuid , UntypedEntityHandle > ,
25+ entity_to_uuids : HashMap < AssetEntity , HashSet < Uuid > > ,
26+ }
1927
2028impl AssetUuidMap {
2129 /// Sets the handle that a UUID refers to.
2230 pub fn set_uuid ( & mut self , uuid : Uuid , handle : UntypedEntityHandle ) {
23- self . 0
24- . write ( )
25- . unwrap_or_else ( PoisonError :: into_inner)
26- . entry ( handle. 0 . type_id )
31+ let mut type_id_map = self . 0 . write ( ) . unwrap_or_else ( PoisonError :: into_inner) ;
32+ let inner = type_id_map. entry ( handle. 0 . type_id ) . or_default ( ) ;
33+ let new_entity = handle. entity ( ) ;
34+ match inner. uuid_to_handle . entry ( uuid) {
35+ Entry :: Vacant ( entry) => {
36+ entry. insert ( handle) ;
37+ }
38+ Entry :: Occupied ( mut entry) => {
39+ let old_entity = entry. get ( ) . entity ( ) ;
40+ inner
41+ . entity_to_uuids
42+ . get_mut ( & old_entity)
43+ . unwrap ( )
44+ . remove ( & uuid) ;
45+ entry. insert ( handle) ;
46+ }
47+ }
48+ inner
49+ . entity_to_uuids
50+ . entry ( new_entity)
2751 . or_default ( )
28- . insert ( uuid, handle ) ;
52+ . insert ( uuid) ;
2953 }
3054
3155 /// Convenience function for accessing the internal uuid map.
32- fn read ( & self ) -> RwLockReadGuard < ' _ , TypeIdMap < HashMap < Uuid , UntypedEntityHandle > > > {
56+ pub ( crate ) fn read ( & self ) -> RwLockReadGuard < ' _ , TypeIdMap < AssetUuidMapInner > > {
3357 self . 0 . read ( ) . unwrap_or_else ( PoisonError :: into_inner)
3458 }
3559
@@ -46,7 +70,7 @@ impl AssetUuidMap {
4670 UntypedHandle :: Uuid { type_id, uuid } => self
4771 . read ( )
4872 . get ( & type_id)
49- . and_then ( |map| map . get ( & uuid) )
73+ . and_then ( |inner| inner . uuid_to_handle . get ( & uuid) )
5074 . cloned ( )
5175 . ok_or ( ResolveUuidError ( uuid) ) ,
5276 }
@@ -79,11 +103,26 @@ impl AssetUuidMap {
79103 UntypedAssetId :: Uuid { type_id, uuid } => self
80104 . read ( )
81105 . get ( & type_id)
82- . and_then ( |map| map . get ( & uuid) )
106+ . and_then ( |inner| inner . uuid_to_handle . get ( & uuid) )
83107 . map ( |value| value. 0 . entity )
84108 . ok_or ( ResolveUuidError ( uuid) ) ,
85109 }
86110 }
111+
112+ /// Returns a reverse mapping from an entity to all UUIDs that reference it.
113+ pub ( crate ) fn entity_to_uuids (
114+ & self ,
115+ entity : AssetEntity ,
116+ type_id : TypeId ,
117+ ) -> Option < HashSet < Uuid > > {
118+ Some (
119+ self . read ( )
120+ . get ( & type_id) ?
121+ . entity_to_uuids
122+ . get ( & entity) ?
123+ . clone ( ) ,
124+ )
125+ }
87126}
88127
89128/// An error while resolve a [`Uuid`] in the [`AssetUuidMap`].
0 commit comments