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`].
|
/// [`bevy_reflect::TypeRegistration::data`].
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ReflectComponent {
|
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: fn(&mut World, Entity, &dyn Reflect),
|
||||||
|
apply_or_insert: fn(&mut World, Entity, &dyn Reflect),
|
||||||
remove: fn(&mut World, Entity),
|
remove: fn(&mut World, Entity),
|
||||||
reflect: fn(&World, Entity) -> Option<&dyn Reflect>,
|
reflect: fn(&World, Entity) -> Option<&dyn Reflect>,
|
||||||
reflect_mut: unsafe fn(&World, Entity) -> Option<ReflectMut>,
|
reflect_mut: unsafe fn(&World, Entity) -> Option<ReflectMut>,
|
||||||
@ -32,8 +33,8 @@ impl ReflectComponent {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if there is no such entity.
|
/// Panics if there is no such entity.
|
||||||
pub fn add(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
|
pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
|
||||||
(self.add)(world, entity, component);
|
(self.insert)(world, entity, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses reflection to set the value of this [`Component`] type in the entity to the given value.
|
/// 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);
|
(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.
|
/// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
@ -103,7 +113,7 @@ impl ReflectComponent {
|
|||||||
impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
|
impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
|
||||||
fn from_type() -> Self {
|
fn from_type() -> Self {
|
||||||
ReflectComponent {
|
ReflectComponent {
|
||||||
add: |world, entity, reflected_component| {
|
insert: |world, entity, reflected_component| {
|
||||||
let mut component = C::from_world(world);
|
let mut component = C::from_world(world);
|
||||||
component.apply(reflected_component);
|
component.apply(reflected_component);
|
||||||
world.entity_mut(entity).insert(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();
|
let mut component = world.get_mut::<C>(entity).unwrap();
|
||||||
component.apply(reflected_component);
|
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| {
|
remove: |world, entity| {
|
||||||
world.entity_mut(entity).remove::<C>();
|
world.entity_mut(entity).remove::<C>();
|
||||||
},
|
},
|
||||||
@ -154,6 +173,7 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
|
|||||||
pub struct ReflectResource {
|
pub struct ReflectResource {
|
||||||
insert: fn(&mut World, &dyn Reflect),
|
insert: fn(&mut World, &dyn Reflect),
|
||||||
apply: fn(&mut World, &dyn Reflect),
|
apply: fn(&mut World, &dyn Reflect),
|
||||||
|
apply_or_insert: fn(&mut World, &dyn Reflect),
|
||||||
remove: fn(&mut World),
|
remove: fn(&mut World),
|
||||||
reflect: fn(&World) -> Option<&dyn Reflect>,
|
reflect: fn(&World) -> Option<&dyn Reflect>,
|
||||||
reflect_unchecked_mut: unsafe fn(&World) -> Option<ReflectMut>,
|
reflect_unchecked_mut: unsafe fn(&World) -> Option<ReflectMut>,
|
||||||
@ -175,6 +195,11 @@ impl ReflectResource {
|
|||||||
(self.apply)(world, resource);
|
(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.
|
/// Removes this [`Resource`] type from the world. Does nothing if it doesn't exist.
|
||||||
pub fn remove(&self, world: &mut World) {
|
pub fn remove(&self, world: &mut World) {
|
||||||
(self.remove)(world);
|
(self.remove)(world);
|
||||||
@ -224,6 +249,15 @@ impl<C: Resource + Reflect + FromWorld> FromType<C> for ReflectResource {
|
|||||||
let mut resource = world.resource_mut::<C>();
|
let mut resource = world.resource_mut::<C>();
|
||||||
resource.apply(reflected_resource);
|
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| {
|
remove: |world| {
|
||||||
world.remove_resource::<C>();
|
world.remove_resource::<C>();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -112,14 +112,7 @@ impl DynamicScene {
|
|||||||
// If the entity already has the given component attached,
|
// If the entity already has the given component attached,
|
||||||
// just apply the (possibly) new value, otherwise add the
|
// just apply the (possibly) new value, otherwise add the
|
||||||
// component to the entity.
|
// component to the entity.
|
||||||
if world
|
reflect_component.apply_or_insert(world, entity, &**component);
|
||||||
.entity(entity)
|
|
||||||
.contains_type_id(registration.type_id())
|
|
||||||
{
|
|
||||||
reflect_component.apply(world, entity, &**component);
|
|
||||||
} else {
|
|
||||||
reflect_component.add(world, entity, &**component);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user