euv_engine/entity/impl.rs
1use crate::*;
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 /// # Arguments
17 ///
18 /// - `&str` - The name of the entity.
19 ///
20 /// # Returns
21 ///
22 /// - `Entity` - The newly created entity.
23 pub fn create(name: &str) -> Entity {
24 Entity::new(
25 Self::generate_id(),
26 name.to_string(),
27 Transform2D::identity(),
28 true,
29 Vec::new(),
30 Vec::new(),
31 )
32 }
33
34 /// Creates a new entity at the specified position with a default name.
35 ///
36 /// # Arguments
37 ///
38 /// - `Vector2D` - The initial position.
39 ///
40 /// # Returns
41 ///
42 /// - `Entity` - The newly created entity.
43 pub fn create_at(position: Vector2D) -> Entity {
44 let mut entity: Entity = Self::create(DEFAULT_ENTITY_NAME);
45 entity.get_mut_transform().set_position(position);
46 entity
47 }
48}
49
50/// Implements lifecycle and component management methods for `Entity`.
51impl Entity {
52 /// Adds a component to this entity and calls its `on_start` lifecycle method.
53 ///
54 /// # Arguments
55 ///
56 /// - `ComponentRc` - The component to add.
57 pub fn add_component(&mut self, component: ComponentRc) {
58 component.borrow_mut().on_start();
59 self.get_mut_components().push(component);
60 }
61
62 /// Removes the first component matching the given name.
63 ///
64 /// # Arguments
65 ///
66 /// - `&str` - The component name to match.
67 ///
68 /// # Returns
69 ///
70 /// - `Option<ComponentRc>` - The removed component, if found.
71 pub fn remove_component_by_name(&mut self, name: &str) -> Option<ComponentRc> {
72 let position: Option<usize> = self
73 .get_components()
74 .iter()
75 .position(|component: &ComponentRc| component.borrow().name() == name);
76 let index: usize = position?;
77 let removed: ComponentRc = self.get_mut_components().remove(index);
78 removed.borrow_mut().on_destroy();
79 Some(removed)
80 }
81
82 /// Returns the first component matching the given name.
83 ///
84 /// # Arguments
85 ///
86 /// - `&str` - The component name to match.
87 ///
88 /// # Returns
89 ///
90 /// - `Option<ComponentRc>` - The matching component, if found.
91 pub fn get_component_by_name(&self, name: &str) -> Option<ComponentRc> {
92 self.get_components()
93 .iter()
94 .find(|component: &&ComponentRc| component.borrow().name() == name)
95 .cloned()
96 }
97
98 /// Calls `on_update` on all active components.
99 ///
100 /// # Arguments
101 ///
102 /// - `f64` - The delta time in seconds.
103 pub fn update(&mut self, delta_time: f64) {
104 if !self.get_active() {
105 return;
106 }
107 for component in self.get_components() {
108 component.borrow_mut().on_update(delta_time);
109 }
110 }
111
112 /// Calls `on_render` on all active components.
113 ///
114 /// # Arguments
115 ///
116 /// - `&CanvasRenderingContext2d` - The canvas rendering context.
117 pub fn render(&self, context: &CanvasRenderingContext2d) {
118 if !self.get_active() {
119 return;
120 }
121 let transform: Transform2D = self.get_transform();
122 for component in self.get_components() {
123 component.borrow_mut().on_render(context, &transform);
124 }
125 }
126
127 /// Calls `on_destroy` on all components and clears the component list.
128 pub fn destroy(&mut self) {
129 for component in self.get_components() {
130 component.borrow_mut().on_destroy();
131 }
132 self.get_mut_components().clear();
133 }
134
135 /// Adds a tag string to this entity.
136 ///
137 /// # Arguments
138 ///
139 /// - `String` - The tag to add.
140 pub fn add_tag(&mut self, tag: String) {
141 if !self.get_tags().contains(&tag) {
142 self.get_mut_tags().push(tag);
143 }
144 }
145
146 /// Tests whether this entity has the given tag.
147 ///
148 /// # Arguments
149 ///
150 /// - `&str` - The tag to check.
151 ///
152 /// # Returns
153 ///
154 /// - `bool` - True if the tag is present.
155 pub fn has_tag(&self, tag: &str) -> bool {
156 self.get_tags().iter().any(|t: &String| t == tag)
157 }
158}
159
160/// Implements event subscription, emission, and management for `EventBus`.
161impl EventBus {
162 /// Creates a new empty event bus.
163 ///
164 /// # Returns
165 ///
166 /// - `EventBus` - The new event bus.
167 pub fn create() -> EventBus {
168 EventBus::new()
169 }
170
171 /// Subscribes a handler to the named event channel.
172 ///
173 /// # Arguments
174 ///
175 /// - `String` - The event name to subscribe to.
176 /// - `EventHandler` - The handler closure to call when the event is emitted.
177 pub fn subscribe(&mut self, event_name: String, handler: EventHandler) {
178 self.get_mut_handlers()
179 .entry(event_name)
180 .or_default()
181 .push(handler);
182 }
183
184 /// Emits an event to all handlers subscribed to the matching channel.
185 ///
186 /// The event name is derived from the `EntityEvent` variant.
187 ///
188 /// # Arguments
189 ///
190 /// - `&EntityEvent` - The event to emit.
191 pub fn emit(&self, event: &EntityEvent) {
192 let event_name: String = Self::event_name(event);
193 if let Some(handlers) = self.get_handlers().get(&event_name) {
194 for handler in handlers {
195 handler(event);
196 }
197 }
198 }
199
200 /// Removes all handlers for the named event channel.
201 ///
202 /// # Arguments
203 ///
204 /// - `&str` - The event name to clear.
205 pub fn unsubscribe_all(&mut self, event_name: &str) {
206 self.get_mut_handlers().remove(event_name);
207 }
208
209 /// Returns the number of handlers registered for the named event.
210 ///
211 /// # Arguments
212 ///
213 /// - `&str` - The event name.
214 ///
215 /// # Returns
216 ///
217 /// - `usize` - The handler count.
218 pub fn handler_count(&self, event_name: &str) -> usize {
219 self.get_handlers()
220 .get(event_name)
221 .map(|handlers: &Vec<EventHandler>| handlers.len())
222 .unwrap_or(0)
223 }
224
225 /// Derives the event channel name from an `EntityEvent` variant.
226 ///
227 /// # Arguments
228 ///
229 /// - `&EntityEvent` - The event.
230 ///
231 /// # Returns
232 ///
233 /// - `String` - The channel name.
234 fn event_name(event: &EntityEvent) -> String {
235 match event {
236 EntityEvent::Collision { .. } => "collision".to_string(),
237 EntityEvent::TriggerEnter { .. } => "trigger_enter".to_string(),
238 EntityEvent::TriggerExit { .. } => "trigger_exit".to_string(),
239 EntityEvent::Spawn => "spawn".to_string(),
240 EntityEvent::Destroy => "destroy".to_string(),
241 EntityEvent::Custom { name, .. } => name.clone(),
242 }
243 }
244}
245
246/// Implements `Default` for `EventBus` as a new empty bus.
247impl Default for EventBus {
248 fn default() -> EventBus {
249 EventBus::create()
250 }
251}