From 86f9ee4821666542bda1529ffe90ece820f7af42 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Fri, 2 Sep 2022 18:40:59 -0400 Subject: [PATCH] core: Add a "preload everything we know about" method --- core/src/loader.rs | 28 ++++++++++++++++++++++++---- core/src/player.rs | 30 +++++++++++++++--------------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/core/src/loader.rs b/core/src/loader.rs index 9309c5a0e..e86ad99fe 100644 --- a/core/src/loader.rs +++ b/core/src/loader.rs @@ -351,6 +351,24 @@ impl<'gc> LoadManager<'gc> { let loader = self.get_loader_mut(handle).unwrap(); loader.sound_loader_avm2(player, request) } + + /// Process tags on all loaders in the Parsing phase. + pub fn preload_tick(context: &mut UpdateContext<'_, 'gc, '_>, limit: &mut ExecutionLimit) { + let handles: Vec<_> = context.load_manager.0.iter().map(|(h, _)| h).collect(); + + for handle in handles { + let status = match context.load_manager.get_loader(handle) { + Some(Loader::Movie { loader_status, .. }) => Some(loader_status), + _ => None, + }; + + if matches!(status, Some(LoaderStatus::Parsing)) { + if let Err(e) = Loader::preload_tick(handle, context, limit) { + log::error!("Error encountered while preloading movie: {}", e); + } + } + } + } } impl<'gc> Default for LoadManager<'gc> { @@ -493,7 +511,6 @@ impl<'gc> Loader<'gc> { target_clip, event_handler, movie, - loader_status, .. }) => { if movie.is_none() { @@ -501,8 +518,6 @@ impl<'gc> Loader<'gc> { return Ok(()); } - *loader_status = LoaderStatus::Parsing; - (*target_clip, *event_handler, movie.clone().unwrap()) } None => return Err(Error::Cancelled), @@ -692,7 +707,12 @@ impl<'gc> Loader<'gc> { )?); match uc.load_manager.get_loader_mut(handle) { - Some(Loader::Movie { movie: old, .. }) => { + Some(Loader::Movie { + movie: old, + loader_status, + .. + }) => { + *loader_status = LoaderStatus::Parsing; *old = Some(movie.clone()) } _ => unreachable!(), diff --git a/core/src/player.rs b/core/src/player.rs index a144ade9c..bfce63a29 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -401,7 +401,12 @@ impl Player { stage.build_matrices(&mut activation.context); }); - self.preload(); + self.preload(&mut ExecutionLimit::none()); + + if self.swf.is_action_script_3() && self.warn_on_unsupported_content { + self.ui.display_unsupported_message(); + } + self.audio.set_frame_rate(self.frame_rate); } @@ -1323,25 +1328,20 @@ impl Player { needs_render } - /// Preload the first movie in the player. + /// Preload all pending movies in the player, including the root movie. /// - /// This should only be called once. Further movie loads should preload the - /// specific `MovieClip` referenced. - fn preload(&mut self) { + /// This should be called periodically with a reasonable execution limit. + /// By default, the Player will do so after every `run_frame` using a limit + /// derived from the current frame rate and execution time. Clients that + /// want synchronous or 'lockstep' preloading may call this function with + /// an unlimited execution limit. + fn preload(&mut self, limit: &mut ExecutionLimit) { self.mutate_with_update_context(|context| { let root = context.stage.root_clip(); - let preload_done = root - .as_movie_clip() - .unwrap() - .preload(context, &mut ExecutionLimit::none()); + root.as_movie_clip().unwrap().preload(context, limit); - if !preload_done { - log::warn!("Preloading of root clip did not complete in a single call."); - } + LoadManager::preload_tick(context, limit); }); - if self.swf.is_action_script_3() && self.warn_on_unsupported_content { - self.ui.display_unsupported_message(); - } } pub fn run_frame(&mut self) {