euv_engine/entity/impl.rs
1use super::*;
2
3/// Implements static factory and ID generation methods for `Entity`.
4impl Entity {
5 /// Generates the next unique entity ID using a global atomic counter.
6 ///
7 /// # Returns
8 ///
9 /// - `u64` - The next unique ID.
10 pub fn generate_id() -> u64 {
11 NEXT_ENTITY_ID.fetch_add(1, Ordering::Relaxed)
12 }
13
14 /// Creates a new entity with the given name and a default identity transform.
15 ///
16 /// Creates a new entity with the given name and a default identity transform.
17 ///
18 /// # Arguments
19 ///
20 /// - `N: AsRef<str>` - The name of the entity.
21 ///
22 /// # Returns
23 ///
24 /// - `Entity` - The newly created entity.
25 pub fn create<N>(name: N) -> Entity
26 where
27 N: AsRef<str>,
28 {
29 Entity::new(
30 Self::generate_id(),
31 name.as_ref().to_string(),
32 Transform2D::identity(),
33 true,
34 Vec::new(),
35 Vec::new(),
36 )
37 }
38
39 /// Creates a new entity at the specified position with a default name.
40 ///
41 /// # Arguments
42 ///
43 /// - `Vector2D` - The initial position.
44 ///
45 /// # Returns
46 ///
47 /// - `Entity` - The newly created entity.
48 pub fn create_at(position: Vector2D) -> Entity {
49 let mut entity: Entity = Self::create(DEFAULT_ENTITY_NAME);
50 entity.get_mut_transform().set_position(position);
51 entity
52 }
53}
54
55/// Implements lifecycle and component management methods for `Entity`.
56impl Entity {
57 /// Adds a component to this entity and calls its `on_start` lifecycle method.
58 ///
59 /// # Arguments
60 ///
61 /// - `ComponentRc` - The component to add.
62 pub fn add_component(&mut self, component: ComponentRc) {
63 component.get_mut().on_start();
64 self.get_mut_components().push(component);
65 }
66
67 /// Removes the first component matching the given name.
68 ///
69 /// # Arguments
70 ///
71 /// - `&str` - The component name to match.
72 ///
73 /// # Returns
74 ///
75 /// - `Option<ComponentRc>` - The removed component, if found.
76 pub fn remove_component_by_name<N>(&mut self, name: N) -> Option<ComponentRc>
77 where
78 N: AsRef<str>,
79 {
80 let target: &str = name.as_ref();
81 let position: Option<usize> = self
82 .get_components()
83 .iter()
84 .position(|component: &ComponentRc| component.get().name() == target);
85 let index: usize = position?;
86 let removed: ComponentRc = self.get_mut_components().remove(index);
87 removed.get_mut().on_destroy();
88 Some(removed)
89 }
90
91 /// Returns the first component matching the given name.
92 ///
93 /// # Arguments
94 ///
95 /// - `&str` - The component name to match.
96 ///
97 /// # Returns
98 ///
99 /// - `Option<ComponentRc>` - The matching component, if found.
100 pub fn get_component_by_name<N>(&self, name: N) -> Option<ComponentRc>
101 where
102 N: AsRef<str>,
103 {
104 let target: &str = name.as_ref();
105 self.get_components()
106 .iter()
107 .find(|component: &&ComponentRc| component.get().name() == target)
108 .cloned()
109 }
110
111 /// Calls `on_update` on all active components.
112 ///
113 /// # Arguments
114 ///
115 /// - `f64` - The delta time in seconds.
116 pub fn update(&mut self, delta_time: f64) {
117 if !self.get_active() {
118 return;
119 }
120 for component in self.get_components() {
121 component.get_mut().on_update(delta_time);
122 }
123 }
124
125 /// Calls `on_render` on all active components, recording into the draw list.
126 ///
127 /// # Arguments
128 ///
129 /// - `&mut DrawList` - The draw list to record commands into.
130 pub fn render(&self, draw_list: &mut DrawList) {
131 if !self.get_active() {
132 return;
133 }
134 let transform: Transform2D = self.get_transform();
135 for component in self.get_components() {
136 component.get_mut().on_render(draw_list, &transform);
137 }
138 }
139
140 /// Calls `on_destroy` on all components and clears the component list.
141 pub fn destroy(&mut self) {
142 for component in self.get_components() {
143 component.get_mut().on_destroy();
144 }
145 self.get_mut_components().clear();
146 }
147
148 /// Adds a tag string to this entity.
149 ///
150 /// # Arguments
151 ///
152 /// - `String` - The tag to add.
153 pub fn add_tag(&mut self, tag: String) {
154 if !self.get_tags().contains(&tag) {
155 self.get_mut_tags().push(tag);
156 }
157 }
158
159 /// Tests whether this entity has the given tag.
160 ///
161 /// # Arguments
162 ///
163 /// - `&str` - The tag to check.
164 ///
165 /// # Returns
166 ///
167 /// - `bool` - True if the tag is present.
168 pub fn has_tag<T>(&self, tag: T) -> bool
169 where
170 T: AsRef<str>,
171 {
172 let target: &str = tag.as_ref();
173 self.get_tags().iter().any(|t: &String| t == target)
174 }
175}
176
177/// Forwards `Entity::update` through the [`Updatable`] trait so that collections
178/// of heterogeneous updateable objects can be driven by the scheduler.
179///
180/// The inherent [`Entity::update`] method is the canonical implementation;
181/// this impl exists purely for trait dispatch. The inherent call resolves
182/// first when both are in scope, so there is no recursion.
183impl Updatable for Entity {
184 fn update(&mut self, delta_time: f64) {
185 Entity::update(self, delta_time);
186 }
187}
188
189/// Implements event subscription, emission, and management for `EventBus`.
190impl EventBus {
191 /// Creates a new empty event bus.
192 ///
193 /// # Returns
194 ///
195 /// - `EventBus` - The new event bus.
196 pub fn create() -> EventBus {
197 EventBus::new()
198 }
199
200 /// Subscribes a handler to the named event channel.
201 ///
202 /// # Arguments
203 ///
204 /// - `String` - The event name to subscribe to.
205 /// - `EventHandler` - The handler closure to call when the event is emitted.
206 pub fn subscribe(&mut self, event_name: String, handler: EventHandler) {
207 self.get_mut_handlers()
208 .entry(event_name)
209 .or_default()
210 .push(handler);
211 }
212
213 /// Emits an event to all handlers subscribed to the matching channel.
214 ///
215 /// The event name is derived from the `EntityEvent` variant.
216 ///
217 /// # Arguments
218 ///
219 /// - `&EntityEvent` - The event to emit.
220 pub fn emit(&self, event: &EntityEvent) {
221 let event_name: String = Self::event_name(event);
222 if let Some(handlers) = self.get_handlers().get(&event_name) {
223 for handler in handlers {
224 handler(event);
225 }
226 }
227 }
228
229 /// Removes all handlers for the named event channel.
230 ///
231 /// # Arguments
232 ///
233 /// - `E: AsRef<str>` - The event name to clear.
234 pub fn unsubscribe_all<E>(&mut self, event_name: E)
235 where
236 E: AsRef<str>,
237 {
238 self.get_mut_handlers().remove(event_name.as_ref());
239 }
240
241 /// Returns the number of handlers registered for the named event.
242 ///
243 /// # Arguments
244 ///
245 /// - `&str` - The event name.
246 ///
247 /// # Returns
248 ///
249 /// - `usize` - The handler count.
250 pub fn handler_count<E>(&self, event_name: E) -> usize
251 where
252 E: AsRef<str>,
253 {
254 self.get_handlers()
255 .get(event_name.as_ref())
256 .map(|handlers: &Vec<EventHandler>| handlers.len())
257 .unwrap_or(0)
258 }
259
260 /// Derives the event channel name from an `EntityEvent` variant.
261 ///
262 /// # Arguments
263 ///
264 /// - `&EntityEvent` - The event.
265 ///
266 /// # Returns
267 ///
268 /// - `String` - The channel name.
269 fn event_name(event: &EntityEvent) -> String {
270 match event {
271 EntityEvent::Collision { .. } => "collision".to_string(),
272 EntityEvent::TriggerEnter { .. } => "trigger_enter".to_string(),
273 EntityEvent::TriggerExit { .. } => "trigger_exit".to_string(),
274 EntityEvent::Spawn => "spawn".to_string(),
275 EntityEvent::Destroy => "destroy".to_string(),
276 EntityEvent::Custom { name, .. } => name.clone(),
277 }
278 }
279}
280
281/// Implements `Default` for `EventBus` as a new empty bus.
282impl Default for EventBus {
283 fn default() -> EventBus {
284 EventBus::create()
285 }
286}