Skip to content

Commit c700dcf

Browse files
committed
Improved Entity Mapping and Cloning
1 parent 8c7f1b3 commit c700dcf

File tree

27 files changed

+1095
-749
lines changed

27 files changed

+1095
-749
lines changed

benches/benches/bevy_ecs/entity_cloning.rs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use core::hint::black_box;
22

33
use benches::bench;
44
use bevy_ecs::bundle::Bundle;
5-
use bevy_ecs::component::ComponentCloneHandler;
5+
use bevy_ecs::component::ComponentCloneBehavior;
6+
use bevy_ecs::entity::EntityCloner;
67
use bevy_ecs::hierarchy::ChildOf;
78
use bevy_ecs::reflect::AppTypeRegistry;
89
use bevy_ecs::{component::Component, world::World};
@@ -52,7 +53,10 @@ type ComplexBundle = (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10);
5253

5354
/// Sets the [`ComponentCloneHandler`] for all explicit and required components in a bundle `B` to
5455
/// use the [`Reflect`] trait instead of [`Clone`].
55-
fn set_reflect_clone_handler<B: Bundle + GetTypeRegistration>(world: &mut World) {
56+
fn reflection_cloner<B: Bundle + GetTypeRegistration>(
57+
world: &mut World,
58+
recursive: bool,
59+
) -> EntityCloner {
5660
// Get mutable access to the type registry, creating it if it does not exist yet.
5761
let registry = world.get_resource_or_init::<AppTypeRegistry>();
5862

@@ -67,12 +71,15 @@ fn set_reflect_clone_handler<B: Bundle + GetTypeRegistration>(world: &mut World)
6771
// this bundle are saved.
6872
let component_ids: Vec<_> = world.register_bundle::<B>().contributed_components().into();
6973

70-
let clone_handlers = world.get_component_clone_handlers_mut();
74+
let mut builder = EntityCloner::build(world);
7175

7276
// Overwrite the clone handler for all components in the bundle to use `Reflect`, not `Clone`.
7377
for component in component_ids {
74-
clone_handlers.set_component_handler(component, ComponentCloneHandler::reflect_handler());
78+
builder.override_clone_behavior_with_id(component, ComponentCloneBehavior::reflect());
7579
}
80+
builder.recursive(recursive);
81+
82+
builder.finish()
7683
}
7784

7885
/// A helper function that benchmarks running the [`EntityCommands::clone_and_spawn()`] command on a
@@ -91,18 +98,18 @@ fn bench_clone<B: Bundle + Default + GetTypeRegistration>(
9198
) {
9299
let mut world = World::default();
93100

94-
if clone_via_reflect {
95-
set_reflect_clone_handler::<B>(&mut world);
96-
}
101+
let mut cloner = if clone_via_reflect {
102+
reflection_cloner::<B>(&mut world, false)
103+
} else {
104+
EntityCloner::default()
105+
};
97106

98107
// Spawn the first entity, which will be cloned in the benchmark routine.
99108
let id = world.spawn(B::default()).id();
100109

101110
b.iter(|| {
102-
// Queue the command to clone the entity.
103-
world.commands().entity(black_box(id)).clone_and_spawn();
104-
105-
// Run the command.
111+
// clones the given entity
112+
cloner.spawn_clone(&mut world, black_box(id));
106113
world.flush();
107114
});
108115
}
@@ -125,9 +132,15 @@ fn bench_clone_hierarchy<B: Bundle + Default + GetTypeRegistration>(
125132
) {
126133
let mut world = World::default();
127134

128-
if clone_via_reflect {
129-
set_reflect_clone_handler::<B>(&mut world);
130-
}
135+
let mut cloner = if clone_via_reflect {
136+
reflection_cloner::<B>(&mut world, true)
137+
} else {
138+
let mut builder = EntityCloner::build(&mut world);
139+
builder.recursive(true);
140+
builder.finish()
141+
};
142+
143+
// Make the clone command recursive, so children are cloned as well.
131144

132145
// Spawn the first entity, which will be cloned in the benchmark routine.
133146
let id = world.spawn(B::default()).id();
@@ -148,18 +161,8 @@ fn bench_clone_hierarchy<B: Bundle + Default + GetTypeRegistration>(
148161
}
149162
}
150163

151-
// Flush all `set_parent()` commands.
152-
world.flush();
153-
154164
b.iter(|| {
155-
world
156-
.commands()
157-
.entity(black_box(id))
158-
.clone_and_spawn_with(|builder| {
159-
// Make the clone command recursive, so children are cloned as well.
160-
builder.recursive(true);
161-
});
162-
165+
cloner.spawn_clone(&mut world, black_box(id));
163166
world.flush();
164167
});
165168
}

crates/bevy_animation/src/lib.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,7 @@ use crate::{
3333

3434
use bevy_app::{Animation, App, Plugin, PostUpdate};
3535
use bevy_asset::{Asset, AssetApp, Assets};
36-
use bevy_ecs::{
37-
entity::{VisitEntities, VisitEntitiesMut},
38-
prelude::*,
39-
reflect::{ReflectMapEntities, ReflectVisitEntities, ReflectVisitEntitiesMut},
40-
world::EntityMutExcept,
41-
};
36+
use bevy_ecs::{prelude::*, world::EntityMutExcept};
4237
use bevy_math::FloatOrd;
4338
use bevy_platform_support::{collections::HashMap, hash::NoOpHash};
4439
use bevy_reflect::{prelude::ReflectDefault, Reflect, TypePath};
@@ -207,16 +202,16 @@ impl Hash for AnimationTargetId {
207202
/// Note that each entity can only be animated by one animation player at a
208203
/// time. However, you can change [`AnimationTarget`]'s `player` property at
209204
/// runtime to change which player is responsible for animating the entity.
210-
#[derive(Clone, Copy, Component, Reflect, VisitEntities, VisitEntitiesMut)]
211-
#[reflect(Component, MapEntities, VisitEntities, VisitEntitiesMut)]
205+
#[derive(Clone, Copy, Component, Reflect)]
206+
#[reflect(Component)]
212207
pub struct AnimationTarget {
213208
/// The ID of this animation target.
214209
///
215210
/// Typically, this is derived from the path.
216-
#[visit_entities(ignore)]
217211
pub id: AnimationTargetId,
218212

219213
/// The entity containing the [`AnimationPlayer`].
214+
#[entities]
220215
pub player: Entity,
221216
}
222217

0 commit comments

Comments
 (0)