moonshine_util/
spawn.rs

1//! Utilities related to spawning entities.
2
3use bevy_ecs::lifecycle::HookContext;
4use bevy_ecs::prelude::*;
5use bevy_ecs::world::DeferredWorld;
6
7use crate::Static;
8
9/// This [`Component`] is similar to [`SpawnWith`], but it spawns the
10/// associated entity without any [`Relationship`](bevy_ecs::relationship::Relationship).
11#[derive(Component)]
12#[component(storage = "SparseSet")]
13#[component(on_add = Self::on_add)]
14pub struct SpawnUnrelated<B: Bundle, F: FnOnce(Entity) -> B>(pub F)
15where
16    F: Static,
17    B: Static;
18
19impl<B: Bundle, F: FnOnce(Entity) -> B> SpawnUnrelated<B, F>
20where
21    F: Static,
22    B: Static,
23{
24    fn on_add(mut world: DeferredWorld, ctx: HookContext) {
25        let entity = ctx.entity;
26        world.commands().queue(move |world: &mut World| {
27            let mut entity = world.entity_mut(entity);
28            let SpawnUnrelated(f) = entity.take::<Self>().unwrap();
29            let source = entity.id();
30            world.spawn(f(source));
31        });
32    }
33}
34
35/// A [`Component`] which spawns a child [`Entity`] when inserted into some parent.
36///
37/// Unlike [`Children::spawn`](SpawnRelated::spawn) (and by extension [`children!`]), each instance
38/// of this component is unique, allowing you to have multiple instances of it in the same bundle.
39#[derive(Component)]
40#[component(storage = "SparseSet")]
41#[component(on_add = Self::on_add)]
42pub struct WithChild<B: Bundle, F: FnOnce(Entity) -> B>(pub F)
43where
44    F: Static,
45    B: Static;
46
47impl<B: Bundle, F: FnOnce(Entity) -> B> WithChild<B, F>
48where
49    F: Static,
50    B: Static,
51{
52    fn on_add(mut world: DeferredWorld, ctx: HookContext) {
53        let entity = ctx.entity;
54        world.commands().queue(move |world: &mut World| {
55            let mut entity = world.entity_mut(entity);
56            let WithChild(f) = entity.take::<Self>().unwrap();
57            entity.with_child(f(entity.id()));
58        });
59    }
60}