Skip to main content

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    /// Advances the simulation by `delta_time` seconds.
185    ///
186    /// # Arguments
187    ///
188    /// - `f64` - Seconds elapsed since the previous update.
189    fn update(&mut self, delta_time: f64) {
190        Entity::update(self, delta_time);
191    }
192}
193
194/// Implements event subscription, emission, and management for `EventBus`.
195impl EventBus {
196    /// Creates a new empty event bus.
197    ///
198    /// # Returns
199    ///
200    /// - `EventBus` - The new event bus.
201    pub fn create() -> EventBus {
202        EventBus::new()
203    }
204
205    /// Subscribes a handler to the named event channel.
206    ///
207    /// # Arguments
208    ///
209    /// - `String` - The event name to subscribe to.
210    /// - `EventHandler` - The handler closure to call when the event is emitted.
211    pub fn subscribe(&mut self, event_name: String, handler: EventHandler) {
212        self.get_mut_handlers()
213            .entry(event_name)
214            .or_default()
215            .push(handler);
216    }
217
218    /// Emits an event to all handlers subscribed to the matching channel.
219    ///
220    /// The event name is derived from the `EntityEvent` variant.
221    ///
222    /// # Arguments
223    ///
224    /// - `&EntityEvent` - The event to emit.
225    pub fn emit(&self, event: &EntityEvent) {
226        let event_name: String = Self::event_name(event);
227        if let Some(handlers) = self.get_handlers().get(&event_name) {
228            for handler in handlers {
229                handler(event);
230            }
231        }
232    }
233
234    /// Removes all handlers for the named event channel.
235    ///
236    /// # Arguments
237    ///
238    /// - `E: AsRef<str>` - The event name to clear.
239    pub fn unsubscribe_all<E>(&mut self, event_name: E)
240    where
241        E: AsRef<str>,
242    {
243        self.get_mut_handlers().remove(event_name.as_ref());
244    }
245
246    /// Returns the number of handlers registered for the named event.
247    ///
248    /// # Arguments
249    ///
250    /// - `&str` - The event name.
251    ///
252    /// # Returns
253    ///
254    /// - `usize` - The handler count.
255    pub fn handler_count<E>(&self, event_name: E) -> usize
256    where
257        E: AsRef<str>,
258    {
259        self.get_handlers()
260            .get(event_name.as_ref())
261            .map(|handlers: &Vec<EventHandler>| handlers.len())
262            .unwrap_or_default()
263    }
264
265    /// Derives the event channel name from an `EntityEvent` variant.
266    ///
267    /// # Arguments
268    ///
269    /// - `&EntityEvent` - The event.
270    ///
271    /// # Returns
272    ///
273    /// - `String` - The channel name.
274    fn event_name(event: &EntityEvent) -> String {
275        match event {
276            EntityEvent::Collision { .. } => "collision".to_string(),
277            EntityEvent::TriggerEnter { .. } => "trigger_enter".to_string(),
278            EntityEvent::TriggerExit { .. } => "trigger_exit".to_string(),
279            EntityEvent::Spawn => "spawn".to_string(),
280            EntityEvent::Destroy => "destroy".to_string(),
281            EntityEvent::Custom { name, .. } => name.clone(),
282        }
283    }
284}
285
286/// Implements `Default` for `EventBus` as a new empty bus.
287impl Default for EventBus {
288    /// Constructs a default [`EventBus`] value.
289    ///
290    /// # Returns
291    ///
292    /// - `EventBus` - A default-constructed instance with the documented initial state.
293    fn default() -> EventBus {
294        EventBus::create()
295    }
296}