implement MapEntities for higher-order types (#19071)
# Objective With the current `MapEntities` `impl`s, it is not possible to derive things like this: ```rust #[derive(Component)] pub struct Inventory { #[entities] slots: Vec<Option<Entity>>, } ``` This is because `MapEntities` is only implemented for `Vec<Entity>` & `Option<Entity>`, and not arbitrary combinations of those. It would be nice to also support those types. ## Solution I replaced the `impl`s of the following types - `Option<Entity>`: replaced with `Option<T>` - `Vec<Entity>`: replaced with `Vec<T>` - `HashSet<Entity, S>`: replaced with `HashSet<T, S>` - `T` also had to be `Eq + core:#️⃣:Hash` here. **Not sure if this is too restrictive?** - `IndexSet<Entity, S>`: replaced with `IndexSet <T, S>` - `T` also had to be `Eq + core:#️⃣:Hash` here. **Not sure if this is too restrictive?** - `BTreeSet<Entity>`: replaced with `BTreeSet<T>` - `VecDeque<Entity>`: replaced with `VecDeque<T>` - `SmallVec<A: smallvec::Array<Item = Entity>>`: replaced with `SmallVec<A: smallvec::Array<Item = T>>` (in all of the above, `T` is a generic type that implements `MapEntities` (`Entity` being one of them).) ## Testing I did not test any of this, but extended the `Component::map_entities` doctest with an example usage of the newly supported types. --- ## Showcase With these changes, this is now possible: ```rust #[derive(Component)] pub struct Inventory { #[entities] slots: Vec<Option<Entity>>, } ```
This commit is contained in:
parent
8f3e45b45f
commit
b8724c21ce
@ -574,6 +574,17 @@ pub trait Component: Send + Sync + 'static {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Fields with `#[entities]` must implement [`MapEntities`](crate::entity::MapEntities).
|
/// Fields with `#[entities]` must implement [`MapEntities`](crate::entity::MapEntities).
|
||||||
|
///
|
||||||
|
/// Bevy provides various implementations of [`MapEntities`](crate::entity::MapEntities), so that arbitrary combinations like these are supported with `#[entities]`:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use bevy_ecs::{component::Component, entity::Entity};
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct Inventory {
|
||||||
|
/// #[entities]
|
||||||
|
/// items: Vec<Option<Entity>>
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
fn map_entities<E: EntityMapper>(_this: &mut Self, _mapper: &mut E) {}
|
fn map_entities<E: EntityMapper>(_this: &mut Self, _mapper: &mut E) {}
|
||||||
}
|
}
|
||||||
|
@ -65,25 +65,38 @@ impl MapEntities for Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapEntities for Option<Entity> {
|
impl<T: MapEntities> MapEntities for Option<T> {
|
||||||
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
||||||
if let Some(entity) = self {
|
if let Some(entities) = self {
|
||||||
*entity = entity_mapper.get_mapped(*entity);
|
entities.map_entities(entity_mapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BuildHasher + Default> MapEntities for HashSet<Entity, S> {
|
impl<T: MapEntities + Eq + core::hash::Hash, S: BuildHasher + Default> MapEntities
|
||||||
|
for HashSet<T, S>
|
||||||
|
{
|
||||||
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
||||||
*self = self.drain().map(|e| entity_mapper.get_mapped(e)).collect();
|
*self = self
|
||||||
|
.drain()
|
||||||
|
.map(|mut entities| {
|
||||||
|
entities.map_entities(entity_mapper);
|
||||||
|
entities
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BuildHasher + Default> MapEntities for IndexSet<Entity, S> {
|
impl<T: MapEntities + Eq + core::hash::Hash, S: BuildHasher + Default> MapEntities
|
||||||
|
for IndexSet<T, S>
|
||||||
|
{
|
||||||
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
||||||
*self = self
|
*self = self
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|e| entity_mapper.get_mapped(e))
|
.map(|mut entities| {
|
||||||
|
entities.map_entities(entity_mapper);
|
||||||
|
entities
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,35 +110,38 @@ impl MapEntities for EntityIndexSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapEntities for BTreeSet<Entity> {
|
impl<T: MapEntities + Ord> MapEntities for BTreeSet<T> {
|
||||||
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
||||||
*self = mem::take(self)
|
*self = mem::take(self)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| entity_mapper.get_mapped(e))
|
.map(|mut entities| {
|
||||||
|
entities.map_entities(entity_mapper);
|
||||||
|
entities
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapEntities for Vec<Entity> {
|
impl<T: MapEntities> MapEntities for Vec<T> {
|
||||||
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
||||||
for entity in self.iter_mut() {
|
for entities in self.iter_mut() {
|
||||||
*entity = entity_mapper.get_mapped(*entity);
|
entities.map_entities(entity_mapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapEntities for VecDeque<Entity> {
|
impl<T: MapEntities> MapEntities for VecDeque<T> {
|
||||||
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
||||||
for entity in self.iter_mut() {
|
for entities in self.iter_mut() {
|
||||||
*entity = entity_mapper.get_mapped(*entity);
|
entities.map_entities(entity_mapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: smallvec::Array<Item = Entity>> MapEntities for SmallVec<A> {
|
impl<T: MapEntities, A: smallvec::Array<Item = T>> MapEntities for SmallVec<A> {
|
||||||
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
|
||||||
for entity in self.iter_mut() {
|
for entities in self.iter_mut() {
|
||||||
*entity = entity_mapper.get_mapped(*entity);
|
entities.map_entities(entity_mapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user