Add a set_parent method to ChildBuilder#5845
Add a set_parent method to ChildBuilder#5845nicopap wants to merge 4 commits intobevyengine:mainfrom
set_parent method to ChildBuilder#5845Conversation
This allows removing a few `unsafe` in child_builder.
djeedai
left a comment
There was a problem hiding this comment.
I'm not familiar enough with ECS to be sure the change is good, though I like the idea and it's certainly useful. Some remarks though on the documenting comments themselves that could be improved I think. Thanks!
| /// This is a safe alternative to [`EntityMut::world_mut`]. | ||
| /// | ||
| /// If you _know_ that `use_world` doesn't change the current entity's location, | ||
| /// then `self.update_location` is extaneous and it might be more efficient to use |
There was a problem hiding this comment.
| /// then `self.update_location` is extaneous and it might be more efficient to use | |
| /// then `self.update_location` is extraneous and it might be more efficient to use |
| self.world | ||
| } | ||
|
|
||
| /// Access the inner `&mut World` within `use_world` and run [`Self::update_location`]. |
There was a problem hiding this comment.
I've read the entire comment for this method but I have no idea what it means. This sounds like a fairly advanced usage. I don't know what use_world() does, nor update_location(). Can we try to give a little bit more detail, and maybe give an example of when this method is useful?
There was a problem hiding this comment.
use_world is the function parameter. update_location is linked in the doc, because it is surrounded in [], if someone is reading the documentation and doesn't know what update_location is, they should be able to click on the link and read the update_location documentation.
There was a problem hiding this comment.
| /// Access the inner `&mut World` within `use_world` and run [`Self::update_location`]. | |
| /// Access the inner `&mut World` within the `use_world` function argument and run [`Self::update_location`]. |
|
|
||
| /// Command that removes children from an entity, and removes that child's parent and inserts it into the previous parent component | ||
| /// Command that removes children from an entity, | ||
| /// and removes that child's parent and inserts it into the previous parent component |
There was a problem hiding this comment.
I don't understand that second part. First, the use of singular on child is confusing since the first part of the sentence uses the plural children, though I assume we're talking here about the removed children? Then, we don't "remove the parent", we actually remove the Parent component from the Entity, don't we? And then I still don't understand the last bit about inserting into the previous parent component. Sorry I know the original comment was the same before your change, but if you could clean it up while you're touching it that'd be beneficial I think. Thanks!
There was a problem hiding this comment.
It's the same comment than before, I only changed the formatting, I feel like this shouldn't be in scope of this PR, but I agree the phrasing can be improved.
There was a problem hiding this comment.
Yep, I'm fine to leave this alone for this PR.
| /// Spawns an [`Entity`] with no components | ||
| /// and inserts it into the children defined by the [`ChildBuilder`] | ||
| /// which adds the [`Parent`] component to it. |
There was a problem hiding this comment.
Same, that comment is quite confusing to me. How about:
/// Spawns an [`Entity`] without any component, and inserts it into the collection of children
/// of the current [`ChildBuilder`]. A [`Parent`] component is automatically added to that new
/// entity.
There was a problem hiding this comment.
I think we can avoid bikeshedding on these doc changes here. I'm fine leaving them how they are or reverting them completely.
|
|
||
| /// Set the parent. | ||
| /// | ||
| /// This overwrites the existing parent. |
There was a problem hiding this comment.
...I assume, for all children of the underlying collection at once?
There was a problem hiding this comment.
The idea is that
child.set_parent(parent)
// is equivalent to
parent.add_child(child)I don't understand what you mean by "for all children of the underlying collection". Could you precise?
If you mean the Children component of the parent, the answer is no. set_parent just sets the parent of an entity, so it does nothing else than:
- Add a
Parent(parent)component to thechild - Push
childto theChildrencomponent of theparent
|
|
||
| fn set_parent(&mut self, parent: Entity) -> &mut Self { | ||
| let child = self.id(); | ||
| self.commands().add(AddChild { child, parent }); |
There was a problem hiding this comment.
Does that really work? What if there's already the opposite AddChild from the above add_child() call, do we correctly overwrite? I'm a bit surprised that we don't need to do any more book-keeping here.
There was a problem hiding this comment.
I might add more test. But logically, if AddChild { parent, child } works, I don't see why AddChild { child, parent } wouldn't.
There was a problem hiding this comment.
I'd like to see a simple test :)
| } | ||
|
|
||
| /// Spawns an [`Entity`] with no components and inserts it into the children defined by the [`WorldChildBuilder`] which adds the [`Parent`] component to it. | ||
| /// Spawns an [`Entity`] with no components and inserts it |
There was a problem hiding this comment.
Same remark as previously, comment is fairly confusing to me.
| assert_eq!(*world.get::<Parent>(child1).unwrap(), Parent(parent)); | ||
| assert_eq!(*world.get::<Parent>(child2).unwrap(), Parent(parent)); | ||
|
|
||
| // Why are those assertions repeated? |
There was a problem hiding this comment.
Probably a mismerge. Can you please delete instead of adding a comment?
There was a problem hiding this comment.
I wasn't willing to remove those asserts before someone reviewed the PR and told me they were not here for a reason I was overlooking (this is called "Chesterton's Fence")
So I added the comment to attract the attention of reviewers and allow them to comment on the asserts.
There was a problem hiding this comment.
Yes absolutely, not blaming you here, that was the right call. But I think we both agree that this is useless and unlikely to have any real use? So I was just ACK'ing on the removal. Or do you want to wait for a second reviewer's opinion too? Im fine with that.
There was a problem hiding this comment.
We should remove the duplicate assertions.
| /// then `self.update_location` is extaneous and it might be more efficient to use | ||
| /// the unsafe `world_mut` method instead. | ||
| #[inline] | ||
| pub fn with_world_mut(&mut self, use_world: impl FnOnce(&mut World)) { |
There was a problem hiding this comment.
This needs a doc example to be clear enough for the average user. Cool bit of machinery though!
| // Inserting a bundle in the children entities may change the parent entity's location if they were of the same archetype | ||
| self.update_location(); | ||
| } | ||
| self.with_world_mut(|world| update_old_parents(world, parent, children)); |
There was a problem hiding this comment.
Really like the elimination of unsafe here.
|
Superseded by #6189 |
Objective
Depending on the use-case, since #4197, it can be hard
to specify a hierarchy of entities in bevy, especially when
declaring parents.
Solution
Currently, it's possible to use
parent.add_child(child),however, there is a few cases where this is highly inconvenient,
and would be better expressed with a
child.set_parent(parent)operation.Changelog
set_parentmethod toChildBuilderwith_world_mutmethod toEntityMutfor improved safety.