core: Add a "preload everything we know about" method

This commit is contained in:
David Wendt 2022-09-02 18:40:59 -04:00 committed by kmeisthax
parent 940de4bb7e
commit 86f9ee4821
2 changed files with 39 additions and 19 deletions

View File

@ -351,6 +351,24 @@ impl<'gc> LoadManager<'gc> {
let loader = self.get_loader_mut(handle).unwrap(); let loader = self.get_loader_mut(handle).unwrap();
loader.sound_loader_avm2(player, request) 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> { impl<'gc> Default for LoadManager<'gc> {
@ -493,7 +511,6 @@ impl<'gc> Loader<'gc> {
target_clip, target_clip,
event_handler, event_handler,
movie, movie,
loader_status,
.. ..
}) => { }) => {
if movie.is_none() { if movie.is_none() {
@ -501,8 +518,6 @@ impl<'gc> Loader<'gc> {
return Ok(()); return Ok(());
} }
*loader_status = LoaderStatus::Parsing;
(*target_clip, *event_handler, movie.clone().unwrap()) (*target_clip, *event_handler, movie.clone().unwrap())
} }
None => return Err(Error::Cancelled), None => return Err(Error::Cancelled),
@ -692,7 +707,12 @@ impl<'gc> Loader<'gc> {
)?); )?);
match uc.load_manager.get_loader_mut(handle) { 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()) *old = Some(movie.clone())
} }
_ => unreachable!(), _ => unreachable!(),

View File

@ -401,7 +401,12 @@ impl Player {
stage.build_matrices(&mut activation.context); 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); self.audio.set_frame_rate(self.frame_rate);
} }
@ -1323,25 +1328,20 @@ impl Player {
needs_render 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 /// This should be called periodically with a reasonable execution limit.
/// specific `MovieClip` referenced. /// By default, the Player will do so after every `run_frame` using a limit
fn preload(&mut self) { /// 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| { self.mutate_with_update_context(|context| {
let root = context.stage.root_clip(); let root = context.stage.root_clip();
let preload_done = root root.as_movie_clip().unwrap().preload(context, limit);
.as_movie_clip()
.unwrap()
.preload(context, &mut ExecutionLimit::none());
if !preload_done { LoadManager::preload_tick(context, limit);
log::warn!("Preloading of root clip did not complete in a single call.");
}
}); });
if self.swf.is_action_script_3() && self.warn_on_unsupported_content {
self.ui.display_unsupported_message();
}
} }
pub fn run_frame(&mut self) { pub fn run_frame(&mut self) {