dotzuki_engine_script/
cutscene.rs1use std::collections::VecDeque;
38
39#[derive(Debug, Clone)]
45pub struct CutsceneManager {
46 pub active: bool,
48 pub current_script: Option<String>,
50 pub blocking: bool,
54 pub queue: VecDeque<String>,
57 pub started: bool,
61}
62
63impl CutsceneManager {
64 pub fn new() -> Self {
66 Self {
67 active: false,
68 current_script: None,
69 blocking: true,
70 queue: VecDeque::new(),
71 started: false,
72 }
73 }
74
75 pub fn start_cutscene(&mut self, script_name: &str, blocking: bool) {
82 if self.active {
83 self.queue.push_back(script_name.to_string());
84 return;
85 }
86 self.active = true;
87 self.current_script = Some(script_name.to_string());
88 self.blocking = blocking;
89 self.started = false;
90 }
91
92 pub fn is_active(&self) -> bool {
94 self.active
95 }
96
97 pub fn is_blocking(&self) -> bool {
99 self.active && self.blocking
100 }
101
102 pub fn current_script_name(&self) -> Option<&str> {
104 self.current_script.as_deref()
105 }
106
107 pub fn end_cutscene(&mut self) -> Option<String> {
111 self.active = false;
112 self.current_script = None;
113 self.started = false;
114
115 if let Some(next) = self.queue.pop_front() {
116 self.active = true;
117 self.current_script = Some(next.clone());
118 self.started = false;
119 return Some(next);
120 }
121 None
122 }
123
124 pub fn queue_script(&mut self, script_name: &str) {
126 self.queue.push_back(script_name.to_string());
127 }
128
129 pub fn queue_len(&self) -> usize {
131 self.queue.len()
132 }
133
134 pub fn has_queued(&self) -> bool {
136 !self.queue.is_empty()
137 }
138
139 pub fn clear_queue(&mut self) {
141 self.queue.clear();
142 }
143
144 pub fn force_stop(&mut self) {
146 self.active = false;
147 self.current_script = None;
148 self.queue.clear();
149 self.started = false;
150 }
151
152 pub fn mark_started(&mut self) {
153 self.started = true;
154 }
155
156 pub fn needs_start(&self) -> bool {
157 self.active && !self.started
158 }
159}
160
161impl Default for CutsceneManager {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_new_cutscene_manager() {
173 let cm = CutsceneManager::new();
174 assert!(!cm.is_active());
175 assert!(cm.current_script.is_none());
176 assert!(cm.queue.is_empty());
177 }
178
179 #[test]
180 fn test_start_and_end_cutscene() {
181 let mut cm = CutsceneManager::new();
182 cm.start_cutscene("prof_lab_intro", true);
183 assert!(cm.is_active());
184 assert!(cm.is_blocking());
185 assert_eq!(cm.current_script_name(), Some("prof_lab_intro"));
186
187 cm.end_cutscene();
188 assert!(!cm.is_active());
189 assert!(cm.current_script.is_none());
190 }
191
192 #[test]
193 fn test_non_blocking_cutscene() {
194 let mut cm = CutsceneManager::new();
195 cm.start_cutscene("ambient_chatter", false);
196 assert!(cm.is_active());
197 assert!(!cm.is_blocking());
198 }
199
200 #[test]
201 fn test_queue_when_active() {
202 let mut cm = CutsceneManager::new();
203 cm.start_cutscene("first", true);
204 cm.start_cutscene("second", true);
205 cm.start_cutscene("third", true);
206
207 assert_eq!(cm.current_script_name(), Some("first"));
209 assert_eq!(cm.queue_len(), 2);
210
211 let next = cm.end_cutscene();
213 assert_eq!(next, Some("second".to_string()));
214 assert_eq!(cm.current_script_name(), Some("second"));
215 assert_eq!(cm.queue_len(), 1);
216
217 let next = cm.end_cutscene();
219 assert_eq!(next, Some("third".to_string()));
220 assert_eq!(cm.current_script_name(), Some("third"));
221 assert_eq!(cm.queue_len(), 0);
222
223 let next = cm.end_cutscene();
225 assert_eq!(next, None);
226 assert!(!cm.is_active());
227 }
228
229 #[test]
230 fn test_queue_script() {
231 let mut cm = CutsceneManager::new();
232 cm.queue_script("intro");
233 cm.queue_script("prof_arrives");
234 assert_eq!(cm.queue_len(), 2);
235 assert!(!cm.is_active()); cm.start_cutscene("manual_start", true);
239 assert_eq!(cm.current_script_name(), Some("manual_start"));
240
241 let next = cm.end_cutscene();
243 assert_eq!(next, Some("intro".to_string()));
244
245 let next = cm.end_cutscene();
247 assert_eq!(next, Some("prof_arrives".to_string()));
248 }
249
250 #[test]
251 fn test_force_stop() {
252 let mut cm = CutsceneManager::new();
253 cm.start_cutscene("running", true);
254 cm.queue_script("next1");
255 cm.queue_script("next2");
256
257 cm.force_stop();
258 assert!(!cm.is_active());
259 assert!(cm.current_script.is_none());
260 assert!(cm.queue.is_empty());
261 }
262
263 #[test]
264 fn test_clear_queue() {
265 let mut cm = CutsceneManager::new();
266 cm.queue_script("a");
267 cm.queue_script("b");
268 cm.clear_queue();
269 assert_eq!(cm.queue_len(), 0);
270 assert!(cm.queue.is_empty());
271 }
272
273 #[test]
274 fn test_default() {
275 let cm: CutsceneManager = Default::default();
276 assert!(!cm.is_active());
277 assert!(cm.queue.is_empty());
278 }
279}