examples/systems/
system_mutate_entity_handle.rs

1use crate::z_ignore_test_common::*;
2
3use flecs_ecs::prelude::*;
4// This example is the same as the mutate_entity example, but instead stores the
5// handle of the to be deleted entity in a component.
6
7#[derive(Component)]
8struct Timeout {
9    pub to_delete: Entity,
10    pub value: f32,
11}
12
13#[derive(Component)]
14pub struct Tag;
15
16fn main() {
17    let world = World::new();
18
19    // System that deletes an entity after a timeout expires
20    world
21        .system::<&mut Timeout>()
22        .each_iter(|it, _index, timeout| {
23            timeout.value -= it.delta_time();
24            if timeout.value <= 0.0 {
25                // Delete the entity
26
27                // To make sure the delete operation is enqueued (see
28                // mutate_entity example for more details) we need to provide it
29                // with a mutable context (stage) using the mut() function. If
30                // we don't provide a mutable context, the operation will be
31                // attempted on the context stored in the flecs::entity object,
32                // which would throw a readonly error.
33
34                // To catch these errors at compile time, replace the type of
35                // to_delete with flecs::entity_view. This class does not have
36                // any methods for mutating the entity, which forces the code to
37                // first call mut().
38
39                // The it.world() function can be used to provide the context:
40                //   t.to_delete.mut(it.world()).destruct();
41                //
42                // The current entity can also be used to provide context. This
43                // is useful for functions that accept a flecs::entity:
44                //   t.to_delete.mut(it.entity(index)).destruct();
45                //
46                // A shortcut is to use the iterator directly:
47                let world = it.world();
48                let to_delete = world.get_alive(timeout.to_delete);
49                println!("Expire: {} deleted!", to_delete.name());
50                to_delete.destruct();
51            }
52        });
53
54    // System that prints remaining expiry time
55    world.system::<&Timeout>().each_entity(|e, timeout| {
56        let world = e.world();
57        let to_delete = world.get_alive(timeout.to_delete);
58        println!(
59            "PrintExpire: {} has {:.2} seconds left",
60            to_delete.name(),
61            timeout.value
62        );
63    });
64
65    // Observer that triggers when entity is actually deleted
66    world
67        .observer::<flecs::OnRemove, &Tag>()
68        .each_entity(|e, _tag| {
69            println!("Expired: {} actually deleted", e.name());
70        });
71
72    let to_delete = world.entity_named("ToDelete").add::<Tag>();
73
74    world.entity_named("MyEntity").set(Timeout {
75        to_delete: to_delete.id(),
76        value: 2.5,
77    });
78
79    world.set_target_fps(1.0);
80
81    while world.progress() {
82        // If entity is no longer alive, exit
83        if !to_delete.is_alive() {
84            break;
85        }
86
87        println!("Tick...");
88    }
89
90    // Output:
91    //  PrintExpire: ToDelete has 2.00 seconds left
92    //  Tick...
93    //  PrintExpire: ToDelete has 0.98 seconds left
94    //  Tick...
95    //  Expire: ToDelete deleted!
96    //  PrintExpire: ToDelete has -0.03 seconds left
97    //  Expired: ToDelete actually deleted
98}
99
100#[cfg(feature = "flecs_nightly_tests")]
101#[test]
102fn test() {
103    let output_capture = OutputCapture::capture().unwrap();
104    main();
105    assert!(output_capture.output_string().contains("deleted"));
106}