//! Functionality that relates to the [`Template`] trait.12use core::{hash::Hash, ops::Deref};34pub use bevy_ecs_macros::FromTemplate;5use bevy_platform::{collections::hash_map::RawEntryMut, hash::Hashed};6use bevy_utils::PreHashMap;7use indexmap::Equivalent;89use crate::{10component::Mutable,11entity::Entity,12error::{BevyError, Result},13resource::Resource,14world::{EntityWorldMut, Mut, World},15};16use alloc::vec::Vec;17use variadics_please::all_tuples;1819/// 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, relative29/// 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`].34type Output;3536/// Uses this template and the given `entity` context to produce a [`Template::Output`].37fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output>;3839/// Clones this template. See [`Clone`].40fn clone_template(&self) -> Self;41}4243/// The context used to apply the current [`Template`]. This contains a reference to the entity that the template is being44/// applied to (via an [`EntityWorldMut`]).45pub struct TemplateContext<'a, 'w> {46/// The current entity the template is being applied to47pub entity: &'a mut EntityWorldMut<'w>,48/// A mapping of [`SceneEntityReference`] to [`Entity`] used for resolving `#Name` entity references49pub entity_references: &'a mut SceneEntityReferences,50}5152impl<'a, 'w> TemplateContext<'a, 'w> {53/// Creates a new [`TemplateContext`].54pub fn new(55entity: &'a mut EntityWorldMut<'w>,56entity_references: &'a mut SceneEntityReferences,57) -> Self {58Self {59entity,60entity_references,61}62}63/// Get the entity associated with the [`SceneEntityReference`], spawning a new one64/// if this is the first call with this index.65pub fn get_entity(&mut self, reference: SceneEntityReference) -> Entity {66self.entity_references.get(67reference,68// Safety: only used to create a new Entity69unsafe { self.entity.world_mut() },70)71}7273/// Retrieves a reference to the given resource `R`.74#[inline]75pub fn resource<R: Resource>(&self) -> &R {76self.entity.resource()77}7879/// Retrieves a mutable reference to the given resource `R`.80#[inline]81pub fn resource_mut<R: Resource<Mutability = Mutable>>(&mut self) -> Mut<'_, R> {82self.entity.resource_mut()83}8485/// Retrieves the entity associated with the given resource `R`, if it exists.86#[inline]87pub fn resource_entity<R: Resource>(&self) -> Option<Entity> {88self.entity.resource_entity::<R>()89}90}9192/// Struct to store a mapping from [`SceneEntityReference`] to [`Entity`]93/// which are used for resolving `#Name` entity references in bsn! macros94#[derive(Default)]95pub struct SceneEntityReferences(PreHashMap<InnerSceneEntityReference, Entity>);9697impl SceneEntityReferences {98/// Get the [`Entity`] associated with this [`SceneEntityReference`]99/// If the index is unknown, spawn a new empty [`Entity`] and store it100pub fn get(&mut self, reference: SceneEntityReference, world: &mut World) -> Entity {101let inner = reference.0;102let entry = self103.0104.raw_entry_mut()105.from_key_hashed_nocheck(inner.hash(), &inner);106match entry {107RawEntryMut::Occupied(entry) => *entry.get(),108RawEntryMut::Vacant(view) => {109let entity = world.spawn_empty().id();110view.insert_hashed_nocheck(inner.hash(), inner, entity);111entity112}113}114}115116/// Set the [`Entity`] associated with a [`SceneEntityReference`]117pub fn set(&mut self, reference: SceneEntityReference, entity: Entity) {118let inner = reference.0;119match self120.0121.raw_entry_mut()122.from_key_hashed_nocheck(inner.hash(), &inner)123{124RawEntryMut::Occupied(_) => {}125RawEntryMut::Vacant(view) => {126view.insert_hashed_nocheck(inner.hash(), inner, entity);127}128};129}130}131132/// A unique reference for a named entity in a scene.133/// Usually used by `bevy_scene` in generated code134///135/// Hashed here should allow implementing compile-time hashing in the future, and136/// encourage constant-folding until then137#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]138pub struct SceneEntityReference(Hashed<InnerSceneEntityReference>);139140/// The inner struct actually storing the unique index141#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]142pub struct InnerSceneEntityReference {143file: &'static str,144line: usize,145column: usize,146local: usize,147}148149impl SceneEntityReference {150/// Create a new [`SceneEntityReference`] from the invocation location and a local (per-macro) counter for names151pub fn new((file, line, column): (&'static str, usize, usize), local: usize) -> Self {152Self(Hashed::new(InnerSceneEntityReference {153file,154line,155column,156local,157}))158}159}160161impl core::fmt::Display for SceneEntityReference {162fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {163f.write_fmt(format_args!(164"global={}:{}:{} local={}",165self.file, self.line, self.column, self.local166))167}168}169170impl Deref for SceneEntityReference {171type Target = Hashed<InnerSceneEntityReference>;172173#[inline]174fn deref(&self) -> &Self::Target {175&self.0176}177}178179impl Equivalent<Hashed<InnerSceneEntityReference>> for SceneEntityReference {180#[inline]181fn equivalent(&self, key: &Hashed<InnerSceneEntityReference>) -> bool {182&self.0 == key183}184}185186/// [`FromTemplate`] is implemented for types that can be produced by a specific, canonical [`Template`]. This creates a way to correlate to the [`Template`] using the187/// desired template output type. This is used by Bevy's scene system.188///189/// Both [`FromTemplate`] and [`Template`] are blanket implemented for types that implement [`Default`] and [`Clone`], meaning most types you would want to use190/// _already have templates_.191///192/// 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 blanket193/// impl, you cannot implement [`FromTemplate`], [`Default`], and [`Clone`] together on the same type, as it would result in two conflicting [`FromTemplate`] impls.194/// 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).195///196/// You can _and should_ prefer deriving [`Default`] and [`Clone`] instead of an explicit [`FromTemplate`] impl, unless your type uses something that requires (or uses)197/// 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 want198/// to derive [`FromTemplate`].199///200/// [`FromTemplate`] can be derived for types whose fields _also_ implement [`FromTemplate`]:201/// ```202/// # use bevy_ecs::prelude::*;203/// # #[derive(Default, Clone)]204/// # struct Handle<T>(core::marker::PhantomData<T>);205/// # #[derive(Default, Clone)]206/// # struct Image;207/// #[derive(FromTemplate)]208/// struct Player {209/// image: Handle<Image>210/// }211/// ```212///213/// Deriving [`FromTemplate`] will generate a [`Template`] type for the deriving type. The example above would generate a `PlayerTemplate` like this:214/// ```215/// # use bevy_ecs::{prelude::*, template::TemplateContext};216/// # #[derive(FromTemplate)]217/// # struct Handle<T: core::marker::Unpin>(core::marker::PhantomData<T>);218/// # #[derive(Default, Clone)]219/// # struct Image;220/// struct Player {221/// image: Handle<Image>222/// }223///224/// impl FromTemplate for Player {225/// type Template = PlayerTemplate;226/// }227///228/// struct PlayerTemplate {229/// image: HandleTemplate<Image>,230/// }231///232/// impl Template for PlayerTemplate {233/// type Output = Player;234/// fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {235/// Ok(Player {236/// image: self.image.build_template(context)?,237/// })238/// }239///240/// fn clone_template(&self) -> Self {241/// PlayerTemplate {242/// image: self.image.clone_template(),243/// }244/// }245/// }246/// ```247///248/// [`FromTemplate`] derives can specify custom templates to use instead of a canonical [`FromTemplate`]:249/// ```250/// # use bevy_ecs::{prelude::*, template::TemplateContext};251/// # struct Image;252/// #[derive(FromTemplate)]253/// struct Counter {254/// #[template(Always10)]255/// count: usize256/// }257///258/// #[derive(Default)]259/// struct Always10;260///261/// impl Template for Always10 {262/// type Output = usize;263///264/// fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {265/// Ok(10)266/// }267///268/// fn clone_template(&self) -> Self {269/// Always10270/// }271/// }272/// ```273///274/// [`FromTemplate`] is automatically implemented for anything that is [`Default`] and [`Clone`]. "Built in" collection types like275/// [`Option`] and [`Vec`] pick up this "blanket" implementation, which is generally a good thing because it means these collection276/// types work with [`FromTemplate`] derives by default. However if the items in the collection have a custom [`FromTemplate`] impl277/// (ex: a manual implementation like `Handle<T>` for assets or an explicit [`FromTemplate`] derive), then relying on a [`Default`] /278/// [`Clone`] implementation doesn't work, as that won't run the template logic!279///280/// Therefore, cases like [`Option<Handle<T>>`] need something other than [`FromTemplate`] to determine the type. One option is to specify281/// the template manually:282///283/// ```284/// # use bevy_ecs::{prelude::*, template::{TemplateContext, OptionTemplate}};285/// # use core::marker::PhantomData;286/// # struct Handle<T>(PhantomData<T>);287/// # struct HandleTemplate<T>(PhantomData<T>);288/// # struct Image;289/// # impl<T> FromTemplate for Handle<T> {290/// # type Template = HandleTemplate<T>;291/// # }292/// # impl<T> Template for HandleTemplate<T> {293/// # type Output = Handle<T>;294/// # fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {295/// # unimplemented!()296/// # }297/// # fn clone_template(&self) -> Self {298/// # unimplemented!()299/// # }300/// # }301/// #[derive(FromTemplate)]302/// struct Widget {303/// #[template(OptionTemplate<HandleTemplate<Image>>)]304/// image: Option<Handle<Image>>305/// }306/// ```307///308/// However that is a bit of a mouthful! This is where [`BuiltInTemplate`] comes in. It fills the same role309/// as [`FromTemplate`], but has no blanket implementation for [`Default`] and [`Clone`], meaning we can have310/// custom implementations for types like [`Option`] and [`Vec`].311///312/// If you are deriving [`FromTemplate`] and you have a "built in" type like [`Option<Handle<T>>`] which has custom template logic,313/// annotate it with the `template(built_in)` attribute to use [`BuiltInTemplate`] instead of [`FromTemplate`]:314///315/// ```316/// # use bevy_ecs::{prelude::*, template::TemplateContext};317/// # use core::marker::PhantomData;318/// # struct Handle<T>(PhantomData<T>);319/// # struct HandleTemplate<T>(PhantomData<T>);320/// # struct Image;321/// # impl<T> FromTemplate for Handle<T> {322/// # type Template = HandleTemplate<T>;323/// # }324/// # impl<T> Template for HandleTemplate<T> {325/// # type Output = Handle<T>;326/// # fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {327/// # unimplemented!()328/// # }329/// # fn clone_template(&self) -> Self {330/// # unimplemented!()331/// # }332/// # }333/// #[derive(FromTemplate)]334/// struct Widget {335/// #[template(built_in)]336/// image: Option<Handle<Image>>337/// }338/// ```339pub trait FromTemplate: Sized {340/// The [`Template`] for this type.341type Template: Template<Output = Self>;342}343344macro_rules! template_impl {345($($template: ident),*) => {346#[expect(347clippy::allow_attributes,348reason = "This is a tuple-related macro; as such, the lints below may not always apply."349)]350impl<$($template: Template),*> Template for TemplateTuple<($($template,)*)> {351type Output = ($($template::Output,)*);352fn build_template(&self, _context: &mut TemplateContext) -> Result<Self::Output> {353#[allow(354non_snake_case,355reason = "The names of these variables are provided by the caller, not by us."356)]357let ($($template,)*) = &self.0;358Ok(($($template.build_template(_context)?,)*))359}360361fn clone_template(&self) -> Self {362#[allow(363non_snake_case,364reason = "The names of these variables are provided by the caller, not by us."365)]366let ($($template,)*) = &self.0;367TemplateTuple(($($template.clone_template(),)*))368}369}370}371}372373/// A wrapper over a tuple of [`Template`] implementations, which also implements [`Template`]. This exists because [`Template`] cannot374/// be directly implemented for tuples of [`Template`] implementations.375pub struct TemplateTuple<T>(pub T);376377all_tuples!(template_impl, 0, 12, T);378379// This includes `Unpin` to enable specialization for Templates that also implement Default, by using the380// ["auto trait specialization" trick](https://github.com/coolcatcoder/rust_techniques/issues/1)381impl<T: Clone + Default + Unpin> Template for T {382type Output = T;383384fn build_template(&self, _context: &mut TemplateContext) -> Result<Self::Output> {385Ok(self.clone())386}387388fn clone_template(&self) -> Self {389self.clone()390}391}392393// This includes `Unpin` to enable specialization for Templates that also implement Default, by using the394// ["auto trait specialization" trick](https://github.com/coolcatcoder/rust_techniques/issues/1)395impl<T: Clone + Default + Unpin> FromTemplate for T {396type Template = T;397}398399/// This is used to help improve error messages related to [`FromTemplate`] specialization. Developers should generally just ignore400/// this trait and read the error message when they encounter it.401#[diagnostic::on_unimplemented(402message = "This type does not manually implement FromTemplate, and it must. If you are deriving FromTemplate and you see this, it is likely because \403a field does not have a FromTemplate impl. This can usually be fixed by using a custom template for that field. \404Ex: for an Option<Handle<Image>> field, annotate the field with `#[template(OptionTemplate<HandleTemplate<Image>>)]`",405note = "FromTemplate currently uses pseudo-specialization to enable FromTemplate to override Default. This error message is a consequence of t."406)]407pub trait SpecializeFromTemplate: Sized {}408409/// A [`Template`] reference to an [`Entity`].410#[derive(Copy, Clone, Default, Debug)]411pub enum EntityTemplate {412/// A reference to a specific [`Entity`]413Entity(Entity),414/// A reference to an entity via a unique reference415SceneEntityReference(SceneEntityReference),416/// An entity has not been specified. Building a template with this variant will result in an error.417#[default]418None,419}420impl Unpin for EntityTemplate where for<'a> [()]: SpecializeFromTemplate {}421422impl From<Entity> for EntityTemplate {423fn from(entity: Entity) -> Self {424Self::Entity(entity)425}426}427428impl Template for EntityTemplate {429type Output = Entity;430431fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {432Ok(match self {433Self::Entity(entity) => *entity,434Self::SceneEntityReference(reference) => context.get_entity(*reference),435Self::None => {436return Err(BevyError::error(437"Failed to specify an entity for this EntityTemplate",438))439}440})441}442443fn clone_template(&self) -> Self {444match self {445Self::Entity(entity) => Self::Entity(*entity),446Self::SceneEntityReference(reference) => Self::SceneEntityReference(*reference),447Self::None => Self::None,448}449}450}451452impl FromTemplate for Entity {453type Template = EntityTemplate;454}455456/// A [`Template`] driven by a function that returns an output. This is used to create "free floating" templates without457/// defining a new type. See [`template`] for usage.458pub struct FnTemplate<F: Fn(&mut TemplateContext) -> Result<O>, O>(pub F);459460impl<F: Fn(&mut TemplateContext) -> Result<O> + Clone, O> Template for FnTemplate<F, O> {461type Output = O;462463fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {464(self.0)(context)465}466467fn clone_template(&self) -> Self {468Self(self.0.clone())469}470}471472/// Returns a "free floating" template for a given `func`. This prevents the need to define a custom type for one-off templates.473pub fn template<F: Fn(&mut TemplateContext) -> Result<O>, O>(func: F) -> FnTemplate<F, O> {474FnTemplate(func)475}476477/// Roughly equivalent to [`FromTemplate`], but does not have a blanket implementation for [`Default`] + [`Clone`] types.478/// This is generally used for common generic collection types like [`Option`] and [`Vec`], which have [`Default`] + [`Clone`] impls and479/// therefore also pick up the [`FromTemplate`] behavior. This is fine when the `T` in [`Option<T>`] is not "templated"480/// (ex: does not have an explicit [`FromTemplate`] derive). But if `T` is "templated", such as [`Option<Handle<T>>`], then it would require481/// a manual `#[template(OptionTemplate<HandleTemplate<T>>)]` field annotation. This isn't fun to type out.482///483/// [`BuiltInTemplate`] enables equivalent "template type inference", by annotating a field with a type that implements [`BuiltInTemplate`] with484/// `#[template(built_in)]`.485pub trait BuiltInTemplate: Sized {486/// The template to consider the "built in" template for this type.487type Template: Template;488}489490impl<T: FromTemplate> BuiltInTemplate for Option<T> {491type Template = OptionTemplate<T::Template>;492}493494impl<T: FromTemplate> BuiltInTemplate for Vec<T> {495type Template = VecTemplate<T::Template>;496}497498/// A [`Template`] for [`Option`].499#[derive(Default)]500pub enum OptionTemplate<T> {501/// Template of [`Option::Some`].502Some(T),503/// Template of [`Option::None`].504#[default]505None,506}507508impl<T> From<Option<T>> for OptionTemplate<T> {509fn from(value: Option<T>) -> Self {510match value {511Some(value) => OptionTemplate::Some(value),512None => OptionTemplate::None,513}514}515}516517impl<T> From<T> for OptionTemplate<T> {518fn from(value: T) -> Self {519OptionTemplate::Some(value)520}521}522523impl<T: Template> Template for OptionTemplate<T> {524type Output = Option<T::Output>;525526fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {527Ok(match &self {528OptionTemplate::Some(template) => Some(template.build_template(context)?),529OptionTemplate::None => None,530})531}532533fn clone_template(&self) -> Self {534match self {535OptionTemplate::Some(value) => OptionTemplate::Some(value.clone_template()),536OptionTemplate::None => OptionTemplate::None,537}538}539}540541/// A [`Template`] for [`Vec`].542pub struct VecTemplate<T>(pub Vec<T>);543544impl<T> Default for VecTemplate<T> {545fn default() -> Self {546Self(Vec::new())547}548}549550impl<T: Template> Template for VecTemplate<T> {551type Output = Vec<T::Output>;552553fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {554let mut output = Vec::with_capacity(self.0.len());555for value in &self.0 {556output.push(value.build_template(context)?);557}558Ok(output)559}560561fn clone_template(&self) -> Self {562VecTemplate(self.0.iter().map(Template::clone_template).collect())563}564}565566#[cfg(test)]567mod tests {568use crate::prelude::*;569use alloc::string::{String, ToString};570571#[test]572fn option_template() {573#[derive(FromTemplate)]574struct Handle(String);575576#[derive(FromTemplate)]577struct Foo {578#[template(built_in)]579handle: Option<Handle>,580}581582let mut world = World::new();583let foo_template = FooTemplate {584handle: Some(HandleTemplate("handle_path".to_string())).into(),585};586let foo = world.spawn_empty().build_template(&foo_template).unwrap();587assert_eq!(foo.handle.unwrap().0, "handle_path".to_string());588}589}590591592