Parent -> ChildOf (#17427)
Fixes #17412 ## Objective `Parent` uses the "has a X" naming convention. There is increasing sentiment that we should use the "is a X" naming convention for relationships (following #17398). This leaves `Children` as-is because there is prevailing sentiment that `Children` is clearer than `ParentOf` in many cases (especially when treating it like a collection). This renames `Parent` to `ChildOf`. This is just the implementation PR. To discuss the path forward, do so in #17412. ## Migration Guide - The `Parent` component has been renamed to `ChildOf`.
This commit is contained in:
parent
000c362de0
commit
ba5e71f53d
@ -3,7 +3,7 @@ use core::hint::black_box;
|
||||
use benches::bench;
|
||||
use bevy_ecs::bundle::Bundle;
|
||||
use bevy_ecs::component::ComponentCloneHandler;
|
||||
use bevy_ecs::hierarchy::Parent;
|
||||
use bevy_ecs::hierarchy::ChildOf;
|
||||
use bevy_ecs::reflect::AppTypeRegistry;
|
||||
use bevy_ecs::{component::Component, world::World};
|
||||
use bevy_math::Mat4;
|
||||
@ -142,7 +142,7 @@ fn bench_clone_hierarchy<B: Bundle + Default + GetTypeRegistration>(
|
||||
|
||||
for parent_id in current_hierarchy_level {
|
||||
for _ in 0..children {
|
||||
let child_id = world.spawn((B::default(), Parent(parent_id))).id();
|
||||
let child_id = world.spawn((B::default(), ChildOf(parent_id))).id();
|
||||
hierarchy_level.push(child_id);
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ pub fn event_propagation(criterion: &mut Criterion) {
|
||||
struct TestEvent<const N: usize> {}
|
||||
|
||||
impl<const N: usize> Event for TestEvent<N> {
|
||||
type Traversal = &'static Parent;
|
||||
type Traversal = &'static ChildOf;
|
||||
const AUTO_PROPAGATE: bool = true;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ impl Default for App {
|
||||
{
|
||||
app.init_resource::<AppTypeRegistry>();
|
||||
app.register_type::<Name>();
|
||||
app.register_type::<Parent>();
|
||||
app.register_type::<ChildOf>();
|
||||
app.register_type::<Children>();
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
bundle::Bundle,
|
||||
component::{Component, ComponentCloneHandler, ComponentId, ComponentInfo, Components},
|
||||
entity::Entity,
|
||||
hierarchy::{Children, Parent},
|
||||
hierarchy::{ChildOf, Children},
|
||||
query::DebugCheckedUnwrap,
|
||||
world::{DeferredWorld, World},
|
||||
};
|
||||
@ -631,11 +631,11 @@ impl<'w> EntityCloneBuilder<'w> {
|
||||
/// Sets the option to add cloned entity as a child to the parent entity.
|
||||
pub fn as_child(&mut self, as_child: bool) -> &mut Self {
|
||||
if as_child {
|
||||
self.override_component_clone_handler::<Parent>(ComponentCloneHandler::custom_handler(
|
||||
self.override_component_clone_handler::<ChildOf>(ComponentCloneHandler::custom_handler(
|
||||
component_clone_parent,
|
||||
))
|
||||
} else {
|
||||
self.remove_component_clone_handler_override::<Parent>()
|
||||
self.remove_component_clone_handler_override::<ChildOf>()
|
||||
}
|
||||
}
|
||||
|
||||
@ -694,18 +694,21 @@ fn component_clone_children(world: &mut DeferredWorld, ctx: &mut ComponentCloneC
|
||||
.with_source_and_target(*child, child_clone);
|
||||
world.commands().queue(move |world: &mut World| {
|
||||
clone_entity.clone_entity(world);
|
||||
world.entity_mut(child_clone).insert(Parent(parent));
|
||||
world.entity_mut(child_clone).insert(ChildOf(parent));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Clone handler for the [`Parent`] component. Allows to add clone as a child to the parent entity.
|
||||
/// Clone handler for the [`ChildOf`] component. Allows to add clone as a child to the parent entity.
|
||||
fn component_clone_parent(world: &mut DeferredWorld, ctx: &mut ComponentCloneCtx) {
|
||||
let parent = ctx
|
||||
.read_source_component::<Parent>()
|
||||
.read_source_component::<ChildOf>()
|
||||
.map(|p| p.0)
|
||||
.expect("Source entity must have Parent component");
|
||||
world.commands().entity(ctx.target()).insert(Parent(parent));
|
||||
.expect("Source entity must have a ChildOf component");
|
||||
world
|
||||
.commands()
|
||||
.entity(ctx.target())
|
||||
.insert(ChildOf(parent));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! The canonical "parent-child" [`Relationship`] for entities, driven by
|
||||
//! the [`Parent`] [`Relationship`] and the [`Children`] [`RelationshipTarget`].
|
||||
//! the [`ChildOf`] [`Relationship`] and the [`Children`] [`RelationshipTarget`].
|
||||
//!
|
||||
//! See [`Parent`] for a full description of the relationship and how to use it.
|
||||
//! See [`ChildOf`] for a full description of the relationship and how to use it.
|
||||
//!
|
||||
//! [`Relationship`]: crate::relationship::Relationship
|
||||
//! [`RelationshipTarget`]: crate::relationship::RelationshipTarget
|
||||
@ -38,32 +38,32 @@ use log::warn;
|
||||
/// 3. Ensuring a hierarchy is despawned when an entity is despawned.
|
||||
/// 4.
|
||||
///
|
||||
/// [`Parent`] contains a single "target" [`Entity`]. When [`Parent`] is inserted on a "source" entity,
|
||||
/// [`ChildOf`] contains a single "target" [`Entity`]. When [`ChildOf`] is inserted on a "source" entity,
|
||||
/// the "target" entity will automatically (and immediately, via a component hook) have a [`Children`]
|
||||
/// component inserted, and the "source" entity will be added to that [`Children`] instance.
|
||||
///
|
||||
/// If the [`Parent`] component is replaced with a different "target" entity, the old target's [`Children`]
|
||||
/// If the [`ChildOf`] component is replaced with a different "target" entity, the old target's [`Children`]
|
||||
/// will be automatically (and immediately, via a component hook) be updated to reflect that change.
|
||||
///
|
||||
/// Likewise, when the [`Parent`] component is removed, the "source" entity will be removed from the old
|
||||
/// Likewise, when the [`ChildOf`] component is removed, the "source" entity will be removed from the old
|
||||
/// target's [`Children`]. If this results in [`Children`] being empty, [`Children`] will be automatically removed.
|
||||
///
|
||||
/// When a parent is despawned, all children (and their descendants) will _also_ be despawned.
|
||||
///
|
||||
/// You can create parent-child relationships in a variety of ways. The most direct way is to insert a [`Parent`] component:
|
||||
/// You can create parent-child relationships in a variety of ways. The most direct way is to insert a [`ChildOf`] component:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # let mut world = World::new();
|
||||
/// let root = world.spawn_empty().id();
|
||||
/// let child1 = world.spawn(Parent(root)).id();
|
||||
/// let child2 = world.spawn(Parent(root)).id();
|
||||
/// let grandchild = world.spawn(Parent(child1)).id();
|
||||
/// let child1 = world.spawn(ChildOf(root)).id();
|
||||
/// let child2 = world.spawn(ChildOf(root)).id();
|
||||
/// let grandchild = world.spawn(ChildOf(child1)).id();
|
||||
///
|
||||
/// assert_eq!(&**world.entity(root).get::<Children>().unwrap(), &[child1, child2]);
|
||||
/// assert_eq!(&**world.entity(child1).get::<Children>().unwrap(), &[grandchild]);
|
||||
///
|
||||
/// world.entity_mut(child2).remove::<Parent>();
|
||||
/// world.entity_mut(child2).remove::<ChildOf>();
|
||||
/// assert_eq!(&**world.entity(root).get::<Children>().unwrap(), &[child1]);
|
||||
///
|
||||
/// world.entity_mut(root).despawn();
|
||||
@ -105,16 +105,16 @@ use log::warn;
|
||||
)
|
||||
)]
|
||||
#[relationship(relationship_target = Children)]
|
||||
pub struct Parent(pub Entity);
|
||||
pub struct ChildOf(pub Entity);
|
||||
|
||||
impl Parent {
|
||||
impl ChildOf {
|
||||
/// Returns the "target" entity.
|
||||
pub fn get(&self) -> Entity {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Parent {
|
||||
impl Deref for ChildOf {
|
||||
type Target = Entity;
|
||||
|
||||
#[inline]
|
||||
@ -123,24 +123,24 @@ impl Deref for Parent {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: We need to impl either FromWorld or Default so Parent can be registered as Reflect.
|
||||
// TODO: We need to impl either FromWorld or Default so ChildOf can be registered as Reflect.
|
||||
// This is because Reflect deserialize by creating an instance and apply a patch on top.
|
||||
// However Parent should only ever be set with a real user-defined entity. Its worth looking into
|
||||
// However ChildOf should only ever be set with a real user-defined entity. Its worth looking into
|
||||
// better ways to handle cases like this.
|
||||
impl FromWorld for Parent {
|
||||
impl FromWorld for ChildOf {
|
||||
#[inline(always)]
|
||||
fn from_world(_world: &mut World) -> Self {
|
||||
Parent(Entity::PLACEHOLDER)
|
||||
ChildOf(Entity::PLACEHOLDER)
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`RelationshipTarget`](crate::relationship::RelationshipTarget) collection component that is populated
|
||||
/// with entities that "target" this entity with the [`Parent`] [`Relationship`](crate::relationship::Relationship) component.
|
||||
/// with entities that "target" this entity with the [`ChildOf`] [`Relationship`](crate::relationship::Relationship) component.
|
||||
///
|
||||
/// Together, these components form the "canonical parent-child hierarchy". See the [`Parent`] component for all full
|
||||
/// Together, these components form the "canonical parent-child hierarchy". See the [`ChildOf`] component for all full
|
||||
/// description of this relationship and instructions on how to use it.
|
||||
#[derive(Component, Default, VisitEntitiesMut, Debug, PartialEq, Eq)]
|
||||
#[relationship_target(relationship = Parent, despawn_descendants)]
|
||||
#[relationship_target(relationship = ChildOf, despawn_descendants)]
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
|
||||
#[cfg_attr(
|
||||
feature = "bevy_reflect",
|
||||
@ -167,14 +167,14 @@ impl Deref for Children {
|
||||
}
|
||||
}
|
||||
|
||||
/// A type alias over [`RelatedSpawner`] used to spawn child entities containing a [`Parent`] relationship.
|
||||
pub type ChildSpawner<'w> = RelatedSpawner<'w, Parent>;
|
||||
/// A type alias over [`RelatedSpawner`] used to spawn child entities containing a [`ChildOf`] relationship.
|
||||
pub type ChildSpawner<'w> = RelatedSpawner<'w, ChildOf>;
|
||||
|
||||
/// A type alias over [`RelatedSpawnerCommands`] used to spawn child entities containing a [`Parent`] relationship.
|
||||
pub type ChildSpawnerCommands<'w> = RelatedSpawnerCommands<'w, Parent>;
|
||||
/// A type alias over [`RelatedSpawnerCommands`] used to spawn child entities containing a [`ChildOf`] relationship.
|
||||
pub type ChildSpawnerCommands<'w> = RelatedSpawnerCommands<'w, ChildOf>;
|
||||
|
||||
impl<'w> EntityWorldMut<'w> {
|
||||
/// Spawns children of this entity (with a [`Parent`] relationship) by taking a function that operates on a [`ChildSpawner`].
|
||||
/// Spawns children of this entity (with a [`ChildOf`] relationship) by taking a function that operates on a [`ChildSpawner`].
|
||||
pub fn with_children(&mut self, func: impl FnOnce(&mut ChildSpawner)) -> &mut Self {
|
||||
self.with_related(func);
|
||||
self
|
||||
@ -182,12 +182,12 @@ impl<'w> EntityWorldMut<'w> {
|
||||
|
||||
/// Adds the given children to this entity
|
||||
pub fn add_children(&mut self, children: &[Entity]) -> &mut Self {
|
||||
self.add_related::<Parent>(children)
|
||||
self.add_related::<ChildOf>(children)
|
||||
}
|
||||
|
||||
/// Adds the given child to this entity
|
||||
pub fn add_child(&mut self, child: Entity) -> &mut Self {
|
||||
self.add_related::<Parent>(&[child])
|
||||
self.add_related::<ChildOf>(&[child])
|
||||
}
|
||||
|
||||
/// Spawns the passed bundle and adds it to this entity as a child.
|
||||
@ -198,31 +198,31 @@ impl<'w> EntityWorldMut<'w> {
|
||||
pub fn with_child(&mut self, bundle: impl Bundle) -> &mut Self {
|
||||
let id = self.id();
|
||||
self.world_scope(|world| {
|
||||
world.spawn((bundle, Parent(id)));
|
||||
world.spawn((bundle, ChildOf(id)));
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Removes the [`Parent`] component, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_mut.remove::<Parent>()")]
|
||||
/// Removes the [`ChildOf`] component, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_mut.remove::<ChildOf>()")]
|
||||
pub fn remove_parent(&mut self) -> &mut Self {
|
||||
self.remove::<Parent>();
|
||||
self.remove::<ChildOf>();
|
||||
self
|
||||
}
|
||||
|
||||
/// Inserts the [`Parent`] component with the given `parent` entity, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_mut.insert(Parent(entity))")]
|
||||
/// Inserts the [`ChildOf`] component with the given `parent` entity, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_mut.insert(ChildOf(entity))")]
|
||||
pub fn set_parent(&mut self, parent: Entity) -> &mut Self {
|
||||
self.insert(Parent(parent));
|
||||
self.insert(ChildOf(parent));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EntityCommands<'a> {
|
||||
/// Spawns children of this entity (with a [`Parent`] relationship) by taking a function that operates on a [`ChildSpawner`].
|
||||
/// Spawns children of this entity (with a [`ChildOf`] relationship) by taking a function that operates on a [`ChildSpawner`].
|
||||
pub fn with_children(
|
||||
&mut self,
|
||||
func: impl FnOnce(&mut RelatedSpawnerCommands<Parent>),
|
||||
func: impl FnOnce(&mut RelatedSpawnerCommands<ChildOf>),
|
||||
) -> &mut Self {
|
||||
self.with_related(func);
|
||||
self
|
||||
@ -230,12 +230,12 @@ impl<'a> EntityCommands<'a> {
|
||||
|
||||
/// Adds the given children to this entity
|
||||
pub fn add_children(&mut self, children: &[Entity]) -> &mut Self {
|
||||
self.add_related::<Parent>(children)
|
||||
self.add_related::<ChildOf>(children)
|
||||
}
|
||||
|
||||
/// Adds the given child to this entity
|
||||
pub fn add_child(&mut self, child: Entity) -> &mut Self {
|
||||
self.add_related::<Parent>(&[child])
|
||||
self.add_related::<ChildOf>(&[child])
|
||||
}
|
||||
|
||||
/// Spawns the passed bundle and adds it to this entity as a child.
|
||||
@ -245,21 +245,21 @@ impl<'a> EntityCommands<'a> {
|
||||
/// [`with_children`]: EntityCommands::with_children
|
||||
pub fn with_child(&mut self, bundle: impl Bundle) -> &mut Self {
|
||||
let id = self.id();
|
||||
self.commands.spawn((bundle, Parent(id)));
|
||||
self.commands.spawn((bundle, ChildOf(id)));
|
||||
self
|
||||
}
|
||||
|
||||
/// Removes the [`Parent`] component, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_commands.remove::<Parent>()")]
|
||||
/// Removes the [`ChildOf`] component, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_commands.remove::<ChildOf>()")]
|
||||
pub fn remove_parent(&mut self) -> &mut Self {
|
||||
self.remove::<Parent>();
|
||||
self.remove::<ChildOf>();
|
||||
self
|
||||
}
|
||||
|
||||
/// Inserts the [`Parent`] component with the given `parent` entity, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_commands.insert(Parent(entity))")]
|
||||
/// Inserts the [`ChildOf`] component with the given `parent` entity, if it exists.
|
||||
#[deprecated(since = "0.16.0", note = "Use entity_commands.insert(ChildOf(entity))")]
|
||||
pub fn set_parent(&mut self, parent: Entity) -> &mut Self {
|
||||
self.insert(Parent(parent));
|
||||
self.insert(ChildOf(parent));
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -272,7 +272,7 @@ pub fn validate_parent_has_component<C: Component>(
|
||||
_: ComponentId,
|
||||
) {
|
||||
let entity_ref = world.entity(entity);
|
||||
let Some(child_of) = entity_ref.get::<Parent>() else {
|
||||
let Some(child_of) = entity_ref.get::<ChildOf>() else {
|
||||
return;
|
||||
};
|
||||
if !world
|
||||
@ -297,7 +297,7 @@ pub fn validate_parent_has_component<C: Component>(
|
||||
mod tests {
|
||||
use crate::{
|
||||
entity::Entity,
|
||||
hierarchy::{Children, Parent},
|
||||
hierarchy::{ChildOf, Children},
|
||||
relationship::RelationshipTarget,
|
||||
world::World,
|
||||
};
|
||||
@ -338,9 +338,9 @@ mod tests {
|
||||
fn hierarchy() {
|
||||
let mut world = World::new();
|
||||
let root = world.spawn_empty().id();
|
||||
let child1 = world.spawn(Parent(root)).id();
|
||||
let grandchild = world.spawn(Parent(child1)).id();
|
||||
let child2 = world.spawn(Parent(root)).id();
|
||||
let child1 = world.spawn(ChildOf(root)).id();
|
||||
let grandchild = world.spawn(ChildOf(child1)).id();
|
||||
let child2 = world.spawn(ChildOf(root)).id();
|
||||
|
||||
// Spawn
|
||||
let hierarchy = get_hierarchy(&world, root);
|
||||
@ -356,12 +356,12 @@ mod tests {
|
||||
);
|
||||
|
||||
// Removal
|
||||
world.entity_mut(child1).remove::<Parent>();
|
||||
world.entity_mut(child1).remove::<ChildOf>();
|
||||
let hierarchy = get_hierarchy(&world, root);
|
||||
assert_eq!(hierarchy, Node::new_with(root, vec![Node::new(child2)]));
|
||||
|
||||
// Insert
|
||||
world.entity_mut(child1).insert(Parent(root));
|
||||
world.entity_mut(child1).insert(ChildOf(root));
|
||||
let hierarchy = get_hierarchy(&world, root);
|
||||
assert_eq!(
|
||||
hierarchy,
|
||||
@ -420,10 +420,10 @@ mod tests {
|
||||
fn self_parenting_invalid() {
|
||||
let mut world = World::new();
|
||||
let id = world.spawn_empty().id();
|
||||
world.entity_mut(id).insert(Parent(id));
|
||||
world.entity_mut(id).insert(ChildOf(id));
|
||||
assert!(
|
||||
world.entity(id).get::<Parent>().is_none(),
|
||||
"invalid Parent relationships should self-remove"
|
||||
world.entity(id).get::<ChildOf>().is_none(),
|
||||
"invalid ChildOf relationships should self-remove"
|
||||
);
|
||||
}
|
||||
|
||||
@ -432,10 +432,10 @@ mod tests {
|
||||
let mut world = World::new();
|
||||
let parent = world.spawn_empty().id();
|
||||
world.entity_mut(parent).despawn();
|
||||
let id = world.spawn(Parent(parent)).id();
|
||||
let id = world.spawn(ChildOf(parent)).id();
|
||||
assert!(
|
||||
world.entity(id).get::<Parent>().is_none(),
|
||||
"invalid Parent relationships should self-remove"
|
||||
world.entity(id).get::<ChildOf>().is_none(),
|
||||
"invalid ChildOf relationships should self-remove"
|
||||
);
|
||||
}
|
||||
|
||||
@ -443,12 +443,12 @@ mod tests {
|
||||
fn reinsert_same_parent() {
|
||||
let mut world = World::new();
|
||||
let parent = world.spawn_empty().id();
|
||||
let id = world.spawn(Parent(parent)).id();
|
||||
world.entity_mut(id).insert(Parent(parent));
|
||||
let id = world.spawn(ChildOf(parent)).id();
|
||||
world.entity_mut(id).insert(ChildOf(parent));
|
||||
assert_eq!(
|
||||
Some(&Parent(parent)),
|
||||
world.entity(id).get::<Parent>(),
|
||||
"Parent should still be there"
|
||||
Some(&ChildOf(parent)),
|
||||
world.entity(id).get::<ChildOf>(),
|
||||
"ChildOf should still be there"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ pub mod prelude {
|
||||
component::{require, Component},
|
||||
entity::{Entity, EntityBorrow, EntityMapper},
|
||||
event::{Event, EventMutator, EventReader, EventWriter, Events},
|
||||
hierarchy::{ChildSpawner, ChildSpawnerCommands, Children, Parent},
|
||||
hierarchy::{ChildOf, ChildSpawner, ChildSpawnerCommands, Children},
|
||||
name::{Name, NameOrEntity},
|
||||
observer::{CloneEntityWithObserversExt, Observer, Trigger},
|
||||
query::{Added, AnyOf, Changed, Has, Or, QueryBuilder, QueryState, With, Without},
|
||||
|
@ -800,9 +800,9 @@ mod tests {
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Parent(Entity);
|
||||
struct ChildOf(Entity);
|
||||
|
||||
impl<D> Traversal<D> for &'_ Parent {
|
||||
impl<D> Traversal<D> for &'_ ChildOf {
|
||||
fn traverse(item: Self::Item<'_>, _: &D) -> Option<Entity> {
|
||||
Some(item.0)
|
||||
}
|
||||
@ -812,7 +812,7 @@ mod tests {
|
||||
struct EventPropagating;
|
||||
|
||||
impl Event for EventPropagating {
|
||||
type Traversal = &'static Parent;
|
||||
type Traversal = &'static ChildOf;
|
||||
|
||||
const AUTO_PROPAGATE: bool = true;
|
||||
}
|
||||
@ -1198,7 +1198,7 @@ mod tests {
|
||||
.id();
|
||||
|
||||
let child = world
|
||||
.spawn(Parent(parent))
|
||||
.spawn(ChildOf(parent))
|
||||
.observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child");
|
||||
})
|
||||
@ -1225,7 +1225,7 @@ mod tests {
|
||||
.id();
|
||||
|
||||
let child = world
|
||||
.spawn(Parent(parent))
|
||||
.spawn(ChildOf(parent))
|
||||
.observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child");
|
||||
})
|
||||
@ -1255,7 +1255,7 @@ mod tests {
|
||||
.id();
|
||||
|
||||
let child = world
|
||||
.spawn(Parent(parent))
|
||||
.spawn(ChildOf(parent))
|
||||
.observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child");
|
||||
})
|
||||
@ -1285,7 +1285,7 @@ mod tests {
|
||||
.id();
|
||||
|
||||
let child = world
|
||||
.spawn(Parent(parent))
|
||||
.spawn(ChildOf(parent))
|
||||
.observe(
|
||||
|mut trigger: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child");
|
||||
@ -1315,14 +1315,14 @@ mod tests {
|
||||
.id();
|
||||
|
||||
let child_a = world
|
||||
.spawn(Parent(parent))
|
||||
.spawn(ChildOf(parent))
|
||||
.observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child_a");
|
||||
})
|
||||
.id();
|
||||
|
||||
let child_b = world
|
||||
.spawn(Parent(parent))
|
||||
.spawn(ChildOf(parent))
|
||||
.observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child_b");
|
||||
})
|
||||
@ -1372,7 +1372,7 @@ mod tests {
|
||||
.id();
|
||||
|
||||
let child_a = world
|
||||
.spawn(Parent(parent_a))
|
||||
.spawn(ChildOf(parent_a))
|
||||
.observe(
|
||||
|mut trigger: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child_a");
|
||||
@ -1389,7 +1389,7 @@ mod tests {
|
||||
.id();
|
||||
|
||||
let child_b = world
|
||||
.spawn(Parent(parent_b))
|
||||
.spawn(ChildOf(parent_b))
|
||||
.observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
|
||||
res.observed("child_b");
|
||||
})
|
||||
@ -1416,8 +1416,8 @@ mod tests {
|
||||
});
|
||||
|
||||
let grandparent = world.spawn_empty().id();
|
||||
let parent = world.spawn(Parent(grandparent)).id();
|
||||
let child = world.spawn(Parent(parent)).id();
|
||||
let parent = world.spawn(ChildOf(grandparent)).id();
|
||||
let child = world.spawn(ChildOf(parent)).id();
|
||||
|
||||
// TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
|
||||
// and therefore does not automatically flush.
|
||||
@ -1441,8 +1441,8 @@ mod tests {
|
||||
);
|
||||
|
||||
let grandparent = world.spawn(A).id();
|
||||
let parent = world.spawn(Parent(grandparent)).id();
|
||||
let child = world.spawn((A, Parent(parent))).id();
|
||||
let parent = world.spawn(ChildOf(grandparent)).id();
|
||||
let child = world.spawn((A, ChildOf(parent))).id();
|
||||
|
||||
// TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
|
||||
// and therefore does not automatically flush.
|
||||
|
@ -28,7 +28,7 @@ use log::warn;
|
||||
/// component is inserted on an [`Entity`], the corresponding [`RelationshipTarget`] component is immediately inserted on the target component if it does
|
||||
/// not already exist, and the "source" entity is automatically added to the [`RelationshipTarget`] collection (this is done via "component hooks").
|
||||
///
|
||||
/// A common example of a [`Relationship`] is the parent / child relationship. Bevy ECS includes a canonical form of this via the [`Parent`](crate::hierarchy::Parent)
|
||||
/// A common example of a [`Relationship`] is the parent / child relationship. Bevy ECS includes a canonical form of this via the [`ChildOf`](crate::hierarchy::ChildOf)
|
||||
/// [`Relationship`] and the [`Children`](crate::hierarchy::Children) [`RelationshipTarget`].
|
||||
///
|
||||
/// [`Relationship`] and [`RelationshipTarget`] should always be derived via the [`Component`] trait to ensure the hooks are set up properly.
|
||||
@ -38,10 +38,10 @@ use log::warn;
|
||||
/// # use bevy_ecs::entity::Entity;
|
||||
/// #[derive(Component)]
|
||||
/// #[relationship(relationship_target = Children)]
|
||||
/// pub struct Parent(pub Entity);
|
||||
/// pub struct ChildOf(pub Entity);
|
||||
///
|
||||
/// #[derive(Component)]
|
||||
/// #[relationship_target(relationship = Parent)]
|
||||
/// #[relationship_target(relationship = ChildOf)]
|
||||
/// pub struct Children(Vec<Entity>);
|
||||
/// ```
|
||||
///
|
||||
@ -53,10 +53,10 @@ use log::warn;
|
||||
/// # use bevy_ecs::entity::Entity;
|
||||
/// #[derive(Component)]
|
||||
/// #[relationship(relationship_target = Children)]
|
||||
/// pub struct Parent(pub Entity);
|
||||
/// pub struct ChildOf(pub Entity);
|
||||
///
|
||||
/// #[derive(Component)]
|
||||
/// #[relationship_target(relationship = Parent, despawn_descendants)]
|
||||
/// #[relationship_target(relationship = ChildOf, despawn_descendants)]
|
||||
/// pub struct Children(Vec<Entity>);
|
||||
/// ```
|
||||
pub trait Relationship: Component + Sized {
|
||||
|
@ -144,7 +144,7 @@ impl<E: Event + Clone> Event for FocusedInput<E> {
|
||||
#[derive(QueryData)]
|
||||
/// These are for accessing components defined on the targeted entity
|
||||
pub struct WindowTraversal {
|
||||
parent: Option<&'static Parent>,
|
||||
parent: Option<&'static ChildOf>,
|
||||
window: Option<&'static Window>,
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ pub trait IsFocused {
|
||||
/// When working with the entire [`World`], consider using the [`IsFocused`] instead.
|
||||
#[derive(SystemParam)]
|
||||
pub struct IsFocusedHelper<'w, 's> {
|
||||
parent_query: Query<'w, 's, &'static Parent>,
|
||||
parent_query: Query<'w, 's, &'static ChildOf>,
|
||||
input_focus: Option<Res<'w, InputFocus>>,
|
||||
input_focus_visible: Option<Res<'w, InputFocusVisible>>,
|
||||
}
|
||||
@ -327,7 +327,7 @@ impl IsFocused for World {
|
||||
if e == entity {
|
||||
return true;
|
||||
}
|
||||
if let Some(parent) = self.entity(e).get::<Parent>().map(Parent::get) {
|
||||
if let Some(parent) = self.entity(e).get::<ChildOf>().map(ChildOf::get) {
|
||||
e = parent;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -29,7 +29,7 @@ use bevy_ecs::prelude::ReflectComponent;
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
hierarchy::{Children, Parent},
|
||||
hierarchy::{ChildOf, Children},
|
||||
observer::Trigger,
|
||||
query::{With, Without},
|
||||
system::{Commands, Query, Res, ResMut, SystemParam},
|
||||
@ -157,7 +157,7 @@ pub struct TabNavigation<'w, 's> {
|
||||
Without<TabGroup>,
|
||||
>,
|
||||
// Query for parents.
|
||||
parent_query: Query<'w, 's, &'static Parent>,
|
||||
parent_query: Query<'w, 's, &'static ChildOf>,
|
||||
}
|
||||
|
||||
impl TabNavigation<'_, '_> {
|
||||
@ -371,8 +371,8 @@ mod tests {
|
||||
let world = app.world_mut();
|
||||
|
||||
let tab_group_entity = world.spawn(TabGroup::new(0)).id();
|
||||
let tab_entity_1 = world.spawn((TabIndex(0), Parent(tab_group_entity))).id();
|
||||
let tab_entity_2 = world.spawn((TabIndex(1), Parent(tab_group_entity))).id();
|
||||
let tab_entity_1 = world.spawn((TabIndex(0), ChildOf(tab_group_entity))).id();
|
||||
let tab_entity_2 = world.spawn((TabIndex(1), ChildOf(tab_group_entity))).id();
|
||||
|
||||
let mut system_state: SystemState<TabNavigation> = SystemState::new(world);
|
||||
let tab_navigation = system_state.get(world);
|
||||
|
@ -78,7 +78,7 @@ pub struct Pointer<E: Debug + Clone + Reflect> {
|
||||
/// propagates to the pointer's window and stops there.
|
||||
#[derive(QueryData)]
|
||||
pub struct PointerTraversal {
|
||||
parent: Option<&'static Parent>,
|
||||
parent: Option<&'static ChildOf>,
|
||||
window: Option<&'static Window>,
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ use bevy_ecs::{
|
||||
component::ComponentId,
|
||||
entity::Entity,
|
||||
event::EventCursor,
|
||||
hierarchy::Parent,
|
||||
hierarchy::ChildOf,
|
||||
query::QueryBuilder,
|
||||
reflect::{AppTypeRegistry, ReflectComponent, ReflectResource},
|
||||
removal_detection::RemovedComponentEntity,
|
||||
@ -841,7 +841,7 @@ pub fn process_remote_reparent_request(
|
||||
// If `None`, remove the entities' parents.
|
||||
else {
|
||||
for entity in entities {
|
||||
get_entity_mut(world, entity)?.remove::<Parent>();
|
||||
get_entity_mut(world, entity)?.remove::<ChildOf>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ use crate::{
|
||||
#[reflect(Component, Default, Debug, PartialEq)]
|
||||
#[require(InheritedVisibility, ViewVisibility)]
|
||||
pub enum Visibility {
|
||||
/// An entity with `Visibility::Inherited` will inherit the Visibility of its [`Parent`].
|
||||
/// An entity with `Visibility::Inherited` will inherit the Visibility of its [`ChildOf`] target.
|
||||
///
|
||||
/// A root-level entity that is set to `Inherited` will be visible.
|
||||
#[default]
|
||||
@ -47,7 +47,7 @@ pub enum Visibility {
|
||||
/// An entity with `Visibility::Visible` will be unconditionally visible.
|
||||
///
|
||||
/// Note that an entity with `Visibility::Visible` will be visible regardless of whether the
|
||||
/// [`Parent`] entity is hidden.
|
||||
/// [`ChildOf`] target entity is hidden.
|
||||
Visible,
|
||||
}
|
||||
|
||||
@ -316,7 +316,7 @@ pub enum VisibilitySystems {
|
||||
/// Label for [`update_frusta`] in [`CameraProjectionPlugin`](crate::camera::CameraProjectionPlugin).
|
||||
UpdateFrusta,
|
||||
/// Label for the system propagating the [`InheritedVisibility`] in a
|
||||
/// [`Parent`] / [`Children`] hierarchy.
|
||||
/// [`ChildOf`] / [`Children`] hierarchy.
|
||||
VisibilityPropagate,
|
||||
/// Label for the [`check_visibility`] system updating [`ViewVisibility`]
|
||||
/// of each entity and the [`VisibleEntities`] of each view.\
|
||||
@ -387,10 +387,10 @@ pub fn update_frusta(
|
||||
|
||||
fn visibility_propagate_system(
|
||||
changed: Query<
|
||||
(Entity, &Visibility, Option<&Parent>, Option<&Children>),
|
||||
(Entity, &Visibility, Option<&ChildOf>, Option<&Children>),
|
||||
(
|
||||
With<InheritedVisibility>,
|
||||
Or<(Changed<Visibility>, Changed<Parent>)>,
|
||||
Or<(Changed<Visibility>, Changed<ChildOf>)>,
|
||||
),
|
||||
>,
|
||||
mut visibility_query: Query<(&Visibility, &mut InheritedVisibility)>,
|
||||
@ -761,7 +761,7 @@ mod test {
|
||||
.entity_mut(parent2)
|
||||
.insert(Visibility::Visible);
|
||||
// Simulate a change in the parent component
|
||||
app.world_mut().entity_mut(child2).insert(Parent(parent2)); // example of changing parent
|
||||
app.world_mut().entity_mut(child2).insert(ChildOf(parent2)); // example of changing parent
|
||||
|
||||
// Run the system again to propagate changes
|
||||
app.update();
|
||||
|
@ -203,7 +203,7 @@ mod tests {
|
||||
hash_map::EntityHashMap, Entity, EntityMapper, MapEntities, VisitEntities,
|
||||
VisitEntitiesMut,
|
||||
},
|
||||
hierarchy::Parent,
|
||||
hierarchy::ChildOf,
|
||||
reflect::{AppTypeRegistry, ReflectComponent, ReflectMapEntities, ReflectResource},
|
||||
system::Resource,
|
||||
world::World,
|
||||
@ -269,7 +269,7 @@ mod tests {
|
||||
world
|
||||
.resource_mut::<AppTypeRegistry>()
|
||||
.write()
|
||||
.register::<Parent>();
|
||||
.register::<ChildOf>();
|
||||
let original_parent_entity = world.spawn_empty().id();
|
||||
let original_child_entity = world.spawn_empty().id();
|
||||
world
|
||||
@ -305,7 +305,7 @@ mod tests {
|
||||
world
|
||||
.get_entity(original_child_entity)
|
||||
.unwrap()
|
||||
.get::<Parent>()
|
||||
.get::<ChildOf>()
|
||||
.unwrap()
|
||||
.get(),
|
||||
"something about reloading the scene is touching entities with the same scene Ids"
|
||||
@ -315,7 +315,7 @@ mod tests {
|
||||
world
|
||||
.get_entity(from_scene_parent_entity)
|
||||
.unwrap()
|
||||
.get::<Parent>()
|
||||
.get::<ChildOf>()
|
||||
.unwrap()
|
||||
.get(),
|
||||
"something about reloading the scene is touching components not defined in the scene but on entities defined in the scene"
|
||||
@ -325,7 +325,7 @@ mod tests {
|
||||
world
|
||||
.get_entity(from_scene_child_entity)
|
||||
.unwrap()
|
||||
.get::<Parent>()
|
||||
.get::<ChildOf>()
|
||||
.expect("something is wrong with this test, and the scene components don't have a parent/child relationship")
|
||||
.get(),
|
||||
"something is wrong with this test or the code reloading scenes since the relationship between scene entities is broken"
|
||||
|
@ -3,7 +3,7 @@ use bevy_asset::{AssetEvent, AssetId, Assets, Handle};
|
||||
use bevy_ecs::{
|
||||
entity::{hash_map::EntityHashMap, Entity},
|
||||
event::{Event, EventCursor, Events},
|
||||
hierarchy::Parent,
|
||||
hierarchy::ChildOf,
|
||||
reflect::AppTypeRegistry,
|
||||
system::Resource,
|
||||
world::{Mut, World},
|
||||
@ -377,7 +377,7 @@ impl SceneSpawner {
|
||||
for (instance_id, parent) in scenes_with_parent {
|
||||
if let Some(instance) = self.spawned_instances.get(&instance_id) {
|
||||
for &entity in instance.entity_map.values() {
|
||||
// Add the `Parent` component to the scene root, and update the `Children` component of
|
||||
// Add the `ChildOf` component to the scene root, and update the `Children` component of
|
||||
// the scene parent
|
||||
if !world
|
||||
.get_entity(entity)
|
||||
@ -386,7 +386,7 @@ impl SceneSpawner {
|
||||
// scene have a parent
|
||||
// Entities that wouldn't exist anymore are also skipped
|
||||
// this case shouldn't happen anyway
|
||||
.is_none_or(|entity| entity.contains::<Parent>())
|
||||
.is_none_or(|entity| entity.contains::<ChildOf>())
|
||||
{
|
||||
world.entity_mut(parent).add_child(entity);
|
||||
}
|
||||
|
@ -455,13 +455,13 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
||||
),
|
||||
>,
|
||||
changed_spans: Query<
|
||||
(Entity, Option<&Parent>, Has<TextLayout>),
|
||||
(Entity, Option<&ChildOf>, Has<TextLayout>),
|
||||
(
|
||||
Or<(
|
||||
Changed<TextSpan>,
|
||||
Changed<TextFont>,
|
||||
Changed<Children>,
|
||||
Changed<Parent>, // Included to detect broken text block hierarchies.
|
||||
Changed<ChildOf>, // Included to detect broken text block hierarchies.
|
||||
Added<TextLayout>,
|
||||
)>,
|
||||
With<TextSpan>,
|
||||
@ -469,7 +469,7 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
||||
),
|
||||
>,
|
||||
mut computed: Query<(
|
||||
Option<&Parent>,
|
||||
Option<&ChildOf>,
|
||||
Option<&mut ComputedTextBlock>,
|
||||
Has<TextSpan>,
|
||||
)>,
|
||||
@ -515,7 +515,7 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
||||
// is outweighed by the expense of tracking visited spans.
|
||||
loop {
|
||||
let Ok((maybe_parent, maybe_computed, has_span)) = computed.get_mut(parent) else {
|
||||
once!(warn!("found entity {} with a TextSpan that is part of a broken hierarchy with a Parent \
|
||||
once!(warn!("found entity {} with a TextSpan that is part of a broken hierarchy with a ChildOf \
|
||||
component that points at non-existent entity {}; this warning only prints once",
|
||||
entity, parent));
|
||||
break;
|
||||
|
@ -2,7 +2,7 @@
|
||||
//! while preserving [`GlobalTransform`].
|
||||
|
||||
use crate::prelude::{GlobalTransform, Transform};
|
||||
use bevy_ecs::{entity::Entity, hierarchy::Parent, system::EntityCommands, world::EntityWorldMut};
|
||||
use bevy_ecs::{entity::Entity, hierarchy::ChildOf, system::EntityCommands, world::EntityWorldMut};
|
||||
|
||||
/// Collection of methods similar to the built-in parenting methods on [`EntityWorldMut`] and [`EntityCommands`], but preserving each
|
||||
/// entity's [`GlobalTransform`].
|
||||
@ -10,7 +10,7 @@ pub trait BuildChildrenTransformExt {
|
||||
/// Change this entity's parent while preserving this entity's [`GlobalTransform`]
|
||||
/// by updating its [`Transform`].
|
||||
///
|
||||
/// Insert the [`Parent`] component directly if you don't want to also update the [`Transform`].
|
||||
/// Insert the [`ChildOf`] component directly if you don't want to also update the [`Transform`].
|
||||
///
|
||||
/// Note that both the hierarchy and transform updates will only execute
|
||||
/// the next time commands are applied
|
||||
@ -64,7 +64,7 @@ impl BuildChildrenTransformExt for EntityWorldMut<'_> {
|
||||
fn remove_parent_in_place(&mut self) -> &mut Self {
|
||||
let child = self.id();
|
||||
self.world_scope(|world| {
|
||||
world.entity_mut(child).remove::<Parent>();
|
||||
world.entity_mut(child).remove::<ChildOf>();
|
||||
// FIXME: Replace this closure with a `try` block. See: https://github.com/rust-lang/rust/issues/31436.
|
||||
let mut update_transform = || {
|
||||
let child_global = *world.get_entity(child).ok()?.get::<GlobalTransform>()?;
|
||||
|
@ -28,7 +28,7 @@ use {
|
||||
/// ## [`Transform`] and [`GlobalTransform`]
|
||||
///
|
||||
/// [`Transform`] transforms an entity relative to its parent's reference frame, or relative to world space coordinates,
|
||||
/// if it doesn't have a [`Parent`](bevy_ecs::hierarchy::Parent).
|
||||
/// if it doesn't have a [`ChildOf`](bevy_ecs::hierarchy::ChildOf) component.
|
||||
///
|
||||
/// [`GlobalTransform`] is managed by Bevy; it is computed by successively applying the [`Transform`] of each ancestor
|
||||
/// entity which has a Transform. This is done automatically by Bevy-internal systems in the system set
|
||||
|
@ -19,7 +19,7 @@ use {bevy_ecs::reflect::ReflectComponent, bevy_reflect::prelude::*};
|
||||
/// ## [`Transform`] and [`GlobalTransform`]
|
||||
///
|
||||
/// [`Transform`] is the position of an entity relative to its parent position, or the reference
|
||||
/// frame if it doesn't have a [`Parent`](bevy_ecs::hierarchy::Parent).
|
||||
/// frame if it doesn't have a [`ChildOf`](bevy_ecs::hierarchy::ChildOf) component.
|
||||
///
|
||||
/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
|
||||
///
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! System parameter for computing up-to-date [`GlobalTransform`]s.
|
||||
|
||||
use bevy_ecs::{
|
||||
hierarchy::Parent,
|
||||
hierarchy::ChildOf,
|
||||
prelude::Entity,
|
||||
query::QueryEntityError,
|
||||
system::{Query, SystemParam},
|
||||
@ -18,7 +18,7 @@ use crate::components::{GlobalTransform, Transform};
|
||||
/// the last time the transform propagation systems ran.
|
||||
#[derive(SystemParam)]
|
||||
pub struct TransformHelper<'w, 's> {
|
||||
parent_query: Query<'w, 's, &'static Parent>,
|
||||
parent_query: Query<'w, 's, &'static ChildOf>,
|
||||
transform_query: Query<'w, 's, &'static Transform>,
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ mod tests {
|
||||
use core::f32::consts::TAU;
|
||||
|
||||
use bevy_app::App;
|
||||
use bevy_ecs::{hierarchy::Parent, system::SystemState};
|
||||
use bevy_ecs::{hierarchy::ChildOf, system::SystemState};
|
||||
use bevy_math::{Quat, Vec3};
|
||||
|
||||
use crate::{
|
||||
@ -124,7 +124,7 @@ mod tests {
|
||||
let mut e = app.world_mut().spawn(transform);
|
||||
|
||||
if let Some(entity) = entity {
|
||||
e.insert(Parent(entity));
|
||||
e.insert(ChildOf(entity));
|
||||
}
|
||||
|
||||
entity = Some(e.id());
|
||||
|
@ -11,13 +11,13 @@ pub fn sync_simple_transforms(
|
||||
(&Transform, &mut GlobalTransform),
|
||||
(
|
||||
Or<(Changed<Transform>, Added<GlobalTransform>)>,
|
||||
Without<Parent>,
|
||||
Without<ChildOf>,
|
||||
Without<Children>,
|
||||
),
|
||||
>,
|
||||
Query<(Ref<Transform>, &mut GlobalTransform), (Without<Parent>, Without<Children>)>,
|
||||
Query<(Ref<Transform>, &mut GlobalTransform), (Without<ChildOf>, Without<Children>)>,
|
||||
)>,
|
||||
mut orphaned: RemovedComponents<Parent>,
|
||||
mut orphaned: RemovedComponents<ChildOf>,
|
||||
) {
|
||||
// Update changed entities.
|
||||
query
|
||||
@ -43,11 +43,14 @@ pub fn sync_simple_transforms(
|
||||
pub fn propagate_transforms(
|
||||
mut root_query: Query<
|
||||
(Entity, &Children, Ref<Transform>, &mut GlobalTransform),
|
||||
Without<Parent>,
|
||||
Without<ChildOf>,
|
||||
>,
|
||||
mut orphaned: RemovedComponents<Parent>,
|
||||
transform_query: Query<(Ref<Transform>, &mut GlobalTransform, Option<&Children>), With<Parent>>,
|
||||
parent_query: Query<(Entity, Ref<Parent>), With<GlobalTransform>>,
|
||||
mut orphaned: RemovedComponents<ChildOf>,
|
||||
transform_query: Query<
|
||||
(Ref<Transform>, &mut GlobalTransform, Option<&Children>),
|
||||
With<ChildOf>,
|
||||
>,
|
||||
parent_query: Query<(Entity, Ref<ChildOf>), With<GlobalTransform>>,
|
||||
mut orphaned_entities: Local<Vec<Entity>>,
|
||||
) {
|
||||
orphaned_entities.clear();
|
||||
@ -109,9 +112,9 @@ unsafe fn propagate_recursive(
|
||||
parent: &GlobalTransform,
|
||||
transform_query: &Query<
|
||||
(Ref<Transform>, &mut GlobalTransform, Option<&Children>),
|
||||
With<Parent>,
|
||||
With<ChildOf>,
|
||||
>,
|
||||
parent_query: &Query<(Entity, Ref<Parent>), With<GlobalTransform>>,
|
||||
parent_query: &Query<(Entity, Ref<ChildOf>), With<GlobalTransform>>,
|
||||
entity: Entity,
|
||||
mut changed: bool,
|
||||
) {
|
||||
@ -130,7 +133,7 @@ unsafe fn propagate_recursive(
|
||||
// \ /
|
||||
// D
|
||||
//
|
||||
// D has two parents, B and C. If the propagation passes through C, but the Parent component on D points to B,
|
||||
// D has two parents, B and C. If the propagation passes through C, but the ChildOf component on D points to B,
|
||||
// the above check will panic as the origin parent does match the recorded parent.
|
||||
//
|
||||
// Also consider the following case, where A and B are roots:
|
||||
@ -203,8 +206,8 @@ mod test {
|
||||
let root = commands.spawn(offset_transform(3.3)).id();
|
||||
let parent = commands.spawn(offset_transform(4.4)).id();
|
||||
let child = commands.spawn(offset_transform(5.5)).id();
|
||||
commands.entity(parent).insert(Parent(root));
|
||||
commands.entity(child).insert(Parent(parent));
|
||||
commands.entity(parent).insert(ChildOf(root));
|
||||
commands.entity(child).insert(ChildOf(parent));
|
||||
command_queue.apply(&mut world);
|
||||
schedule.run(&mut world);
|
||||
|
||||
@ -217,7 +220,7 @@ mod test {
|
||||
// Remove parent of `parent`
|
||||
let mut command_queue = CommandQueue::default();
|
||||
let mut commands = Commands::new(&mut command_queue, &world);
|
||||
commands.entity(parent).remove::<Parent>();
|
||||
commands.entity(parent).remove::<ChildOf>();
|
||||
command_queue.apply(&mut world);
|
||||
schedule.run(&mut world);
|
||||
|
||||
@ -230,7 +233,7 @@ mod test {
|
||||
// Remove parent of `child`
|
||||
let mut command_queue = CommandQueue::default();
|
||||
let mut commands = Commands::new(&mut command_queue, &world);
|
||||
commands.entity(child).remove::<Parent>();
|
||||
commands.entity(child).remove::<ChildOf>();
|
||||
command_queue.apply(&mut world);
|
||||
schedule.run(&mut world);
|
||||
|
||||
@ -426,7 +429,7 @@ mod test {
|
||||
#[should_panic]
|
||||
fn panic_when_hierarchy_cycle() {
|
||||
ComputeTaskPool::get_or_init(TaskPool::default);
|
||||
// We cannot directly edit Parent and Children, so we use a temp world to break
|
||||
// We cannot directly edit ChildOf and Children, so we use a temp world to break
|
||||
// the hierarchy's invariants.
|
||||
let mut temp = World::new();
|
||||
let mut app = App::new();
|
||||
@ -456,25 +459,25 @@ mod test {
|
||||
core::mem::swap(
|
||||
#[expect(
|
||||
unsafe_code,
|
||||
reason = "Parent is not mutable but this is for a test to produce a scenario that cannot happen"
|
||||
reason = "ChildOf is not mutable but this is for a test to produce a scenario that cannot happen"
|
||||
)]
|
||||
// SAFETY: Parent is not mutable but this is for a test to produce a scenario that cannot happen
|
||||
// SAFETY: ChildOf is not mutable but this is for a test to produce a scenario that cannot happen
|
||||
unsafe {
|
||||
&mut *app
|
||||
.world_mut()
|
||||
.entity_mut(child)
|
||||
.get_mut_assume_mutable::<Parent>()
|
||||
.get_mut_assume_mutable::<ChildOf>()
|
||||
.unwrap()
|
||||
},
|
||||
// SAFETY: Parent is not mutable but this is for a test to produce a scenario that cannot happen
|
||||
// SAFETY: ChildOf is not mutable but this is for a test to produce a scenario that cannot happen
|
||||
#[expect(
|
||||
unsafe_code,
|
||||
reason = "Parent is not mutable but this is for a test to produce a scenario that cannot happen"
|
||||
reason = "ChildOf is not mutable but this is for a test to produce a scenario that cannot happen"
|
||||
)]
|
||||
unsafe {
|
||||
&mut *temp
|
||||
.entity_mut(grandchild)
|
||||
.get_mut_assume_mutable::<Parent>()
|
||||
.get_mut_assume_mutable::<ChildOf>()
|
||||
.unwrap()
|
||||
},
|
||||
);
|
||||
@ -514,7 +517,7 @@ mod test {
|
||||
.abs_diff_eq(2. * translation, 0.1));
|
||||
|
||||
// Reparent child
|
||||
world.entity_mut(child).remove::<Parent>();
|
||||
world.entity_mut(child).remove::<ChildOf>();
|
||||
world.entity_mut(parent).add_child(child);
|
||||
|
||||
// Run schedule to propagate transforms
|
||||
|
@ -43,17 +43,17 @@ impl GhostNode {
|
||||
#[cfg(feature = "ghost_nodes")]
|
||||
/// System param that allows iteration of all UI root nodes.
|
||||
///
|
||||
/// A UI root node is either a [`Node`] without a [`Parent`], or with only [`GhostNode`] ancestors.
|
||||
/// A UI root node is either a [`Node`] without a [`ChildOf`], or with only [`GhostNode`] ancestors.
|
||||
#[derive(SystemParam)]
|
||||
pub struct UiRootNodes<'w, 's> {
|
||||
root_node_query: Query<'w, 's, Entity, (With<Node>, Without<Parent>)>,
|
||||
root_ghost_node_query: Query<'w, 's, Entity, (With<GhostNode>, Without<Parent>)>,
|
||||
root_node_query: Query<'w, 's, Entity, (With<Node>, Without<ChildOf>)>,
|
||||
root_ghost_node_query: Query<'w, 's, Entity, (With<GhostNode>, Without<ChildOf>)>,
|
||||
all_nodes_query: Query<'w, 's, Entity, With<Node>>,
|
||||
ui_children: UiChildren<'w, 's>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ghost_nodes"))]
|
||||
pub type UiRootNodes<'w, 's> = Query<'w, 's, Entity, (With<Node>, Without<Parent>)>;
|
||||
pub type UiRootNodes<'w, 's> = Query<'w, 's, Entity, (With<Node>, Without<ChildOf>)>;
|
||||
|
||||
#[cfg(feature = "ghost_nodes")]
|
||||
impl<'w, 's> UiRootNodes<'w, 's> {
|
||||
@ -80,7 +80,7 @@ pub struct UiChildren<'w, 's> {
|
||||
changed_children_query: Query<'w, 's, Entity, Changed<Children>>,
|
||||
children_query: Query<'w, 's, &'static Children>,
|
||||
ghost_nodes_query: Query<'w, 's, Entity, With<GhostNode>>,
|
||||
parents_query: Query<'w, 's, &'static Parent>,
|
||||
parents_query: Query<'w, 's, &'static ChildOf>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ghost_nodes"))]
|
||||
@ -89,7 +89,7 @@ pub struct UiChildren<'w, 's> {
|
||||
pub struct UiChildren<'w, 's> {
|
||||
ui_children_query: Query<'w, 's, Option<&'static Children>, With<Node>>,
|
||||
changed_children_query: Query<'w, 's, Entity, Changed<Children>>,
|
||||
parents_query: Query<'w, 's, &'static Parent>,
|
||||
parents_query: Query<'w, 's, &'static ChildOf>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "ghost_nodes")]
|
||||
|
@ -107,7 +107,7 @@ pub fn ui_layout_system(
|
||||
Option<&mut ContentSize>,
|
||||
Option<&UiTargetCamera>,
|
||||
)>,
|
||||
computed_node_query: Query<(Entity, Option<Ref<Parent>>), With<ComputedNode>>,
|
||||
computed_node_query: Query<(Entity, Option<Ref<ChildOf>>), With<ComputedNode>>,
|
||||
ui_children: UiChildren,
|
||||
mut removed_components: UiLayoutSystemRemovedComponentParam,
|
||||
mut node_transform_query: Query<(
|
||||
@ -844,7 +844,7 @@ mod tests {
|
||||
ui_schedule.run(&mut world);
|
||||
|
||||
let overlap_check = world
|
||||
.query_filtered::<(Entity, &ComputedNode, &GlobalTransform), Without<Parent>>()
|
||||
.query_filtered::<(Entity, &ComputedNode, &GlobalTransform), Without<ChildOf>>()
|
||||
.iter(&world)
|
||||
.fold(
|
||||
Option::<(Rect, bool)>::None,
|
||||
|
@ -179,7 +179,7 @@ fn update_accessibility_nodes(
|
||||
Entity,
|
||||
&AccessibilityNode,
|
||||
Option<&Children>,
|
||||
Option<&Parent>,
|
||||
Option<&ChildOf>,
|
||||
)>,
|
||||
node_entities: Query<Entity, With<AccessibilityNode>>,
|
||||
) {
|
||||
@ -218,7 +218,7 @@ fn update_adapter(
|
||||
Entity,
|
||||
&AccessibilityNode,
|
||||
Option<&Children>,
|
||||
Option<&Parent>,
|
||||
Option<&ChildOf>,
|
||||
)>,
|
||||
node_entities: Query<Entity, With<AccessibilityNode>>,
|
||||
primary_window: &Window,
|
||||
@ -253,12 +253,12 @@ fn update_adapter(
|
||||
#[inline]
|
||||
fn queue_node_for_update(
|
||||
node_entity: Entity,
|
||||
parent: Option<&Parent>,
|
||||
child_of: Option<&ChildOf>,
|
||||
node_entities: &Query<Entity, With<AccessibilityNode>>,
|
||||
window_children: &mut Vec<NodeId>,
|
||||
) {
|
||||
let should_push = if let Some(parent) = parent {
|
||||
!node_entities.contains(parent.get())
|
||||
let should_push = if let Some(child_of) = child_of {
|
||||
!node_entities.contains(child_of.get())
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
A runtime warning.
|
||||
|
||||
An [`Entity`] with a hierarchy-inherited component has a [`Parent`]
|
||||
An [`Entity`] with a hierarchy-inherited component has a [`ChildOf`]
|
||||
without the hierarchy-inherited component in question.
|
||||
|
||||
The hierarchy-inherited components defined in bevy include:
|
||||
@ -108,5 +108,5 @@ as a child of a pre-existing [`Entity`] that does not have the proper components
|
||||
[`ViewVisibility`]: https://docs.rs/bevy/*/bevy/render/view/struct.ViewVisibility.html
|
||||
[`Visibility`]: https://docs.rs/bevy/*/bevy/render/view/struct.Visibility.html
|
||||
[`GlobalTransform`]: https://docs.rs/bevy/*/bevy/transform/components/struct.GlobalTransform.html
|
||||
[`Parent`]: https://docs.rs/bevy/*/bevy/hierarchy/struct.Parent.html
|
||||
[`ChildOf`]: https://docs.rs/bevy/*/bevy/ecs/hierarchy/struct.ChildOf.html
|
||||
[`Entity`]: https://docs.rs/bevy/*/bevy/ecs/entity/struct.Entity.html
|
||||
|
@ -432,7 +432,7 @@ fn reset_sphere_position(
|
||||
fn move_sphere(
|
||||
mouse_button_input: Res<ButtonInput<MouseButton>>,
|
||||
pointers: Query<&PointerInteraction>,
|
||||
mut meshes: Query<(&Name, &Parent), With<Mesh3d>>,
|
||||
mut meshes: Query<(&Name, &ChildOf), With<Mesh3d>>,
|
||||
mut transforms: Query<&mut Transform>,
|
||||
app_status: Res<AppStatus>,
|
||||
) {
|
||||
@ -445,11 +445,11 @@ fn move_sphere(
|
||||
}
|
||||
|
||||
// Find the sphere.
|
||||
let Some(parent) = meshes
|
||||
let Some(child_of) = meshes
|
||||
.iter_mut()
|
||||
.filter_map(|(name, parent)| {
|
||||
.filter_map(|(name, child_of)| {
|
||||
if &**name == "Sphere" {
|
||||
Some(parent)
|
||||
Some(child_of)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -460,7 +460,7 @@ fn move_sphere(
|
||||
};
|
||||
|
||||
// Grab its transform.
|
||||
let Ok(mut transform) = transforms.get_mut(parent.0) else {
|
||||
let Ok(mut transform) = transforms.get_mut(child_of.0) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -175,19 +175,19 @@ fn setup(
|
||||
fn set_visibility_ranges(
|
||||
mut commands: Commands,
|
||||
mut new_meshes: Query<Entity, Added<Mesh3d>>,
|
||||
parents: Query<(Option<&Parent>, Option<&MainModel>)>,
|
||||
children: Query<(Option<&ChildOf>, Option<&MainModel>)>,
|
||||
) {
|
||||
// Loop over each newly-added mesh.
|
||||
for new_mesh in new_meshes.iter_mut() {
|
||||
// Search for the nearest ancestor `MainModel` component.
|
||||
let (mut current, mut main_model) = (new_mesh, None);
|
||||
while let Ok((parent, maybe_main_model)) = parents.get(current) {
|
||||
while let Ok((child_of, maybe_main_model)) = children.get(current) {
|
||||
if let Some(model) = maybe_main_model {
|
||||
main_model = Some(model);
|
||||
break;
|
||||
}
|
||||
match parent {
|
||||
Some(parent) => current = parent.0,
|
||||
match child_of {
|
||||
Some(child_of) => current = child_of.0,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
@ -44,21 +44,21 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
/// It is similar to the animation defined in `models/SimpleSkin/SimpleSkin.gltf`.
|
||||
fn joint_animation(
|
||||
time: Res<Time>,
|
||||
parent_query: Query<&Parent, With<SkinnedMesh>>,
|
||||
children_query: Query<&Children>,
|
||||
children: Query<&ChildOf, With<SkinnedMesh>>,
|
||||
parents: Query<&Children>,
|
||||
mut transform_query: Query<&mut Transform>,
|
||||
) {
|
||||
// Iter skinned mesh entity
|
||||
for skinned_mesh_parent in &parent_query {
|
||||
for child_of in &children {
|
||||
// Mesh node is the parent of the skinned mesh entity.
|
||||
let mesh_node_entity = skinned_mesh_parent.get();
|
||||
let mesh_node_entity = child_of.get();
|
||||
// Get `Children` in the mesh node.
|
||||
let mesh_node_children = children_query.get(mesh_node_entity).unwrap();
|
||||
let mesh_node_parent = parents.get(mesh_node_entity).unwrap();
|
||||
|
||||
// First joint is the second child of the mesh node.
|
||||
let first_joint_entity = mesh_node_children[1];
|
||||
let first_joint_entity = mesh_node_parent[1];
|
||||
// Get `Children` in the first joint.
|
||||
let first_joint_children = children_query.get(first_joint_entity).unwrap();
|
||||
let first_joint_children = parents.get(first_joint_entity).unwrap();
|
||||
|
||||
// Second joint is the first child of the first joint.
|
||||
let second_joint_entity = first_joint_children[0];
|
||||
|
@ -67,7 +67,7 @@ fn rotate(
|
||||
}
|
||||
|
||||
// To iterate through the entities children, just treat the Children component as a Vec
|
||||
// Alternatively, you could query entities that have a Parent component
|
||||
// Alternatively, you could query entities that have a ChildOf component
|
||||
for child in children {
|
||||
if let Ok(mut transform) = transform_query.get_mut(*child) {
|
||||
transform.rotate_z(PI * time.delta_secs());
|
||||
|
@ -51,9 +51,9 @@ struct Attack {
|
||||
// two important pieces of information:
|
||||
impl Event for Attack {
|
||||
// 1. Which component we want to propagate along. In this case, we want to "bubble" (meaning propagate
|
||||
// from child to parent) so we use the `Parent` component for propagation. The component supplied
|
||||
// from child to parent) so we use the `ChildOf` component for propagation. The component supplied
|
||||
// must implement the `Traversal` trait.
|
||||
type Traversal = &'static Parent;
|
||||
type Traversal = &'static ChildOf;
|
||||
// 2. We can also choose whether or not this event will propagate by default when triggered. If this is
|
||||
// false, it will only propagate following a call to `Trigger::propagate(true)`.
|
||||
const AUTO_PROPAGATE: bool = true;
|
||||
|
@ -295,6 +295,6 @@ fn spawn_button(
|
||||
}
|
||||
}
|
||||
|
||||
fn despawn_ui(mut commands: Commands, root_node: Single<Entity, (With<Node>, Without<Parent>)>) {
|
||||
fn despawn_ui(mut commands: Commands, root_node: Single<Entity, (With<Node>, Without<ChildOf>)>) {
|
||||
commands.entity(*root_node).despawn();
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
fn toggle_debug_overlay(
|
||||
input: Res<ButtonInput<KeyCode>>,
|
||||
mut debug_options: ResMut<UiDebugOptions>,
|
||||
mut root_node_query: Query<&mut Visibility, (With<Node>, Without<Parent>)>,
|
||||
mut root_node_query: Query<&mut Visibility, (With<Node>, Without<ChildOf>)>,
|
||||
) {
|
||||
info_once!("The debug outlines are enabled, press Space to turn them on/off");
|
||||
if input.just_pressed(KeyCode::Space) {
|
||||
|
@ -37,7 +37,7 @@ impl Clips {
|
||||
fn assign_clips(
|
||||
mut players: Query<&mut AnimationPlayer>,
|
||||
targets: Query<(Entity, &AnimationTarget)>,
|
||||
parents: Query<&Parent>,
|
||||
children: Query<&ChildOf>,
|
||||
scene_handle: Res<SceneHandle>,
|
||||
clips: Res<Assets<AnimationClip>>,
|
||||
gltf_assets: Res<Assets<Gltf>>,
|
||||
@ -109,7 +109,7 @@ fn assign_clips(
|
||||
}
|
||||
|
||||
// Go to the next parent.
|
||||
current = parents.get(entity).ok().map(Parent::get);
|
||||
current = children.get(entity).ok().map(ChildOf::get);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,8 @@ fn create_label(text: &str, font: Handle<Font>) -> (Text, TextFont, TextColor) {
|
||||
}
|
||||
|
||||
fn button_system(
|
||||
mut interaction_query: Query<(&Interaction, &Parent), (Changed<Interaction>, With<Button>)>,
|
||||
labels_query: Query<(&Children, &Parent), With<Button>>,
|
||||
mut interaction_query: Query<(&Interaction, &ChildOf), (Changed<Interaction>, With<Button>)>,
|
||||
labels_query: Query<(&Children, &ChildOf), With<Button>>,
|
||||
mut text_query: Query<&mut Text>,
|
||||
mut counter_query: Query<&mut Counter>,
|
||||
) {
|
||||
@ -119,8 +119,8 @@ fn button_system(
|
||||
}
|
||||
|
||||
// Update button labels to match their parent counter
|
||||
for (children, parent) in &labels_query {
|
||||
let counter = counter_query.get(parent.get()).unwrap();
|
||||
for (children, child_of) in &labels_query {
|
||||
let counter = counter_query.get(child_of.get()).unwrap();
|
||||
let mut text = text_query.get_mut(children[0]).unwrap();
|
||||
|
||||
**text = counter.0.to_string();
|
||||
|
Loading…
Reference in New Issue
Block a user