pub trait FromTemplate: Sized {
type Template: Template<Output = Self>;
}Expand description
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
desired template output type. This is used by Bevy’s scene system.
Both FromTemplate and Template are blanket implemented for types that implement Default and Clone, meaning most types you would want to use
already have templates.
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
impl, you cannot implement FromTemplate, Default, and Clone together on the same type, as it would result in two conflicting FromTemplate impls.
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).
You can and should prefer deriving Default and Clone instead of an explicit FromTemplate impl, unless your type uses something that requires (or uses)
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
to derive FromTemplate.
FromTemplate can be derived for types whose fields also implement FromTemplate:
#[derive(FromTemplate)]
struct Player {
image: Handle<Image>
}Deriving FromTemplate will generate a Template type for the deriving type. The example above would generate a PlayerTemplate like this:
struct Player {
image: Handle<Image>
}
impl FromTemplate for Player {
type Template = PlayerTemplate;
}
struct PlayerTemplate {
image: HandleTemplate<Image>,
}
impl Template for PlayerTemplate {
type Output = Player;
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
Ok(Player {
image: self.image.build_template(context)?,
})
}
fn clone_template(&self) -> Self {
PlayerTemplate {
image: self.image.clone_template(),
}
}
}FromTemplate derives can specify custom templates to use instead of a canonical FromTemplate:
#[derive(FromTemplate)]
struct Counter {
#[template(Always10)]
count: usize
}
#[derive(Default)]
struct Always10;
impl Template for Always10 {
type Output = usize;
fn build_template(&self, context: &mut TemplateContext) -> Result<Self::Output> {
Ok(10)
}
fn clone_template(&self) -> Self {
Always10
}
}FromTemplate is automatically implemented for anything that is Default and Clone. “Built in” collection types like
Option and Vec pick up this “blanket” implementation, which is generally a good thing because it means these collection
types work with FromTemplate derives by default. However if the items in the collection have a custom FromTemplate impl
(ex: a manual implementation like Handle<T> for assets or an explicit FromTemplate derive), then relying on a Default /
Clone implementation doesn’t work, as that won’t run the template logic!
Therefore, cases like Option<Handle<T>> need something other than FromTemplate to determine the type. One option is to specify
the template manually:
#[derive(FromTemplate)]
struct Widget {
#[template(OptionTemplate<HandleTemplate<Image>>)]
image: Option<Handle<Image>>
}However that is a bit of a mouthful! This is where BuiltInTemplate comes in. It fills the same role
as FromTemplate, but has no blanket implementation for Default and Clone, meaning we can have
custom implementations for types like Option and Vec.
If you are deriving FromTemplate and you have a “built in” type like Option<Handle<T>> which has custom template logic,
annotate it with the template(built_in) attribute to use BuiltInTemplate instead of FromTemplate:
#[derive(FromTemplate)]
struct Widget {
#[template(built_in)]
image: Option<Handle<Image>>
}Required Associated Types§
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.