Skip to content

Commit da50f7d

Browse files
authored
Merge branch 'bevyengine:main' into main
2 parents 8657959 + 40e88dc commit da50f7d

File tree

8 files changed

+110
-261
lines changed

8 files changed

+110
-261
lines changed

crates/bevy_ecs/src/entity/map_entities.rs

Lines changed: 10 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,16 @@ use super::{EntityHashMap, VisitEntitiesMut};
1515
/// (usually by using an [`EntityHashMap<Entity>`] between source entities and entities in the
1616
/// current world).
1717
///
18+
/// This trait is similar to [`VisitEntitiesMut`]. They differ in that [`VisitEntitiesMut`] operates
19+
/// on `&mut Entity` and allows for in-place modification, while this trait makes no assumption that
20+
/// such in-place modification is occurring, which is impossible for types such as [`HashSet<Entity>`]
21+
/// and [`EntityHashMap`] which must be rebuilt when their contained [`Entity`]s are remapped.
22+
///
1823
/// Implementing this trait correctly is required for properly loading components
1924
/// with entity references from scenes.
2025
///
26+
/// [`HashSet<Entity>`]: bevy_utils::HashSet
27+
///
2128
/// ## Example
2229
///
2330
/// ```
@@ -60,9 +67,6 @@ impl<T: VisitEntitiesMut> MapEntities for T {
6067
///
6168
/// More generally, this can be used to map [`Entity`] references between any two [`Worlds`](World).
6269
///
63-
/// Note that this trait is _not_ [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety).
64-
/// Please see [`DynEntityMapper`] for an object safe alternative.
65-
///
6670
/// ## Example
6771
///
6872
/// ```
@@ -79,64 +83,16 @@ impl<T: VisitEntitiesMut> MapEntities for T {
7983
/// fn map_entity(&mut self, entity: Entity) -> Entity {
8084
/// self.map.get(&entity).copied().unwrap_or(entity)
8185
/// }
82-
///
83-
/// fn mappings(&self) -> impl Iterator<Item = (Entity, Entity)> {
84-
/// self.map.iter().map(|(&source, &target)| (source, target))
85-
/// }
8686
/// }
8787
/// ```
8888
pub trait EntityMapper {
8989
/// Map an entity to another entity
9090
fn map_entity(&mut self, entity: Entity) -> Entity;
91-
92-
/// Iterate over all entity to entity mappings.
93-
///
94-
/// # Examples
95-
///
96-
/// ```rust
97-
/// # use bevy_ecs::entity::{Entity, EntityMapper};
98-
/// # fn example(mapper: impl EntityMapper) {
99-
/// for (source, target) in mapper.mappings() {
100-
/// println!("Will map from {source} to {target}");
101-
/// }
102-
/// # }
103-
/// ```
104-
fn mappings(&self) -> impl Iterator<Item = (Entity, Entity)>;
105-
}
106-
107-
/// An [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety) version
108-
/// of [`EntityMapper`]. This trait is automatically implemented for type that implements `EntityMapper`.
109-
pub trait DynEntityMapper {
110-
/// Map an entity to another entity.
111-
///
112-
/// This is an [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety)
113-
/// alternative to [`EntityMapper::map_entity`].
114-
fn dyn_map_entity(&mut self, entity: Entity) -> Entity;
115-
116-
/// Iterate over all entity to entity mappings.
117-
///
118-
/// This is an [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety)
119-
/// alternative to [`EntityMapper::mappings`].
120-
fn dyn_mappings(&self) -> Vec<(Entity, Entity)>;
121-
}
122-
123-
impl<T: EntityMapper> DynEntityMapper for T {
124-
fn dyn_map_entity(&mut self, entity: Entity) -> Entity {
125-
<T as EntityMapper>::map_entity(self, entity)
126-
}
127-
128-
fn dyn_mappings(&self) -> Vec<(Entity, Entity)> {
129-
<T as EntityMapper>::mappings(self).collect()
130-
}
13191
}
13292

133-
impl<'a> EntityMapper for &'a mut dyn DynEntityMapper {
93+
impl EntityMapper for &mut dyn EntityMapper {
13494
fn map_entity(&mut self, entity: Entity) -> Entity {
135-
(*self).dyn_map_entity(entity)
136-
}
137-
138-
fn mappings(&self) -> impl Iterator<Item = (Entity, Entity)> {
139-
(*self).dyn_mappings().into_iter()
95+
(*self).map_entity(entity)
14096
}
14197
}
14298

@@ -160,10 +116,6 @@ impl EntityMapper for SceneEntityMapper<'_> {
160116

161117
new
162118
}
163-
164-
fn mappings(&self) -> impl Iterator<Item = (Entity, Entity)> {
165-
self.map.iter().map(|(&source, &target)| (source, target))
166-
}
167119
}
168120

169121
/// A wrapper for [`EntityHashMap<Entity>`], augmenting it with the ability to allocate new [`Entity`] references in a destination
@@ -242,10 +194,9 @@ impl<'m> SceneEntityMapper<'m> {
242194
#[cfg(test)]
243195
mod tests {
244196
use crate::{
245-
entity::{DynEntityMapper, Entity, EntityHashMap, EntityMapper, SceneEntityMapper},
197+
entity::{Entity, EntityHashMap, EntityMapper, SceneEntityMapper},
246198
world::World,
247199
};
248-
use bevy_utils::assert_object_safe;
249200

250201
#[test]
251202
fn entity_mapper() {
@@ -292,26 +243,6 @@ mod tests {
292243
assert!(entity.generation() > dead_ref.generation());
293244
}
294245

295-
#[test]
296-
fn entity_mapper_iteration() {
297-
let mut old_world = World::new();
298-
let mut new_world = World::new();
299-
300-
let mut map = EntityHashMap::default();
301-
let mut mapper = SceneEntityMapper::new(&mut map, &mut new_world);
302-
303-
assert_eq!(mapper.mappings().collect::<Vec<_>>(), vec![]);
304-
305-
let old_entity = old_world.spawn_empty().id();
306-
307-
let new_entity = mapper.map_entity(old_entity);
308-
309-
assert_eq!(
310-
mapper.mappings().collect::<Vec<_>>(),
311-
vec![(old_entity, new_entity)]
312-
);
313-
}
314-
315246
#[test]
316247
fn entity_mapper_no_panic() {
317248
let mut world = World::new();
@@ -328,9 +259,4 @@ mod tests {
328259
// The SceneEntityMapper should leave `Entities` in a flushed state.
329260
assert!(!world.entities.needs_flush());
330261
}
331-
332-
#[test]
333-
fn dyn_entity_mapper_object_safe() {
334-
assert_object_safe::<dyn DynEntityMapper>();
335-
}
336262
}

crates/bevy_ecs/src/reflect/map_entities.rs

Lines changed: 18 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,37 @@
1-
use crate::{
2-
component::Component,
3-
entity::{Entity, EntityHashMap, MapEntities, SceneEntityMapper},
4-
world::World,
5-
};
6-
use bevy_reflect::FromType;
1+
use crate::entity::{EntityMapper, MapEntities};
2+
use bevy_reflect::{FromReflect, FromType, PartialReflect};
73

8-
/// For a specific type of component, this maps any fields with values of type [`Entity`] to a new world.
4+
/// For a specific type of value, this maps any fields with values of type [`Entity`] to a new world.
95
///
106
/// Since a given `Entity` ID is only valid for the world it came from, when performing deserialization
117
/// any stored IDs need to be re-allocated in the destination world.
128
///
13-
/// See [`SceneEntityMapper`] and [`MapEntities`] for more information.
9+
/// See [`EntityMapper`] and [`MapEntities`] for more information.
10+
///
11+
/// [`Entity`]: crate::entity::Entity
12+
/// [`EntityMapper`]: crate::entity::EntityMapper
1413
#[derive(Clone)]
1514
pub struct ReflectMapEntities {
16-
map_all_entities: fn(&mut World, &mut SceneEntityMapper),
17-
map_entities: fn(&mut World, &mut SceneEntityMapper, &[Entity]),
15+
map_entities: fn(&mut dyn PartialReflect, &mut dyn EntityMapper),
1816
}
1917

2018
impl ReflectMapEntities {
21-
/// A general method for applying [`MapEntities`] behavior to all elements in an [`EntityHashMap<Entity>`].
22-
///
23-
/// Be mindful in its usage: Works best in situations where the entities in the [`EntityHashMap<Entity>`] are newly
24-
/// created, before systems have a chance to add new components. If some of the entities referred to
25-
/// by the [`EntityHashMap<Entity>`] might already contain valid entity references, you should use [`map_entities`](Self::map_entities).
26-
///
27-
/// An example of this: A scene can be loaded with `Parent` components, but then a `Parent` component can be added
28-
/// to these entities after they have been loaded. If you reload the scene using [`map_all_entities`](Self::map_all_entities), those `Parent`
29-
/// components with already valid entity references could be updated to point at something else entirely.
30-
pub fn map_all_entities(&self, world: &mut World, entity_map: &mut EntityHashMap<Entity>) {
31-
SceneEntityMapper::world_scope(entity_map, world, self.map_all_entities);
32-
}
33-
34-
/// A general method for applying [`MapEntities`] behavior to elements in an [`EntityHashMap<Entity>`]. Unlike
35-
/// [`map_all_entities`](Self::map_all_entities), this is applied to specific entities, not all values
36-
/// in the [`EntityHashMap<Entity>`].
19+
/// A general method for remapping entities in a reflected value via an [`EntityMapper`].
3720
///
38-
/// This is useful mostly for when you need to be careful not to update components that already contain valid entity
39-
/// values. See [`map_all_entities`](Self::map_all_entities) for more details.
40-
pub fn map_entities(
41-
&self,
42-
world: &mut World,
43-
entity_map: &mut EntityHashMap<Entity>,
44-
entities: &[Entity],
45-
) {
46-
SceneEntityMapper::world_scope(entity_map, world, |world, mapper| {
47-
(self.map_entities)(world, mapper, entities);
48-
});
21+
/// # Panics
22+
/// Panics if the the type of the reflected value doesn't match.
23+
pub fn map_entities(&self, reflected: &mut dyn PartialReflect, mapper: &mut dyn EntityMapper) {
24+
(self.map_entities)(reflected, mapper);
4925
}
5026
}
5127

52-
impl<C: Component + MapEntities> FromType<C> for ReflectMapEntities {
28+
impl<C: FromReflect + MapEntities> FromType<C> for ReflectMapEntities {
5329
fn from_type() -> Self {
5430
ReflectMapEntities {
55-
map_entities: |world, entity_mapper, entities| {
56-
for &entity in entities {
57-
if let Some(mut component) = world.get_mut::<C>(entity) {
58-
component.map_entities(entity_mapper);
59-
}
60-
}
61-
},
62-
map_all_entities: |world, entity_mapper| {
63-
let entities = entity_mapper
64-
.get_map()
65-
.values()
66-
.copied()
67-
.collect::<Vec<Entity>>();
68-
for entity in &entities {
69-
if let Some(mut component) = world.get_mut::<C>(*entity) {
70-
component.map_entities(entity_mapper);
71-
}
72-
}
73-
},
74-
}
75-
}
76-
}
77-
78-
/// For a specific type of resource, this maps any fields with values of type [`Entity`] to a new world.
79-
///
80-
/// Since a given `Entity` ID is only valid for the world it came from, when performing deserialization
81-
/// any stored IDs need to be re-allocated in the destination world.
82-
///
83-
/// See [`SceneEntityMapper`] and [`MapEntities`] for more information.
84-
#[derive(Clone)]
85-
pub struct ReflectMapEntitiesResource {
86-
map_entities: fn(&mut World, &mut SceneEntityMapper),
87-
}
88-
89-
impl ReflectMapEntitiesResource {
90-
/// A method for applying [`MapEntities`] behavior to elements in an [`EntityHashMap<Entity>`].
91-
pub fn map_entities(&self, world: &mut World, entity_map: &mut EntityHashMap<Entity>) {
92-
SceneEntityMapper::world_scope(entity_map, world, |world, mapper| {
93-
(self.map_entities)(world, mapper);
94-
});
95-
}
96-
}
97-
98-
impl<R: crate::system::Resource + MapEntities> FromType<R> for ReflectMapEntitiesResource {
99-
fn from_type() -> Self {
100-
ReflectMapEntitiesResource {
101-
map_entities: |world, entity_mapper| {
102-
if let Some(mut resource) = world.get_resource_mut::<R>() {
103-
resource.map_entities(entity_mapper);
104-
}
31+
map_entities: |reflected, mut mapper| {
32+
let mut concrete = C::from_reflect(reflected).expect("reflected type should match");
33+
concrete.map_entities(&mut mapper);
34+
reflected.apply(&concrete);
10535
},
10636
}
10737
}

crates/bevy_ecs/src/reflect/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub use bundle::{ReflectBundle, ReflectBundleFns};
2424
pub use component::{ReflectComponent, ReflectComponentFns};
2525
pub use entity_commands::ReflectCommandExt;
2626
pub use from_world::{ReflectFromWorld, ReflectFromWorldFns};
27-
pub use map_entities::{ReflectMapEntities, ReflectMapEntitiesResource};
27+
pub use map_entities::ReflectMapEntities;
2828
pub use resource::{ReflectResource, ReflectResourceFns};
2929
pub use visit_entities::{ReflectVisitEntities, ReflectVisitEntitiesMut};
3030

crates/bevy_pbr/src/meshlet/from_mesh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl MeshletMesh {
3030
let indices = validate_input_mesh(mesh)?;
3131

3232
// Split the mesh into an initial list of meshlets (LOD 0)
33-
let vertex_buffer = mesh.get_vertex_buffer_data();
33+
let vertex_buffer = mesh.create_packed_vertex_buffer_data();
3434
let vertex_stride = mesh.get_vertex_size() as usize;
3535
let vertices = VertexDataAdapter::new(&vertex_buffer, vertex_stride, 0).unwrap();
3636
let mut meshlets = compute_meshlets(&indices, &vertices);

crates/bevy_render/src/mesh/allocator.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ impl MeshAllocator {
427427
if self.general_vertex_slabs_supported {
428428
self.allocate(
429429
mesh_id,
430-
mesh.get_vertex_buffer_data().len() as u64,
430+
mesh.get_vertex_size() * mesh.count_vertices() as u64,
431431
vertex_element_layout,
432432
&mut slabs_to_grow,
433433
mesh_allocator_settings,
@@ -474,12 +474,11 @@ impl MeshAllocator {
474474
let Some(&slab_id) = self.mesh_id_to_vertex_slab.get(mesh_id) else {
475475
return;
476476
};
477-
let vertex_data = mesh.get_vertex_buffer_data();
477+
let vertex_data = mesh.create_packed_vertex_buffer_data();
478478

479479
// Call the generic function.
480480
self.copy_element_data(
481481
mesh_id,
482-
mesh,
483482
&vertex_data,
484483
BufferUsages::VERTEX,
485484
slab_id,
@@ -507,7 +506,6 @@ impl MeshAllocator {
507506
// Call the generic function.
508507
self.copy_element_data(
509508
mesh_id,
510-
mesh,
511509
index_data,
512510
BufferUsages::INDEX,
513511
slab_id,
@@ -521,7 +519,6 @@ impl MeshAllocator {
521519
fn copy_element_data(
522520
&mut self,
523521
mesh_id: &AssetId<Mesh>,
524-
mesh: &Mesh,
525522
data: &[u8],
526523
buffer_usages: BufferUsages,
527524
slab_id: SlabId,
@@ -567,7 +564,7 @@ impl MeshAllocator {
567564
slab_id,
568565
buffer_usages_to_str(buffer_usages)
569566
)),
570-
contents: &mesh.get_vertex_buffer_data(),
567+
contents: data,
571568
usage: buffer_usages | BufferUsages::COPY_DST,
572569
},
573570
));

crates/bevy_render/src/mesh/mesh/mod.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,8 @@ impl Mesh {
458458
///
459459
/// If the vertex attributes have different lengths, they are all truncated to
460460
/// the length of the smallest.
461-
pub fn get_vertex_buffer_data(&self) -> Vec<u8> {
462-
let mut vertex_size = 0;
463-
for attribute_data in self.attributes.values() {
464-
let vertex_format = attribute_data.attribute.format;
465-
vertex_size += vertex_format.get_size() as usize;
466-
}
467-
461+
pub fn create_packed_vertex_buffer_data(&self) -> Vec<u8> {
462+
let vertex_size = self.get_vertex_size() as usize;
468463
let vertex_count = self.count_vertices();
469464
let mut attributes_interleaved_buffer = vec![0; vertex_count * vertex_size];
470465
// bundle into interleaved buffers

0 commit comments

Comments
 (0)