examples/relationships/
relationships_enum.rs

1use crate::z_ignore_test_common::*;
2
3use flecs_ecs::prelude::*;
4// When an enumeration constant is added to an entity, it is added as a relationship
5// pair where the relationship is the enum type, and the target is the constant. For
6// example, this statement:
7//   e.add(Color::Red)
8//
9// adds this relationship:
10//   (Color, Color::Red)
11//
12// Enums are registered as exclusive relationships, which means that adding an
13// enum constant will replace the previous constant for that enumeration:
14//   e.add(Color::Green)
15//
16//  will replace Color::Red with Color::Green
17
18//Regular C style enumerations are supported
19//   rust style enum variants are not supported *yet* due to limitations in C flecs lib
20//   where it expects each enum field to be 4 bytes.
21//   I plan on adding support for rust style enums in the future.
22#[derive(Component, Debug, PartialEq)]
23#[repr(C)]
24enum Tile {
25    Grass,
26    Sand,
27    Stone,
28}
29
30#[derive(Component)]
31#[repr(C)]
32enum TileStatus {
33    Free,
34    Occupied,
35}
36
37fn main() {
38    let world = World::new();
39
40    // Create an entity with (Tile, Red) and (TileStatus, Free) relationships
41    let tile = world
42        .entity()
43        .add_enum(Tile::Stone)
44        .add_enum(TileStatus::Free);
45
46    // (Tile, Tile.Stone), (TileStatus, TileStatus.Free)
47    println!("{:?}", tile.archetype());
48
49    // Replace (TileStatus, Free) with (TileStatus, Occupied)
50    tile.add_enum(TileStatus::Occupied);
51
52    // (Tile, Tile.Stone), (TileStatus, TileStatus.Occupied)
53    println!("{:?}", tile.archetype());
54
55    println!();
56
57    // Check if the entity has the Tile relationship and the Tile::Stone pair
58    println!("has tile enum: {}", tile.has::<Tile>()); // true
59    println!(
60        "is the enum from tile stone?: {}",
61        tile.has_enum(Tile::Stone)
62    ); // true
63
64    // Get the current value of the enum
65    tile.try_get::<&Tile>(|tile| {
66        println!("is tile stone: {}", *tile == Tile::Stone); // true
67    });
68
69    // Create a few more entities that we can query
70    world
71        .entity()
72        .add_enum(Tile::Grass)
73        .add_enum(TileStatus::Free);
74
75    world
76        .entity()
77        .add_enum(Tile::Sand)
78        .add_enum(TileStatus::Occupied);
79
80    println!();
81
82    // Iterate all entities with a Tile relationship
83    world
84        .query::<()>()
85        .with_enum_wildcard::<&Tile>()
86        .build()
87        .each_iter(|it, _, _| {
88            let pair = it.pair(0).unwrap();
89            let tile_constant = pair.second_id();
90            println!("{}", tile_constant.path().unwrap());
91        });
92
93    // Output:s:
94    //  ::Tile::Stone
95    //  ::Tile::Grass
96    //  ::Tile::Sand
97
98    println!();
99
100    // Iterate only occupied tiles
101    world
102        .query::<()>()
103        .with_enum_wildcard::<&Tile>()
104        .with_enum(TileStatus::Occupied)
105        .build()
106        .each_iter(|it, _, _| {
107            let pair = it.pair(0).unwrap();
108            let tile_constant = pair.second_id();
109            println!("{}", tile_constant.path().unwrap());
110        });
111
112    // Output:s:
113    //  ::Tile::Stone
114    //  ::Tile::Sand
115
116    println!();
117
118    // Remove any instance of the TileStatus relationship
119    tile.remove::<TileStatus>();
120
121    // (Tile, Tile.Stone)
122    println!("{:?}", tile.archetype());
123
124    // Total Output:
125    //  (relationships_enum.Tile,relationships_enum.Tile.Stone), (relationships_enum.TileStatus,relationships_enum.TileStatus.Free)
126    //  (relationships_enum.Tile,relationships_enum.Tile.Stone), (relationships_enum.TileStatus,relationships_enum.TileStatus.Occupied)
127    //
128    //  has tile enum: true
129    //  is the enum from tile stone?: true
130    //  is tile stone: true
131    //
132    //  ::relationships_enum::Tile::Stone
133    //  ::relationships_enum::Tile::Grass
134    //  ::relationships_enum::Tile::Sand
135    //
136    //  ::relationships_enum::Tile::Stone
137    //  ::relationships_enum::Tile::Sand
138    //
139    //  (relationships_enum.Tile,relationships_enum.Tile.Stone)
140}
141
142#[cfg(feature = "flecs_nightly_tests")]
143#[test]
144#[ignore = "is a hierarchy traversal not supported with new get callback"]
145fn test() {
146    let output_capture = OutputCapture::capture().unwrap();
147    main();
148    output_capture.test("relationships_enum".to_string());
149}