Skip to main content

euv_engine/scene/
impl.rs

1use crate::*;
2
3/// Implements static scene creation for `SceneManager`.
4impl SceneManager {
5    /// Creates a new `SceneRc` wrapping the given scene in a reference-counted cell.
6    ///
7    /// # Arguments
8    ///
9    /// - `T` - The concrete scene type implementing `Scene`.
10    ///
11    /// # Returns
12    ///
13    /// - `SceneRc` - The wrapped scene.
14    pub fn create_scene<T>(scene: T) -> SceneRc
15    where
16        T: Scene + 'static,
17    {
18        Rc::new(RefCell::new(scene))
19    }
20}
21
22/// Implements scene registration and lifecycle management for `SceneManager`.
23impl SceneManager {
24    /// Registers a scene under the given name.
25    ///
26    /// # Arguments
27    ///
28    /// - `String` - The name to register the scene under.
29    /// - `SceneRc` - The scene to register.
30    pub fn register(&mut self, name: String, scene: SceneRc) {
31        self.get_mut_scenes().insert(name, scene);
32    }
33
34    /// Unregisters and removes the scene with the given name.
35    ///
36    /// # Arguments
37    ///
38    /// - `N: AsRef<str>` - The name of the scene to remove.
39    pub fn unregister<N>(&mut self, name: N)
40    where
41        N: AsRef<str>,
42    {
43        self.get_mut_scenes().remove(name.as_ref());
44    }
45
46    /// Transitions to the scene with the given name.
47    ///
48    /// Calls `on_exit` on the current scene and `on_enter` on the new scene.
49    /// Returns `false` if no scene with the given name is registered.
50    ///
51    /// # Arguments
52    ///
53    /// - `N: AsRef<str>` - The name of the scene to switch to.
54    ///
55    /// # Returns
56    ///
57    /// - `bool` - True if the transition was successful.
58    pub fn switch_to<N>(&mut self, name: N) -> bool
59    where
60        N: AsRef<str>,
61    {
62        let name_ref: &str = name.as_ref();
63        if !self.get_scenes().contains_key(name_ref) {
64            return false;
65        }
66        let current_name: Option<String> = self.get_mut_current_scene_name().clone();
67        if let Some(name) = current_name.as_ref()
68            && let Some(current_scene) = self.get_scenes().get(name)
69        {
70            current_scene.borrow_mut().on_exit();
71        }
72        self.set_current_scene_name(Some(name_ref.to_string()));
73        if let Some(new_scene) = self.get_scenes().get(name_ref) {
74            new_scene.borrow_mut().on_enter();
75        }
76        true
77    }
78
79    /// Requests a deferred scene transition to be applied on the next update.
80    ///
81    /// # Arguments
82    ///
83    /// - `String` - The name of the scene to switch to.
84    pub fn request_transition(&mut self, name: String) {
85        self.set_pending_scene_name(Some(name));
86    }
87
88    /// Processes a pending scene transition if one was requested.
89    pub fn process_pending_transition(&mut self) {
90        let Some(name) = self.get_mut_pending_scene_name().take() else {
91            return;
92        };
93        self.switch_to(&name);
94    }
95
96    /// Calls `on_update` on the current scene.
97    ///
98    /// # Arguments
99    ///
100    /// - `f64` - The delta time in seconds.
101    pub fn update(&mut self, delta_time: f64) {
102        self.process_pending_transition();
103        let current_name: Option<String> = self.get_mut_current_scene_name().clone();
104        let Some(current_name) = current_name.as_ref() else {
105            return;
106        };
107        let Some(scene) = self.get_scenes().get(current_name) else {
108            return;
109        };
110        scene.borrow_mut().on_update(delta_time);
111    }
112
113    /// Calls `on_render` on the current scene.
114    ///
115    /// # Arguments
116    ///
117    /// - `&CanvasRenderingContext2d` - The canvas rendering context.
118    pub fn render(&self, context: &CanvasRenderingContext2d) {
119        let Some(current_name) = self.current_scene_name.as_ref() else {
120            return;
121        };
122        let Some(scene) = self.get_scenes().get(current_name) else {
123            return;
124        };
125        scene.borrow().on_render(context);
126    }
127
128    /// Returns whether a scene with the given name is registered.
129    ///
130    /// # Arguments
131    ///
132    /// - `N: AsRef<str>` - The scene name to check.
133    ///
134    /// # Returns
135    ///
136    /// - `bool` - True if the scene is registered.
137    pub fn has_scene<N>(&self, name: N) -> bool
138    where
139        N: AsRef<str>,
140    {
141        self.get_scenes().contains_key(name.as_ref())
142    }
143
144    /// Returns the name of the currently active scene.
145    ///
146    /// # Returns
147    ///
148    /// - `Option<&str>` - The current scene name, or `None`.
149    pub fn current_name(&self) -> Option<&str> {
150        self.current_scene_name.as_deref()
151    }
152}
153
154/// Implements `Default` for `SceneManager` as a new empty manager.
155impl Default for SceneManager {
156    fn default() -> SceneManager {
157        SceneManager::new()
158    }
159}