euv_engine/scene/impl.rs
1use super::*;
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, recording into the shared draw list.
114 ///
115 /// The manager's reusable `DrawList` is cleared, filled by the scene, and
116 /// left populated for the caller to replay (e.g. via
117 /// `CanvasRenderer::replay`). Reusing the list avoids per-frame allocation.
118 ///
119 /// # Arguments
120 ///
121 /// - `&CanvasRenderingContext2d` - The canvas rendering context used to replay
122 /// the recorded commands.
123 pub fn render(&mut self, context: &CanvasRenderingContext2d) {
124 let Some(current_name) = self.try_get_current_scene_name().as_ref() else {
125 return;
126 };
127 // Clone the `Rc` so the immutable borrow of the scenes map ends before
128 // we mutably borrow the draw list.
129 let Some(scene) = self.get_scenes().get(current_name).cloned() else {
130 return;
131 };
132 self.get_mut_draw_list().clear();
133 {
134 let draw_list: &mut DrawList = self.get_mut_draw_list();
135 scene.borrow().on_render(draw_list);
136 }
137 CanvasRenderer::replay_context(context, self.get_draw_list());
138 }
139
140 /// Returns whether a scene with the given name is registered.
141 ///
142 /// # Arguments
143 ///
144 /// - `N: AsRef<str>` - The scene name to check.
145 ///
146 /// # Returns
147 ///
148 /// - `bool` - True if the scene is registered.
149 pub fn has_scene<N>(&self, name: N) -> bool
150 where
151 N: AsRef<str>,
152 {
153 self.get_scenes().contains_key(name.as_ref())
154 }
155
156 /// Returns the name of the currently active scene.
157 ///
158 /// # Returns
159 ///
160 /// - `Option<&str>` - The current scene name, or `None`.
161 pub fn current_name(&self) -> Option<&str> {
162 self.try_get_current_scene_name().as_deref()
163 }
164}
165
166/// Implements `Default` for `SceneManager` as a new empty manager.
167impl Default for SceneManager {
168 fn default() -> SceneManager {
169 SceneManager::new()
170 }
171}