Skip to main content

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}