Allow unloading a movie by sending `None` to `replace_with_movie`.

This also adjusts `MovieClip.unloadMovie` to do just that, instead of removing the clip from the display list. We also have to unload clips when loading new movies into them, since `unloadMovie` desugars to loading `""` as the URL.
This commit is contained in:
David Wendt 2020-01-17 14:50:28 -05:00
parent 8ef4a94672
commit 162b6b70f8
3 changed files with 17 additions and 28 deletions

View File

@ -228,29 +228,8 @@ pub fn create_proto<'gc>(
Ok(Value::Undefined.into())
},
"unloadMovie" => |mut target: MovieClip<'gc>, _avm: &mut Avm1<'gc>, context: &mut UpdateContext<'_, 'gc, '_>, _args: &[Value<'gc>]| {
//TODO: How do we reclaim resources from unloaded movies?
if let Some(parent) = target.parent() {
parent
.as_movie_clip()
.unwrap()
.remove_child_from_avm(context, DisplayObject::MovieClip(target));
} else {
//Removing a layer is a little different.
let mut layer_depth = None;
for (depth, layer) in context.layers.iter() {
if DisplayObject::ptr_eq(*layer, DisplayObject::MovieClip(target)) {
layer_depth = Some(*depth);
break;
}
}
if let Some(depth) = layer_depth {
context.layers.remove(&depth);
}
target.unload(context);
}
target.unload(context);
target.replace_with_movie(context.gc_context, None);
Ok(Value::Undefined.into())
}

View File

@ -111,7 +111,7 @@ impl<'gc> MovieClip<'gc> {
pub fn replace_with_movie(
&mut self,
gc_context: MutationContext<'gc, '_>,
movie: Arc<SwfMovie>,
movie: Option<Arc<SwfMovie>>,
) {
self.0
.write(gc_context)
@ -424,13 +424,17 @@ impl<'gc> MovieClipData<'gc> {
/// Replace the current MovieClipData with a completely new SwfMovie.
///
/// Playback will start at position zero, any existing streamed audio will
/// be terminated, and so on. Children and AVM data will be kept across the
/// load boundary.
/// be terminated, and so on. Children and AVM data will NOT be kept across
/// 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(
&mut self,
gc_context: MutationContext<'gc, '_>,
movie: Arc<SwfMovie>,
movie: Option<Arc<SwfMovie>>,
) {
let movie = movie.unwrap_or_else(|| Arc::new(SwfMovie::empty(self.movie().version())));
let total_frames = movie.header().num_frames;
self.base = Default::default();

View File

@ -211,6 +211,12 @@ impl<'gc> Loader<'gc> {
_ => unreachable!(),
};
clip.as_movie_clip().unwrap().unload(uc);
clip.as_movie_clip()
.unwrap()
.replace_with_movie(uc.gc_context, None);
if let Some(broadcaster) = broadcaster {
avm.insert_stack_frame_for_method(
clip,
@ -264,7 +270,7 @@ impl<'gc> Loader<'gc> {
.as_movie_clip()
.expect("Attempted to load movie into not movie clip");
mc.replace_with_movie(uc.gc_context, movie.clone());
mc.replace_with_movie(uc.gc_context, Some(movie.clone()));
mc.post_instantiation(uc.gc_context, clip, avm.prototypes().movie_clip);
let mut morph_shapes = fnv::FnvHashMap::default();