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}