Skip to content

Commit 6aba995

Browse files
eckzcart
andauthored
Allowing using ChildOf directly inside bsn! macro (#23921)
# Objective If I want to spawn a scene as a child of an entity that already exists, the current api doesn't offer an straightfoward solution. The easies I found is by doing something like this: ```rust const my_entity = ...; commands.spawn_scene(bsn! { template(move |_| Ok(ChildOf(my_entity))) scenes::list_item(text) }); ``` ## Solution - Deriving directly `FromTemplate` for `ChildOf`. - Adding a new variant to `EntityReference`. - This allows code like this to work directly ```rust fn scene(root: Entity) -> impl Scene { bsn! { ( #Child1 ChildOf(root) ), } } ``` ## Testing - Running unit tests locally. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
1 parent cfb897f commit 6aba995

3 files changed

Lines changed: 42 additions & 2 deletions

File tree

crates/bevy_ecs/src/hierarchy.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::{
1414
entity::Entity,
1515
relationship::{RelatedSpawner, RelatedSpawnerCommands},
1616
system::EntityCommands,
17+
template::FromTemplate,
1718
world::{EntityWorldMut, FromWorld, World},
1819
};
1920
use alloc::vec::Vec;
@@ -90,7 +91,7 @@ use core::slice;
9091
/// ```
9192
///
9293
/// [`Relationship`]: crate::relationship::Relationship
93-
#[derive(Component, Clone, PartialEq, Eq, Debug)]
94+
#[derive(Component, FromTemplate, Clone, PartialEq, Eq, Debug)]
9495
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
9596
#[cfg_attr(
9697
feature = "bevy_reflect",

crates/bevy_ecs/src/template.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ pub trait SpecializeFromTemplate: Sized {}
403403

404404
/// A [`Template`] reference to an [`Entity`].
405405
pub enum EntityReference {
406+
/// A reference to a specific [`Entity`]
407+
Entity(Entity),
406408
/// A reference to an entity via a [`ScopedEntityIndex`]
407409
ScopedEntityIndex(ScopedEntityIndex),
408410
}
@@ -427,19 +429,27 @@ impl Default for EntityReference {
427429
}
428430
}
429431

432+
impl From<Entity> for EntityReference {
433+
fn from(entity: Entity) -> Self {
434+
Self::Entity(entity)
435+
}
436+
}
437+
430438
impl Template for EntityReference {
431439
type Output = Entity;
432440

433441
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
434442
Ok(match self {
435-
EntityReference::ScopedEntityIndex(scoped_entity_index) => {
443+
Self::Entity(entity) => *entity,
444+
Self::ScopedEntityIndex(scoped_entity_index) => {
436445
context.get_scoped_entity(*scoped_entity_index)
437446
}
438447
})
439448
}
440449

441450
fn clone_template(&self) -> Self {
442451
match self {
452+
Self::Entity(entity) => Self::Entity(*entity),
443453
Self::ScopedEntityIndex(scoped_entity_index) => {
444454
Self::ScopedEntityIndex(*scoped_entity_index)
445455
}

crates/bevy_scene/src/lib.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ mod tests {
569569
use bevy_asset::{Asset, AssetApp, AssetLoader, AssetPlugin, AssetServer, Assets, Handle};
570570
use bevy_ecs::lifecycle::HookContext;
571571
use bevy_ecs::prelude::*;
572+
use bevy_ecs::relationship::Relationship;
572573
use bevy_ecs::world::DeferredWorld;
573574
use bevy_reflect::TypePath;
574575
use std::path::Path;
@@ -1154,6 +1155,34 @@ mod tests {
11541155
assert_eq!(sprite.0, handle);
11551156
}
11561157

1158+
#[test]
1159+
fn child_of_template() {
1160+
let mut app = test_app();
1161+
1162+
let world = app.world_mut();
1163+
1164+
fn scene(root: Entity) -> impl SceneList {
1165+
bsn_list! {
1166+
( #Child1 ChildOf(root) ),
1167+
( #Child2 ChildOf(#Child1) ),
1168+
}
1169+
}
1170+
1171+
let root = world.spawn_empty().id();
1172+
1173+
let ids = world.spawn_scene_list(scene(root)).unwrap();
1174+
assert_eq!(ids.len(), 2);
1175+
1176+
let [a, b] = world.entity(&*ids)[..] else {
1177+
unreachable!()
1178+
};
1179+
assert_eq!(a.get::<Name>().unwrap().as_str(), "Child1");
1180+
assert_eq!(a.get::<ChildOf>().unwrap().get(), root);
1181+
1182+
assert_eq!(b.get::<Name>().unwrap().as_str(), "Child2");
1183+
assert_eq!(b.get::<ChildOf>().unwrap().get(), a.id());
1184+
}
1185+
11571186
#[test]
11581187
fn scene_list_children() {
11591188
let mut app = test_app();

0 commit comments

Comments
 (0)