core: Add is_root parameter to MovieClip::replace_with_movie

The method MovieClip::replace_with_movie accepts an
Option<Arc<SwfMovie>>. If no movie is given, an empty stub movie is
generated and used.
Previously, the IS_ROOT flag has been set for the new replaced SwfMovie,
depending on whether a movie was given to the method or not.
However, there are cases where an explicitely given movie should not be
set as a root movie (e.g. if a specific empty stub movie is given to the
method). Conversely, there are also cases where no movie is given, but
the stub movie should still be set as a root movie (e.g. in specific
MovieClip states).
Therefore, an is_root parameter has been added to the method. This
explicit parameter is now used to set the flag for the new replaced
SwfMovie.

All calls of replace_with_movie have been adapted to use the new
parameter correctly.
This commit is contained in:
Kornelius Rohrschneider 2023-08-08 19:33:58 +02:00 committed by Nathan Adams
parent 0abe0b9386
commit f582ea572c
2 changed files with 16 additions and 11 deletions

View File

@ -386,20 +386,20 @@ impl<'gc> MovieClip<'gc> {
/// Replace the current MovieClipData with a completely new SwfMovie. /// Replace the current MovieClipData with a completely new SwfMovie.
/// ///
/// If no movie is provided, then the movie clip will be replaced with an
/// empty movie of the same SWF version.
///
/// Playback will start at position zero, any existing streamed audio will /// Playback will start at position zero, any existing streamed audio will
/// be terminated, and so on. Children and AVM data will NOT be kept across /// be terminated, and so on. Children and AVM data will NOT be kept across
/// the load boundary. /// the load boundary.
///
/// If no movie is provided, then the movie clip will be replaced with an
/// empty movie of the same SWF version.
pub fn replace_with_movie( pub fn replace_with_movie(
self, self,
context: &mut UpdateContext<'_, 'gc>, context: &mut UpdateContext<'_, 'gc>,
movie: Option<Arc<SwfMovie>>, movie: Option<Arc<SwfMovie>>,
is_root: bool,
loader_info: Option<LoaderInfoObject<'gc>>, loader_info: Option<LoaderInfoObject<'gc>>,
) { ) {
let mut mc = self.0.write(context.gc_context); let mut mc = self.0.write(context.gc_context);
let is_swf = movie.is_some();
let movie = movie.unwrap_or_else(|| Arc::new(SwfMovie::empty(mc.movie().version()))); let movie = movie.unwrap_or_else(|| Arc::new(SwfMovie::empty(mc.movie().version())));
let total_frames = movie.num_frames(); let total_frames = movie.num_frames();
assert_eq!( assert_eq!(
@ -420,7 +420,7 @@ impl<'gc> MovieClip<'gc> {
); );
mc.tag_stream_pos = 0; mc.tag_stream_pos = 0;
mc.flags = MovieClipFlags::PLAYING; mc.flags = MovieClipFlags::PLAYING;
mc.base.base.set_is_root(is_swf); mc.base.base.set_is_root(is_root);
mc.current_frame = 0; mc.current_frame = 0;
mc.audio_stream = None; mc.audio_stream = None;
mc.container = ChildContainer::new(); mc.container = ChildContainer::new();
@ -2476,7 +2476,7 @@ impl<'gc> MovieClip<'gc> {
None None
}; };
self.replace_with_movie(context, movie, None); self.replace_with_movie(context, movie, self.is_root(), None);
} }
} }

View File

@ -860,7 +860,7 @@ impl<'gc> Loader<'gc> {
if !uc.is_action_script_3() { if !uc.is_action_script_3() {
mc.avm1_unload(uc); mc.avm1_unload(uc);
} }
mc.replace_with_movie(uc, None, None); mc.replace_with_movie(uc, None, false, None);
} }
// NOTE: We do NOT call `movie_loader_start` as `loadBytes` does // NOTE: We do NOT call `movie_loader_start` as `loadBytes` does
@ -1576,7 +1576,12 @@ impl<'gc> Loader<'gc> {
// Store our downloaded `SwfMovie` into our target `MovieClip`, // Store our downloaded `SwfMovie` into our target `MovieClip`,
// and initialize it. // and initialize it.
mc.replace_with_movie(&mut activation.context, Some(movie), loader_info); mc.replace_with_movie(
&mut activation.context,
Some(movie),
true,
loader_info,
);
} }
// NOTE: Certain tests specifically expect small files to preload immediately // NOTE: Certain tests specifically expect small files to preload immediately
@ -1847,7 +1852,7 @@ impl<'gc> Loader<'gc> {
// This is a load of an image into AVM1 - add it as a child of the target clip. // This is a load of an image into AVM1 - add it as a child of the target clip.
if dobj.as_movie_clip().is_none() { if dobj.as_movie_clip().is_none() {
let mc = target_clip.as_movie_clip().unwrap(); let mc = target_clip.as_movie_clip().unwrap();
mc.replace_with_movie(uc, Some(movie.unwrap()), None); mc.replace_with_movie(uc, Some(movie.unwrap()), true, None);
mc.replace_at_depth(uc, dobj, 1); mc.replace_at_depth(uc, dobj, 1);
// This sets the MovieClip image state correctly. // This sets the MovieClip image state correctly.
@ -2020,7 +2025,7 @@ impl<'gc> Loader<'gc> {
let mut initial_loading_movie = SwfMovie::empty(current_version); let mut initial_loading_movie = SwfMovie::empty(current_version);
initial_loading_movie.set_url(current_url.to_string()); initial_loading_movie.set_url(current_url.to_string());
mc.replace_with_movie(uc, Some(Arc::new(initial_loading_movie)), None); mc.replace_with_movie(uc, Some(Arc::new(initial_loading_movie)), true, None);
// Maybe this (keeping the current URL) should be the default behaviour // Maybe this (keeping the current URL) should be the default behaviour
// of replace_with_movie? // of replace_with_movie?
@ -2057,7 +2062,7 @@ impl<'gc> Loader<'gc> {
let error_movie = SwfMovie::error_movie(swf_url); let error_movie = SwfMovie::error_movie(swf_url);
// This also sets total_frames correctly // This also sets total_frames correctly
mc.replace_with_movie(uc, Some(Arc::new(error_movie)), None); mc.replace_with_movie(uc, Some(Arc::new(error_movie)), true, None);
mc.set_cur_preload_frame(uc.gc_context, 0); mc.set_cur_preload_frame(uc.gc_context, 0);
} }