intuicio_framework_ecs/
entity.rs1use intuicio_core::{registry::Registry, IntuicioStruct};
2use intuicio_derive::*;
3use serde::{Deserialize, Serialize};
4
5#[derive(
7 IntuicioStruct, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
8)]
9#[intuicio(module_name = "ecs_entity")]
10pub struct Entity {
11 #[intuicio(ignore)]
12 pub(crate) id: u32,
13 #[intuicio(ignore)]
14 pub(crate) generation: u32,
15}
16
17impl Default for Entity {
18 fn default() -> Self {
19 Self::INVALID
20 }
21}
22
23#[intuicio_methods(module_name = "ecs_entity")]
24impl Entity {
25 pub const INVALID: Self = unsafe { Self::new_unchecked(u32::MAX, 0) };
26
27 pub const fn new(id: u32, generation: u32) -> Option<Self> {
28 if id < u32::MAX {
29 Some(Self { id, generation })
30 } else {
31 None
32 }
33 }
34
35 pub const unsafe fn new_unchecked(id: u32, generation: u32) -> Self {
37 Self { id, generation }
38 }
39
40 #[intuicio_method()]
41 pub const fn is_valid(self) -> bool {
42 self.id < u32::MAX
43 }
44
45 #[intuicio_method()]
46 pub const fn id(self) -> u32 {
47 self.id
48 }
49
50 #[intuicio_method()]
51 pub const fn generation(self) -> u32 {
52 self.generation
53 }
54
55 #[intuicio_method()]
56 pub const fn to_u64(self) -> u64 {
57 ((self.generation as u64) << 32) | self.id as u64
58 }
59
60 #[intuicio_method()]
61 pub const fn from_u64(value: u64) -> Self {
62 Self {
63 generation: (value >> 32) as u32,
64 id: value as u32,
65 }
66 }
67
68 pub(crate) const fn bump_generation(mut self) -> Self {
69 self.generation = self.generation.wrapping_add(1);
70 self
71 }
72}
73
74impl std::fmt::Display for Entity {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 write!(f, "@{}:#{}", self.id, self.generation)
77 }
78}
79
80impl Entity {
81 pub fn install(registry: &mut Registry) {
82 registry.add_type(Self::define_struct(registry));
83 registry.add_function(Self::is_valid__define_function(registry));
84 registry.add_function(Self::id__define_function(registry));
85 registry.add_function(Self::generation__define_function(registry));
86 registry.add_function(Self::to_u64__define_function(registry));
87 registry.add_function(Self::from_u64__define_function(registry));
88 }
89}
90
91#[derive(Debug, Default, Clone, PartialEq, Eq)]
92pub struct EntityDenseMap {
93 inner: Vec<Entity>,
94}
95
96impl EntityDenseMap {
97 pub fn with_capacity(mut capacity: usize) -> Self {
98 capacity = capacity.next_power_of_two().max(1);
99 Self {
100 inner: Vec::with_capacity(capacity),
101 }
102 }
103
104 pub fn clear(&mut self) {
105 self.inner.clear();
106 }
107
108 pub fn insert(&mut self, entity: Entity) -> Result<usize, usize> {
109 if let Some(index) = self.index_of(entity) {
110 Err(index)
111 } else {
112 if self.inner.len() == self.inner.capacity() {
113 self.inner.reserve_exact(self.inner.capacity());
114 }
115 let index = self.inner.len();
116 self.inner.push(entity);
117 Ok(index)
118 }
119 }
120
121 pub fn remove(&mut self, entity: Entity) -> Option<usize> {
122 let index = self.index_of(entity)?;
123 self.inner.swap_remove(index);
124 if self.inner.len() == self.inner.capacity() / 2 {
125 self.inner.shrink_to_fit();
126 }
127 Some(index)
128 }
129
130 pub fn contains(&self, entity: Entity) -> bool {
131 self.inner.contains(&entity)
132 }
133
134 pub fn index_of(&self, entity: Entity) -> Option<usize> {
135 self.inner.iter().position(|e| *e == entity)
136 }
137
138 pub fn get(&self, index: usize) -> Option<Entity> {
139 self.inner.get(index).copied()
140 }
141
142 pub fn iter(&self) -> impl Iterator<Item = Entity> + '_ {
143 self.inner.iter().copied()
144 }
145}