-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Replace VisitEntities with MapEntities #18432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I've opened up a pull request on this pull request to implement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm excited about this change!
I'm going to hold off on merging this, as I think I'd like to walk back the |
# Objective There are currently too many disparate ways to handle entity mapping, especially after #17687. We now have MapEntities, VisitEntities, VisitEntitiesMut, Component::visit_entities, Component::visit_entities_mut. Our only known use case at the moment for these is entity mapping. This means we have significant consolidation potential. Additionally, VisitEntitiesMut cannot be implemented for map-style collections like HashSets, as you cant "just" mutate a `&mut Entity`. Our current approach to Component mapping requires VisitEntitiesMut, meaning this category of entity collection isn't mappable. `MapEntities` is more generally applicable. Additionally, the _existence_ of the blanket From impl on VisitEntitiesMut blocks us from implementing MapEntities for HashSets (or any types we don't own), because the owner could always add a conflicting impl in the future. ## Solution Use `MapEntities` everywhere and remove all "visit entities" usages. * Add `Component::map_entities` * Remove `Component::visit_entities`, `Component::visit_entities_mut`, `VisitEntities`, and `VisitEntitiesMut` * Support deriving `Component::map_entities` in `#[derive(Coomponent)]` * Add `#[derive(MapEntities)]`, and share logic with the `Component::map_entities` derive. * Add `ComponentCloneCtx::queue_deferred`, which is command-like logic that runs immediately after normal clones. Reframe `FromWorld` fallback logic in the "reflect clone" impl to use it. This cuts out a lot of unnecessary work and I think justifies the existence of a pseudo-command interface (given how niche, yet performance sensitive this is). Note that we no longer auto-impl entity mapping for ` IntoIterator<Item = &'a Entity>` types, as this would block our ability to implement cases like `HashMap`. This means the onus is on us (or type authors) to add explicit support for types that should be mappable. Also note that the Component-related changes do not require a migration guide as there hasn't been a release with them yet. ## Migration Guide If you were previously implementing `VisitEntities` or `VisitEntitiesMut` (likely via a derive), instead use `MapEntities`. Those were almost certainly used in the context of Bevy Scenes or reflection via `ReflectMapEntities`. If you have a case that uses `VisitEntities` or `VisitEntitiesMut` directly, where `MapEntities` is not a viable replacement, please let us know! ```rust // before #[derive(VisitEntities, VisitEntitiesMut)] struct Inventory { items: Vec<Entity>, #[visit_entities(ignore)] label: String, } // after #[derive(MapEntities)] struct Inventory { #[entities] items: Vec<Entity>, label: String, } ```
Objective
There are currently too many disparate ways to handle entity mapping, especially after #17687. We now have MapEntities, VisitEntities, VisitEntitiesMut, Component::visit_entities, Component::visit_entities_mut.
Our only known use case at the moment for these is entity mapping. This means we have significant consolidation potential.
Additionally, VisitEntitiesMut cannot be implemented for map-style collections like HashSets, as you cant "just" mutate a
&mut Entity
. Our current approach to Component mapping requires VisitEntitiesMut, meaning this category of entity collection isn't mappable.MapEntities
is more generally applicable. Additionally, the existence of the blanket From impl on VisitEntitiesMut blocks us from implementing MapEntities for HashSets (or any types we don't own), because the owner could always add a conflicting impl in the future.Solution
Use
MapEntities
everywhere and remove all "visit entities" usages.Component::map_entities
Component::visit_entities
,Component::visit_entities_mut
,VisitEntities
, andVisitEntitiesMut
Component::map_entities
in#[derive(Coomponent)]
#[derive(MapEntities)]
, and share logic with theComponent::map_entities
derive.ComponentCloneCtx::queue_deferred
, which is command-like logic that runs immediately after normal clones. ReframeFromWorld
fallback logic in the "reflect clone" impl to use it. This cuts out a lot of unnecessary work and I think justifies the existence of a pseudo-command interface (given how niche, yet performance sensitive this is).Note that we no longer auto-impl entity mapping for
IntoIterator<Item = &'a Entity>
types, as this would block our ability to implement cases likeHashMap
. This means the onus is on us (or type authors) to add explicit support for types that should be mappable.Also note that the Component-related changes do not require a migration guide as there hasn't been a release with them yet.
Migration Guide
If you were previously implementing
VisitEntities
orVisitEntitiesMut
(likely via a derive), instead useMapEntities
. Those were almost certainly used in the context of Bevy Scenes or reflection viaReflectMapEntities
. If you have a case that usesVisitEntities
orVisitEntitiesMut
directly, whereMapEntities
is not a viable replacement, please let us know!