-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Added with_component
to EntityWorldMut
, DeferredWorld
, and World
#16668
base: main
Are you sure you want to change the base?
Conversation
f: impl FnOnce(&mut T) -> R, | ||
) -> Result<Option<R>, EntityFetchError> { | ||
// If the component is not registered, then it doesn't exist on this entity, so no action required. | ||
let Some(component_id) = self.component_id::<T>() else { |
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.
Would it make sense to have a with_component_by_id
method that works with dynamic components?
... oh, there's no get_mut_assume_mutable_by_id
. Should we add that?
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.
That definitely could make sense! I'd rather spin that into a follow-up if this gets accepted though.
.expect("component access confirmed above") | ||
}; | ||
|
||
let result = f(&mut component); |
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.
Would it be useful to pass an EntityMutExcept<T>
to let the closure access the other components on the entity?
Or maybe that's dangerous because we triggered the "on replace" hooks but didn't flush their commands, so f
could see an inconsistent world?
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.
Yeah I see room for issues if you had access to the rest of the entity too. In my mind, if you need this you'd actually remove the component instead.
What about |
Also ensure commands are always flushed when using `World::with_component`
The reason I chose |
Objective
Parent
andChildren
components immutable #16662Solution
Added
with_component
toWorld
andEntityWorldMut
. This method "removes" a component from an entity, gives a mutable reference to it to a provided closure, and then "re-inserts" the component back onto the entity. This replacement triggers theOnReplace
andOnInsert
hooks, but does not cause an archetype move, as the removal is purely simulated.Testing
Showcase
Notes
None
is returned. I chose this as an alternative to returning an error or panicking, but I'm open to changing that based on feedback.unsafe
, in particular for accessing theArchetype
to trigger hooks. All the unsafe operations are contained withinDeferredWorld::with_component
, and I would appreciate that this function is given special attention to ensure soundness.OnAdd
hook can never be triggered by this method, since the component must already be inserted. I have chosen to not triggerOnRemove
, as I believe it makes sense that this method is purely a replacement operation, not an actual removal/insertion.