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}