Skip to main content

FromTemplate

Trait FromTemplate 

Source
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§

Source

type Template: Template<Output = Self>

The Template for this type.

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.

Implementors§