-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Add a set_parent
method to ChildBuilder
#5845
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -508,6 +508,19 @@ impl<'w> EntityMut<'w> { | |||||
self.world | ||||||
} | ||||||
|
||||||
/// Access the inner `&mut World` within `use_world` and run [`Self::update_location`]. | ||||||
/// | ||||||
/// 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs a doc example to be clear enough for the average user. Cool bit of machinery though! |
||||||
use_world(self.world); | ||||||
self.update_location(); | ||||||
} | ||||||
|
||||||
/// Return this `EntityMut`'s [`World`], consuming itself. | ||||||
#[inline] | ||||||
pub fn into_world_mut(self) -> &'w mut World { | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -166,7 +166,8 @@ impl Command for PushChildren { | |
} | ||
} | ||
|
||
/// 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand that second part. First, the use of singular on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, I'm fine to leave this alone for this PR. |
||
pub struct RemoveChildren { | ||
parent: Entity, | ||
children: SmallVec<[Entity; 8]>, | ||
|
@@ -192,7 +193,9 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> { | |
e | ||
} | ||
|
||
/// Spawns an [`Entity`] with no components and inserts it into the children defined by the [`ChildBuilder`] which adds the [`Parent`] component to it. | ||
/// Spawns an [`Entity`] with no components | ||
/// and inserts it into the children defined by the [`ChildBuilder`] | ||
/// which adds the [`Parent`] component to it. | ||
Comment on lines
+196
to
+198
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same, that comment is quite confusing to me. How about:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can avoid bikeshedding on these doc changes here. I'm fine leaving them how they are or reverting them completely. |
||
pub fn spawn(&mut self) -> EntityCommands<'w, 's, '_> { | ||
let e = self.commands.spawn(); | ||
self.push_children.children.push(e.id()); | ||
|
@@ -256,6 +259,11 @@ pub trait BuildChildren { | |
fn remove_children(&mut self, children: &[Entity]) -> &mut Self; | ||
/// Adds a single child | ||
fn add_child(&mut self, child: Entity) -> &mut Self; | ||
|
||
/// Set the parent. | ||
/// | ||
/// This overwrites the existing parent. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...I assume, for all children of the underlying collection at once? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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
|
||
fn set_parent(&mut self, parent: Entity) -> &mut Self; | ||
} | ||
|
||
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> { | ||
|
@@ -314,6 +322,12 @@ impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> { | |
self.commands().add(AddChild { child, parent }); | ||
self | ||
} | ||
|
||
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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does that really work? What if there's already the opposite There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might add more test. But logically, if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to see a simple test :) |
||
self | ||
} | ||
} | ||
|
||
/// Struct for adding children to an entity directly through the [`World`] for use in exclusive systems | ||
|
@@ -345,7 +359,9 @@ impl<'w> WorldChildBuilder<'w> { | |
self.world.entity_mut(entity) | ||
} | ||
|
||
/// 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same remark as previously, comment is fairly confusing to me. |
||
/// into the children defined by the [`WorldChildBuilder`] | ||
/// which adds the [`Parent`] component to it. | ||
pub fn spawn(&mut self) -> EntityMut<'_> { | ||
let parent_entity = self.parent_entity(); | ||
let entity = self.world.spawn().insert(Parent(parent_entity)).id(); | ||
|
@@ -383,31 +399,22 @@ pub trait BuildWorldChildren { | |
|
||
impl<'w> BuildWorldChildren for EntityMut<'w> { | ||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self { | ||
{ | ||
let entity = self.id(); | ||
let entity = self.id(); | ||
self.with_world_mut(|world| { | ||
let mut builder = WorldChildBuilder { | ||
current_entity: None, | ||
parent_entities: vec![entity], | ||
// SAFETY: self.update_location() is called below. It is impossible to make EntityMut | ||
// function calls on `self` within the scope defined here | ||
world: unsafe { self.world_mut() }, | ||
world, | ||
}; | ||
|
||
spawn_children(&mut builder); | ||
} | ||
self.update_location(); | ||
}); | ||
self | ||
} | ||
|
||
fn push_children(&mut self, children: &[Entity]) -> &mut Self { | ||
let parent = self.id(); | ||
{ | ||
// SAFETY: parent entity is not modified and its location is updated manually | ||
let world = unsafe { self.world_mut() }; | ||
update_old_parents(world, parent, children); | ||
// 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really like the elimination of unsafe here. |
||
if let Some(mut children_component) = self.get_mut::<Children>() { | ||
children_component | ||
.0 | ||
|
@@ -421,13 +428,7 @@ impl<'w> BuildWorldChildren for EntityMut<'w> { | |
|
||
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self { | ||
let parent = self.id(); | ||
{ | ||
// SAFETY: parent entity is not modified and its location is updated manually | ||
let world = unsafe { self.world_mut() }; | ||
update_old_parents(world, parent, children); | ||
// 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)); | ||
|
||
if let Some(mut children_component) = self.get_mut::<Children>() { | ||
children_component | ||
|
@@ -442,9 +443,7 @@ impl<'w> BuildWorldChildren for EntityMut<'w> { | |
|
||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self { | ||
let parent = self.id(); | ||
// SAFETY: This doesn't change the parent's location | ||
let world = unsafe { self.world_mut() }; | ||
remove_children(parent, children, world); | ||
self.with_world_mut(|world| remove_children(parent, children, world)); | ||
self | ||
} | ||
} | ||
|
@@ -542,6 +541,8 @@ mod tests { | |
parent.spawn().insert(C(4)).id(), | ||
] | ||
}); | ||
let mut children = children.to_vec(); | ||
children.push(commands.spawn().insert(C(5)).set_parent(parent).id()); | ||
|
||
queue.apply(&mut world); | ||
assert_eq!( | ||
|
@@ -583,6 +584,7 @@ mod tests { | |
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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably a mismerge. Can you please delete instead of adding a comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should remove the duplicate assertions. |
||
assert_eq!(*world.get::<Parent>(child1).unwrap(), Parent(parent)); | ||
assert_eq!(*world.get::<Parent>(child2).unwrap(), Parent(parent)); | ||
|
||
|
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'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, norupdate_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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 whatupdate_location
is, they should be able to click on the link and read theupdate_location
documentation.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.