Add apply_or_insert functions to reflected component and resources (#5201)
# Objective `ReflectResource` and `ReflectComponent` will panic on `apply` method if there is no such component. It's not very ergonomic. And not very good for performance since I need to check if such component exists first. ## Solution * Add `ReflectComponent::apply_or_insert` and `ReflectResource::apply_or_insert` functions. * Rename `ReflectComponent::add` into `ReflectComponent::insert` for consistency. --- ## Changelog ### Added * `ReflectResource::apply_or_insert` and `ReflectComponent::apply_on_insert`. ### Changed * Rename `ReflectComponent::add` into `ReflectComponent::insert` for consistency. * Use `ReflectComponent::apply_on_insert` in `DynamicScene` instead of manual checking. ## Migration Guide * Rename `ReflectComponent::add` into `ReflectComponent::insert`.
This commit is contained in:
parent
8de03b0839
commit
1da6720132
@ -18,8 +18,9 @@ use bevy_reflect::{
|
||||
/// [`bevy_reflect::TypeRegistration::data`].
|
||||
#[derive(Clone)]
|
||||
pub struct ReflectComponent {
|
||||
add: fn(&mut World, Entity, &dyn Reflect),
|
||||
insert: fn(&mut World, Entity, &dyn Reflect),
|
||||
apply: fn(&mut World, Entity, &dyn Reflect),
|
||||
apply_or_insert: fn(&mut World, Entity, &dyn Reflect),
|
||||
remove: fn(&mut World, Entity),
|
||||
reflect: fn(&World, Entity) -> Option<&dyn Reflect>,
|
||||
reflect_mut: unsafe fn(&World, Entity) -> Option<ReflectMut>,
|
||||
@ -32,8 +33,8 @@ impl ReflectComponent {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if there is no such entity.
|
||||
pub fn add(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
|
||||
(self.add)(world, entity, component);
|
||||
pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
|
||||
(self.insert)(world, entity, component);
|
||||
}
|
||||
|
||||
/// Uses reflection to set the value of this [`Component`] type in the entity to the given value.
|
||||
@ -45,6 +46,15 @@ impl ReflectComponent {
|
||||
(self.apply)(world, entity, component);
|
||||
}
|
||||
|
||||
/// Uses reflection to set the value of this [`Component`] type in the entity to the given value or insert a new one if it does not exist.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the `entity` does not exist.
|
||||
pub fn apply_or_insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
|
||||
(self.apply_or_insert)(world, entity, component);
|
||||
}
|
||||
|
||||
/// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist.
|
||||
///
|
||||
/// # Panics
|
||||
@ -103,7 +113,7 @@ impl ReflectComponent {
|
||||
impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
|
||||
fn from_type() -> Self {
|
||||
ReflectComponent {
|
||||
add: |world, entity, reflected_component| {
|
||||
insert: |world, entity, reflected_component| {
|
||||
let mut component = C::from_world(world);
|
||||
component.apply(reflected_component);
|
||||
world.entity_mut(entity).insert(component);
|
||||
@ -112,6 +122,15 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
|
||||
let mut component = world.get_mut::<C>(entity).unwrap();
|
||||
component.apply(reflected_component);
|
||||
},
|
||||
apply_or_insert: |world, entity, reflected_component| {
|
||||
if let Some(mut component) = world.get_mut::<C>(entity) {
|
||||
component.apply(reflected_component);
|
||||
} else {
|
||||
let mut component = C::from_world(world);
|
||||
component.apply(reflected_component);
|
||||
world.entity_mut(entity).insert(component);
|
||||
}
|
||||
},
|
||||
remove: |world, entity| {
|
||||
world.entity_mut(entity).remove::<C>();
|
||||
},
|
||||
@ -154,6 +173,7 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
|
||||
pub struct ReflectResource {
|
||||
insert: fn(&mut World, &dyn Reflect),
|
||||
apply: fn(&mut World, &dyn Reflect),
|
||||
apply_or_insert: fn(&mut World, &dyn Reflect),
|
||||
remove: fn(&mut World),
|
||||
reflect: fn(&World) -> Option<&dyn Reflect>,
|
||||
reflect_unchecked_mut: unsafe fn(&World) -> Option<ReflectMut>,
|
||||
@ -175,6 +195,11 @@ impl ReflectResource {
|
||||
(self.apply)(world, resource);
|
||||
}
|
||||
|
||||
/// Uses reflection to set the value of this [`Resource`] type in the world to the given value or insert a new one if it does not exist.
|
||||
pub fn apply_or_insert(&self, world: &mut World, resource: &dyn Reflect) {
|
||||
(self.apply_or_insert)(world, resource);
|
||||
}
|
||||
|
||||
/// Removes this [`Resource`] type from the world. Does nothing if it doesn't exist.
|
||||
pub fn remove(&self, world: &mut World) {
|
||||
(self.remove)(world);
|
||||
@ -224,6 +249,15 @@ impl<C: Resource + Reflect + FromWorld> FromType<C> for ReflectResource {
|
||||
let mut resource = world.resource_mut::<C>();
|
||||
resource.apply(reflected_resource);
|
||||
},
|
||||
apply_or_insert: |world, reflected_resource| {
|
||||
if let Some(mut resource) = world.get_resource_mut::<C>() {
|
||||
resource.apply(reflected_resource);
|
||||
} else {
|
||||
let mut resource = C::from_world(world);
|
||||
resource.apply(reflected_resource);
|
||||
world.insert_resource(resource);
|
||||
}
|
||||
},
|
||||
remove: |world| {
|
||||
world.remove_resource::<C>();
|
||||
},
|
||||
|
||||
@ -112,14 +112,7 @@ impl DynamicScene {
|
||||
// If the entity already has the given component attached,
|
||||
// just apply the (possibly) new value, otherwise add the
|
||||
// component to the entity.
|
||||
if world
|
||||
.entity(entity)
|
||||
.contains_type_id(registration.type_id())
|
||||
{
|
||||
reflect_component.apply(world, entity, &**component);
|
||||
} else {
|
||||
reflect_component.add(world, entity, &**component);
|
||||
}
|
||||
reflect_component.apply_or_insert(world, entity, &**component);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user