Skip to main content

examples/relationships/
relationships_component_data.rs

1use crate::z_ignore_test_common::*;
2
3use flecs_ecs::prelude::*;
4
5// This example shows how relationships can be combined with components to attach
6// data to a relationship.
7
8// Some demo components:
9
10#[derive(Debug, Component, Default)]
11pub struct Position {
12    pub x: f32,
13    pub y: f32,
14}
15
16#[derive(Component)]
17pub struct Tag;
18
19#[derive(Component)]
20struct Requires {
21    amount: f32,
22}
23
24#[derive(Component)]
25struct Gigawatts;
26
27#[derive(Component)]
28struct Expires {
29    timeout: f32,
30}
31
32#[derive(Component)]
33struct MustHave;
34
35fn main() {
36    let world = World::new();
37
38    // When one element of a pair is a component and the other element is a tag,
39    // the pair assumes the type of the component.
40    let e1 = world
41        .entity()
42        .set_pair::<Requires, Gigawatts>(Requires { amount: 1.21 });
43
44    let require = e1.try_get::<Option<&(Requires, Gigawatts)>>(|req| {
45        if let Some((req)) = req {
46            println!("e1: requires: {}", req.amount);
47        } else {
48            println!("e1: does not have a relationship with Requires, Gigawatts");
49        }
50    });
51
52    // The component can be either the first or second part of a pair:
53    let e2 = world
54        .entity()
55        .set_pair::<Gigawatts, Requires>(Requires { amount: 1.5 });
56
57    let require = e2.try_get::<Option<&(Gigawatts, Requires)>>(|req| {
58        if let Some((req)) = req {
59            println!("e2: requires: {}", req.amount);
60        } else {
61            println!("e2: does not have a relationship with Gigawatts, Requires");
62        }
63    });
64
65    // Note that <Requires, Gigawatts> and <Gigawatts, Requires> are two
66    // different pairs, and can be added to an entity at the same time.
67
68    // If both parts of a pair are components, the pair assumes the type of
69    // the first element:
70    let e3 = world
71        .entity()
72        .set_pair::<Expires, Position>(Expires { timeout: 0.5 });
73
74    let expires = e3.try_get::<&(Expires, Position)>(|expires| {
75        println!("expires: {}", expires.timeout);
76    });
77
78    println!(
79        "{}",
80        world
81            .id_view_from((Requires::id(), Gigawatts))
82            .type_id()
83            .path()
84            .unwrap()
85    );
86    println!(
87        "{}",
88        world
89            .id_view_from((Gigawatts, Requires::id()))
90            .type_id()
91            .path()
92            .unwrap()
93    );
94    println!(
95        "{}",
96        world
97            .id_view_from((Expires::id(), Position::id()))
98            .type_id()
99            .path()
100            .unwrap()
101    );
102
103    // When querying for a relationship component, add the pair type as template
104    // argument to the builder:
105    let query = world.query::<&(Requires, Gigawatts)>().build();
106
107    query.each_entity(|entity, requires| {
108        println!("requires: {} gigawatts", requires.amount);
109    });
110
111    // Output:
112    // e1: requires: 1.21
113    // e1: requires: 1.5
114    // expires: 0.5
115    // ::Requires
116    // ::Requires
117    // ::Expires
118    // requires: 1.21 gigawatts
119}
120
121#[cfg(feature = "flecs_nightly_tests")]
122#[test]
123fn test() {
124    let output_capture = OutputCapture::capture().unwrap();
125    main();
126    // output_capture.test("relationships_component_data".to_string());
127}