examples/prefabs/prefab_override.rs
1use crate::z_ignore_test_common::*;
2
3use flecs_ecs::prelude::*;
4
5// When an entity is instantiated from a prefab, components are by default
6// copied from the prefab to the instance. This behavior can be customized with
7// the OnInstantiate trait, which has three options:
8//
9// - Override (copy to instance)
10// - Inherit (inherit from prefab)
11// - DontInherit (don't copy or inherit)
12//
13// When a component is inheritable, it can be overridden manually by adding the
14// component to the instance, which also copies the value from the prefab
15// component. Additionally, when creating a prefab it is possible to flag a
16// component as "auto override", which can change the behavior for a specific
17// prefab from "inherit" to "override".
18//
19// This example shows how these different features can be used.
20
21#[derive(Component, Clone)]
22pub struct Attack {
23 pub value: f32,
24}
25
26#[derive(Component, Debug, Clone)]
27pub struct Defence {
28 pub value: f32,
29}
30
31#[derive(Component, Clone)]
32pub struct Damage {
33 pub value: f32,
34}
35
36fn main() {
37 let world = World::new();
38
39 // Add the traits to mark the components to be inherited
40 world
41 .component::<Defence>()
42 .add_trait::<(flecs::OnInstantiate, flecs::Inherit)>();
43 world
44 .component::<Attack>()
45 .add_trait::<(flecs::OnInstantiate, flecs::Inherit)>();
46
47 // Attack and Defense are properties that can be shared across many
48 // spaceships. This saves memory, and speeds up prefab creation as we don't
49 // have to copy the values of Attack and Defense to private components.
50 let spaceship = world
51 .prefab_named("SpaceShip")
52 .set(Attack { value: 75.0 })
53 .set(Defence { value: 100.0 })
54 .set(Damage { value: 50.0 });
55
56 // Create a prefab instance.
57 let inst = world.entity_named("my_spaceship").is_a(spaceship);
58
59 // The entity will now have a private copy of the Damage component, but not
60 // of the Attack and Defense components. We can see this when we look at the
61 // type of the instance:
62 println!("{}", inst.archetype());
63
64 // Even though Attack was not automatically overridden, we can always
65 // override it manually afterwards by adding it:
66 inst.override_type::<Attack>();
67
68 // The Attack component now shows up in the entity type:
69 println!("{}", inst.archetype());
70
71 // We can get all components on the instance, regardless of whether they
72 // are overridden or not. Note that the overridden components (Attack and
73 // Damage) are initialized with the values from the prefab component:
74 inst.try_get::<(&Attack, &Defence, &Damage)>(|(attack, defence, damage)| {
75 println!("attack: {}", attack.value);
76 println!("defence: {}", defence.value);
77 println!("damage: {}", damage.value);
78 });
79
80 // Output:
81 // Damage, (Identifier,Name), (IsA,SpaceShip)
82 // Attack, Damage, (Identifier,Name), (IsA,SpaceShip)
83 // attack: 75
84 // defence: 100
85 // damage: 50
86}
87
88#[cfg(feature = "flecs_nightly_tests")]
89#[test]
90fn test() {
91 let output_capture = OutputCapture::capture().unwrap();
92 main();
93 output_capture.test("prefab_override".to_string());
94}