Skip to main content

bevy_ecs/
template.rs

1//! Functionality that relates to the [`Template`] trait.
2pub use bevy_ecs_macros::FromTemplate;
3
4use core::{hash::Hash, ops::Deref};
5
6use crate::{
7    component::Mutable,
8    entity::Entity,
9    error::{BevyError, Result},
10    resource::Resource,
11    world::{EntityWorldMut, Mut, World},
12};
13use alloc::vec::Vec;
14use bevy_platform::{collections::hash_map::RawEntryMut, hash::Hashed};
15use bevy_utils::PreHashMap;
16use indexmap::Equivalent;
17use variadics_please::all_tuples;
18
19/// A [`Template`] is something that, given a spawn context (target [`Entity`], [`World`], etc), can produce a [`Template::Output`].
20///
21/// [`Template`] is the cornerstone of scene systems. It enables define types (and hierarchies) that require no [`World`] or [`Entity`] context to define,
22/// but can _use_ that context to produce the final runtime state. A [`Template`] is notably:
23/// * **Repeatable**: Building a [`Template`] does not consume it. This enables reusing "baked" scenes / avoids rebuilding scenes each time we want to spawn one.
24/// * **Clone-able**: Templates can be duplicated via [`Template::clone_template`], enabling scenes to be duplicated, supporting copy-on-write behaviors, etc.
25/// * **(Often) Serializable**: Templates are intended to be easily serialized and deserialized, as they are typically composed of raw data.
26///
27/// Asset handles and [`Entity`] are two commonly [`Template`]-ed types. Asset handles are often "loaded" from an "asset path". The "asset path" would be the [`Template`].
28/// Likewise [`Entity`] on its own has no reasonable default. A type with an [`Entity`] reference could use an "entity path" template to point to a specific entity, relative
29/// to the current spawn context.
30///
31/// See [`FromTemplate`], which defines the canonical [`Template`] for a type. This can be derived, which will generate a [`Template`] for the deriving type.
32pub trait Template {
33    /// The type of value produced by this [`Template`].
34    type Output;
35
36    /// Uses this template and the given `entity` context to produce a [`Template::Output`].
37    fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output>;
38
39    /// Clones this template. See [`Clone`].
40    fn clone_template(&self) -> Self;
41}
42
43/// The context used to apply the current [`Template`]. This contains a reference to the entity that the template is being
44/// applied to (via an [`EntityWorldMut`]).
45pub struct TemplateContext<'a, 'w> {
46    /// The current entity the template is being applied to
47    pub entity: &'a mut EntityWorldMut<'w>,
48    /// A mapping of [`SceneEntityReference`] to [`Entity`] used for resolving `#Name` entity references
49    pub entity_references: &'a mut SceneEntityReferences,
50}
51
52impl<'a, 'w> TemplateContext<'a, 'w> {
53    /// Creates a new [`TemplateContext`].
54    pub fn new(
55        entity: &'a mut EntityWorldMut<'w>,
56        entity_references: &'a mut SceneEntityReferences,
57    ) -> Self {
58        Self {
59            entity,
60            entity_references,
61        }
62    }
63    /// Get the entity associated with the [`SceneEntityReference`], spawning a new one
64    /// if this is the first call with this index.
65    pub fn get_entity(&mut self, reference: SceneEntityReference) -> Entity {
66        self.entity_references.get(
67            reference,
68            // Safety: only used to create a new Entity
69            unsafe { self.entity.world_mut() },
70        )
71    }
72
73    /// Retrieves a reference to the given resource `R`.
74    #[inline]
75    pub fn resource<R: Resource>(&self) -> &R {
76        self.entity.resource()
77    }
78
79    /// Retrieves a mutable reference to the given resource `R`.
80    #[inline]
81    pub fn resource_mut<R: Resource<Mutability = Mutable>>(&mut self) -> Mut<'_, R> {
82        self.entity.resource_mut()
83    }
84
85    /// Retrieves the entity associated with the given resource `R`, if it exists.
86    #[inline]
87    pub fn resource_entity<R: Resource>(&self) -> Option<Entity> {
88        self.entity.resource_entity::<R>()
89    }
90}
91
92/// Struct to store a mapping from [`SceneEntityReference`] to [`Entity`]
93/// which are used for resolving `#Name` entity references in bsn! macros
94#[derive(Default)]
95pub struct SceneEntityReferences(PreHashMap<InnerSceneEntityReference, Entity>);
96
97impl SceneEntityReferences {
98    /// Get the [`Entity`] associated with this [`SceneEntityReference`]
99    /// If the index is unknown, spawn a new empty [`Entity`] and store it
100    pub fn get(&mut self, reference: SceneEntityReference, world: &mut World) -> Entity {
101        let inner = reference.0;
102        let entry = self
103            .0
104            .raw_entry_mut()
105            .from_key_hashed_nocheck(inner.hash(), &inner);
106        match entry {
107            RawEntryMut::Occupied(entry) => *entry.get(),
108            RawEntryMut::Vacant(view) => {
109                let entity = world.spawn_empty().id();
110                view.insert_hashed_nocheck(inner.hash(), inner, entity);
111                entity
112            }
113        }
114    }
115
116    /// Set the [`Entity`] associated with a [`SceneEntityReference`]
117    pub fn set(&mut self, reference: SceneEntityReference, entity: Entity) {
118        let inner = reference.0;
119        match self
120            .0
121            .raw_entry_mut()
122            .from_key_hashed_nocheck(inner.hash(), &inner)
123        {
124            RawEntryMut::Occupied(_) => {}
125            RawEntryMut::Vacant(view) => {
126                view.insert_hashed_nocheck(inner.hash(), inner, entity);
127            }
128        };
129    }
130}
131
132/// A unique reference for a named entity in a scene.
133/// Usually used by `bevy_scene` in generated code
134///
135/// Hashed here should allow implementing compile-time hashing in the future
136///
137/// The uniqueness of this is ensured by the following factors:
138/// - macro invocation location: filename, line and column
139/// - the `name_id` should uniquely identify a name in the individual macros scope
140/// - runtime, per-scope counter for each runtime call (usually from a static `AtomicU64`)
141#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
142pub struct SceneEntityReference(Hashed<InnerSceneEntityReference>);
143
144/// The inner struct actually storing the unique index
145#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
146pub struct InnerSceneEntityReference {
147    file: &'static str,
148    line: usize,
149    column: usize,
150    name_id: usize,
151    runtime: u64,
152}
153impl SceneEntityReference {
154    /// Create a new [`SceneEntityReference`] from the invocation location, runtime time, and a local (per-macro) counter for names
155    pub fn new(
156        (file, line, column): (&'static str, usize, usize),
157        name_id: usize,
158        runtime: u64,
159    ) -> Self {
160        Self(Hashed::new(InnerSceneEntityReference {
161            file,
162            line,
163            column,
164            name_id,
165            runtime,
166        }))
167    }
168}
169
170impl core::fmt::Display for SceneEntityReference {
171    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172        f.write_fmt(format_args!(
173            "global={}:{}:{} name_id={} runtime={:?}",
174            self.file, self.line, self.column, self.name_id, self.runtime
175        ))
176    }
177}
178
179impl Deref for SceneEntityReference {
180    type Target = Hashed<InnerSceneEntityReference>;
181
182    #[inline]
183    fn deref(&self) -> &Self::Target {
184        &self.0
185    }
186}
187
188impl Equivalent<Hashed<InnerSceneEntityReference>> for SceneEntityReference {
189    #[inline]
190    fn equivalent(&self, key: &Hashed<InnerSceneEntityReference>) -> bool {
191        &self.0 == key
192    }
193}
194
195/// [`FromTemplate`] is implemented for types that can be produced by a specific, canonical [`Template`]. This creates a way to correlate to the [`Template`] using the
196/// desired template output type. This is used by Bevy's scene system.
197///
198/// Both [`FromTemplate`] and [`Template`] are blanket implemented for types that implement [`Default`] and [`Clone`], meaning most types you would want to use
199/// _already have templates_.
200///
201/// It is best to think of [`FromTemplate`] as an alternative to [`Default`] for types that require world/spawn context to instantiate. Note that because of the blanket
202/// impl, you cannot implement [`FromTemplate`], [`Default`], and [`Clone`] together on the same type, as it would result in two conflicting [`FromTemplate`] impls.
203/// This is also why [`Template`] has its own [`Template::clone_template`] method (to avoid using the [`Clone`] impl, which would pull in the auto-impl).
204///
205/// You can _and should_ prefer deriving [`Default`] and [`Clone`] instead of an explicit [`FromTemplate`] impl, unless your type uses something that requires (or uses)
206/// a [`Template`]. Handles in an asset system or [`Entity`] are examples of "templated" types. If you want your type to support templates of them, you probably want
207/// to derive [`FromTemplate`].
208///
209/// [`FromTemplate`] can be derived for types whose fields _also_ implement [`FromTemplate`]:
210/// ```
211/// # use bevy_ecs::prelude::*;
212/// # #[derive(Default, Clone)]
213/// # struct Handle<T>(core::marker::PhantomData<T>);
214/// # #[derive(Default, Clone)]
215/// # struct Image;
216/// #[derive(FromTemplate)]
217/// struct Player {
218///     image: Handle<Image>
219/// }
220/// ```
221///
222/// Deriving [`FromTemplate`] will generate a [`Template`] type for the deriving type. The example above would generate a `PlayerTemplate` like this:
223/// ```
224/// # use bevy_ecs::{prelude::*, template::TemplateContext};
225/// # #[derive(FromTemplate)]
226/// # struct Handle<T: core::marker::Unpin>(core::marker::PhantomData<T>);
227/// # #[derive(Default, Clone)]
228/// # struct Image;
229/// struct Player {
230///     image: Handle<Image>
231/// }
232///
233/// impl FromTemplate for Player {
234///     type Template = PlayerTemplate;
235/// }
236///
237/// struct PlayerTemplate {
238///     image: HandleTemplate<Image>,
239/// }
240///
241/// impl Template for PlayerTemplate {
242///     type Output = Player;
243///     fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
244///         Ok(Player {
245///             image: self.image.build_template(context)?,
246///         })
247///     }
248///
249///     fn clone_template(&self) -> Self {
250///         PlayerTemplate {
251///             image: self.image.clone_template(),
252///         }
253///     }
254/// }
255/// ```
256///
257/// [`FromTemplate`] derives can specify custom templates to use instead of a canonical [`FromTemplate`]:
258/// ```
259/// # use bevy_ecs::{prelude::*, template::TemplateContext};
260/// # struct Image;
261/// #[derive(FromTemplate)]
262/// struct Counter {
263///     #[template(Always10)]
264///     count: usize
265/// }
266///
267/// #[derive(Default)]
268/// struct Always10;
269///
270/// impl Template for Always10 {
271///     type Output = usize;
272///
273///     fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
274///         Ok(10)
275///     }
276///
277///     fn clone_template(&self) -> Self {
278///         Always10
279///     }
280/// }
281/// ```
282///
283/// [`FromTemplate`] is automatically implemented for anything that is [`Default`] and [`Clone`]. "Built in" collection types like
284/// [`Option`] and [`Vec`] pick up this "blanket" implementation, which is generally a good thing because it means these collection
285/// types work with [`FromTemplate`] derives by default. However if the items in the collection have a custom [`FromTemplate`] impl
286/// (ex: a manual implementation like `Handle<T>` for assets or an explicit [`FromTemplate`] derive), then relying on a [`Default`] /
287/// [`Clone`] implementation doesn't work, as that won't run the template logic!
288///
289/// Therefore, cases like [`Option<Handle<T>>`] need something other than [`FromTemplate`] to determine the type. One option is to specify
290/// the template manually:
291///
292/// ```
293/// # use bevy_ecs::{prelude::*, template::{TemplateContext, OptionTemplate}};
294/// # use core::marker::PhantomData;
295/// # struct Handle<T>(PhantomData<T>);
296/// # struct HandleTemplate<T>(PhantomData<T>);
297/// # struct Image;
298/// # impl<T> FromTemplate for Handle<T> {
299/// #     type Template = HandleTemplate<T>;
300/// # }
301/// # impl<T> Template for HandleTemplate<T> {
302/// #    type Output = Handle<T>;
303/// #    fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
304/// #        unimplemented!()
305/// #    }
306/// #    fn clone_template(&self) -> Self {
307/// #        unimplemented!()
308/// #    }
309/// # }
310/// #[derive(FromTemplate)]
311/// struct Widget {
312///     #[template(OptionTemplate<HandleTemplate<Image>>)]
313///     image: Option<Handle<Image>>
314/// }
315/// ```
316///
317/// However that is a bit of a mouthful! This is where [`BuiltInTemplate`] comes in. It fills the same role
318/// as [`FromTemplate`], but has no blanket implementation for [`Default`] and [`Clone`], meaning we can have
319/// custom implementations for types like [`Option`] and [`Vec`].
320///
321/// If you are deriving [`FromTemplate`] and you have a "built in" type like [`Option<Handle<T>>`] which has custom template logic,
322/// annotate it with the `template(built_in)` attribute to use [`BuiltInTemplate`] instead of [`FromTemplate`]:
323///
324/// ```
325/// # use bevy_ecs::{prelude::*, template::TemplateContext};
326/// # use core::marker::PhantomData;
327/// # struct Handle<T>(PhantomData<T>);
328/// # struct HandleTemplate<T>(PhantomData<T>);
329/// # struct Image;
330/// # impl<T> FromTemplate for Handle<T> {
331/// #     type Template = HandleTemplate<T>;
332/// # }
333/// # impl<T> Template for HandleTemplate<T> {
334/// #    type Output = Handle<T>;
335/// #    fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
336/// #        unimplemented!()
337/// #    }
338/// #    fn clone_template(&self) -> Self {
339/// #        unimplemented!()
340/// #    }
341/// # }
342/// #[derive(FromTemplate)]
343/// struct Widget {
344///     #[template(built_in)]
345///     image: Option<Handle<Image>>
346/// }
347/// ```
348pub trait FromTemplate: Sized {
349    /// The [`Template`] for this type.
350    type Template: Template<Output = Self>;
351}
352
353macro_rules! template_impl {
354    ($($template: ident),*) => {
355        #[expect(
356            clippy::allow_attributes,
357            reason = "This is a tuple-related macro; as such, the lints below may not always apply."
358        )]
359        impl<$($template: Template),*> Template for TemplateTuple<($($template,)*)> {
360            type Output = ($($template::Output,)*);
361            fn build_template(&self, _context: &mut TemplateContext) -> Result<Self::Output> {
362                #[allow(
363                    non_snake_case,
364                    reason = "The names of these variables are provided by the caller, not by us."
365                )]
366                let ($($template,)*) = &self.0;
367                Ok(($($template.build_template(_context)?,)*))
368            }
369
370            fn clone_template(&self) -> Self {
371                #[allow(
372                    non_snake_case,
373                    reason = "The names of these variables are provided by the caller, not by us."
374                )]
375                let ($($template,)*) = &self.0;
376                TemplateTuple(($($template.clone_template(),)*))
377            }
378        }
379    }
380}
381
382/// A wrapper over a tuple of [`Template`] implementations, which also implements [`Template`]. This exists because [`Template`] cannot
383/// be directly implemented for tuples of [`Template`] implementations.
384pub struct TemplateTuple<T>(pub T);
385
386all_tuples!(template_impl, 0, 12, T);
387
388// This includes `Unpin` to enable specialization for Templates that also implement Default, by using the
389// ["auto trait specialization" trick](https://github.com/coolcatcoder/rust_techniques/issues/1)
390impl<T: Clone + Default + Unpin> Template for T {
391    type Output = T;
392
393    fn build_template(&self, _context: &mut TemplateContext) -> Result<Self::Output> {
394        Ok(self.clone())
395    }
396
397    fn clone_template(&self) -> Self {
398        self.clone()
399    }
400}
401
402// This includes `Unpin` to enable specialization for Templates that also implement Default, by using the
403// ["auto trait specialization" trick](https://github.com/coolcatcoder/rust_techniques/issues/1)
404impl<T: Clone + Default + Unpin> FromTemplate for T {
405    type Template = T;
406}
407
408/// This is used to help improve error messages related to [`FromTemplate`] specialization. Developers should generally just ignore
409/// this trait and read the error message when they encounter it.
410#[diagnostic::on_unimplemented(
411    message = "This type does not manually implement FromTemplate, and it must. If you are deriving FromTemplate and you see this, it is likely because \
412               a field does not have a FromTemplate impl. This can usually be fixed by using a custom template for that field. \
413               Ex: for an Option<Handle<Image>> field, annotate the field with `#[template(OptionTemplate<HandleTemplate<Image>>)]`",
414    note = "FromTemplate currently uses pseudo-specialization to enable FromTemplate to override Default. This error message is a consequence of t."
415)]
416pub trait SpecializeFromTemplate: Sized {}
417
418/// A [`Template`] reference to an [`Entity`].
419///
420/// This is only valid during scene spawning and should **never** be used as a [`Component`](bevy_ecs::prelude::Component) field.
421#[derive(Copy, Clone, Default, Debug)]
422pub enum EntityTemplate {
423    /// A reference to a specific [`Entity`]
424    Entity(Entity),
425    /// A reference to an entity via a unique reference
426    SceneEntityReference(SceneEntityReference),
427    /// An entity has not been specified. Building a template with this variant will result in an error.
428    #[default]
429    None,
430}
431impl Unpin for EntityTemplate where for<'a> [()]: SpecializeFromTemplate {}
432
433impl EntityTemplate {
434    /// Create a [`EntityTemplate::SceneEntityReference`] from the data needed for [`SceneEntityReference`]
435    pub fn from_reference(
436        invocation: (&'static str, usize, usize),
437        name_id: usize,
438        runtime: u64,
439    ) -> Self {
440        Self::SceneEntityReference(SceneEntityReference::new(invocation, name_id, runtime))
441    }
442}
443
444impl From<Entity> for EntityTemplate {
445    fn from(entity: Entity) -> Self {
446        Self::Entity(entity)
447    }
448}
449
450impl Template for EntityTemplate {
451    type Output = Entity;
452
453    fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
454        Ok(match self {
455            Self::Entity(entity) => *entity,
456            Self::SceneEntityReference(reference) => context.get_entity(*reference),
457            Self::None => {
458                return Err(BevyError::error(
459                    "Failed to specify an entity for this EntityTemplate",
460                ))
461            }
462        })
463    }
464
465    fn clone_template(&self) -> Self {
466        match self {
467            Self::Entity(entity) => Self::Entity(*entity),
468            Self::SceneEntityReference(reference) => Self::SceneEntityReference(*reference),
469            Self::None => Self::None,
470        }
471    }
472}
473
474impl FromTemplate for Entity {
475    type Template = EntityTemplate;
476}
477
478/// A [`Template`] driven by a function that returns an output. This is used to create "free floating" templates without
479/// defining a new type. See [`template`] for usage.
480pub struct FnTemplate<F: Fn(&mut TemplateContext) -> Result<O>, O>(pub F);
481
482impl<F: Fn(&mut TemplateContext) -> Result<O> + Clone, O> Template for FnTemplate<F, O> {
483    type Output = O;
484
485    fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
486        (self.0)(context)
487    }
488
489    fn clone_template(&self) -> Self {
490        Self(self.0.clone())
491    }
492}
493
494/// Returns a "free floating" template for a given `func`. This prevents the need to define a custom type for one-off templates.
495pub fn template<F: Fn(&mut TemplateContext) -> Result<O>, O>(func: F) -> FnTemplate<F, O> {
496    FnTemplate(func)
497}
498
499/// Roughly equivalent to [`FromTemplate`], but does not have a blanket implementation for [`Default`] + [`Clone`] types.
500/// This is generally used for common generic collection types like [`Option`] and [`Vec`], which have [`Default`] + [`Clone`] impls and
501/// therefore also pick up the [`FromTemplate`] behavior. This is fine when the `T` in [`Option<T>`] is not "templated"
502/// (ex: does not have an explicit [`FromTemplate`] derive). But if `T` is "templated", such as [`Option<Handle<T>>`], then it would require
503/// a manual `#[template(OptionTemplate<HandleTemplate<T>>)]` field annotation. This isn't fun to type out.
504///
505/// [`BuiltInTemplate`] enables equivalent "template type inference", by annotating a field with a type that implements [`BuiltInTemplate`] with
506/// `#[template(built_in)]`.
507pub trait BuiltInTemplate: Sized {
508    /// The template to consider the "built in" template for this type.
509    type Template: Template;
510}
511
512impl<T: FromTemplate> BuiltInTemplate for Option<T> {
513    type Template = OptionTemplate<T::Template>;
514}
515
516impl<T: FromTemplate> BuiltInTemplate for Vec<T> {
517    type Template = VecTemplate<T::Template>;
518}
519
520/// A [`Template`] for [`Option`].
521#[derive(Default)]
522pub enum OptionTemplate<T> {
523    /// Template of [`Option::Some`].
524    Some(T),
525    /// Template of [`Option::None`].
526    #[default]
527    None,
528}
529
530impl<T> From<Option<T>> for OptionTemplate<T> {
531    fn from(value: Option<T>) -> Self {
532        match value {
533            Some(value) => OptionTemplate::Some(value),
534            None => OptionTemplate::None,
535        }
536    }
537}
538
539impl<T> From<T> for OptionTemplate<T> {
540    fn from(value: T) -> Self {
541        OptionTemplate::Some(value)
542    }
543}
544
545impl<T: Template> Template for OptionTemplate<T> {
546    type Output = Option<T::Output>;
547
548    fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
549        Ok(match &self {
550            OptionTemplate::Some(template) => Some(template.build_template(context)?),
551            OptionTemplate::None => None,
552        })
553    }
554
555    fn clone_template(&self) -> Self {
556        match self {
557            OptionTemplate::Some(value) => OptionTemplate::Some(value.clone_template()),
558            OptionTemplate::None => OptionTemplate::None,
559        }
560    }
561}
562
563/// A [`Template`] for [`Vec`].
564pub struct VecTemplate<T>(pub Vec<T>);
565
566impl<T> Default for VecTemplate<T> {
567    fn default() -> Self {
568        Self(Vec::new())
569    }
570}
571
572impl<T: Template> Template for VecTemplate<T> {
573    type Output = Vec<T::Output>;
574
575    fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
576        let mut output = Vec::with_capacity(self.0.len());
577        for value in &self.0 {
578            output.push(value.build_template(context)?);
579        }
580        Ok(output)
581    }
582
583    fn clone_template(&self) -> Self {
584        VecTemplate(self.0.iter().map(Template::clone_template).collect())
585    }
586}
587
588#[cfg(test)]
589mod tests {
590    use crate::prelude::*;
591    use alloc::string::{String, ToString};
592
593    #[test]
594    fn option_template() {
595        #[derive(FromTemplate)]
596        struct Handle(String);
597
598        #[derive(FromTemplate)]
599        struct Foo {
600            #[template(built_in)]
601            handle: Option<Handle>,
602        }
603
604        let mut world = World::new();
605        let foo_template = FooTemplate {
606            handle: Some(HandleTemplate("handle_path".to_string())).into(),
607        };
608        let foo = world.spawn_empty().build_template(&foo_template).unwrap();
609        assert_eq!(foo.handle.unwrap().0, "handle_path".to_string());
610    }
611}