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:
parent
8ef4a94672
commit
162b6b70f8
|
@ -228,29 +228,8 @@ pub fn create_proto<'gc>(
|
||||||
Ok(Value::Undefined.into())
|
Ok(Value::Undefined.into())
|
||||||
},
|
},
|
||||||
"unloadMovie" => |mut target: MovieClip<'gc>, _avm: &mut Avm1<'gc>, context: &mut UpdateContext<'_, 'gc, '_>, _args: &[Value<'gc>]| {
|
"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())
|
Ok(Value::Undefined.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
pub fn replace_with_movie(
|
pub fn replace_with_movie(
|
||||||
&mut self,
|
&mut self,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
gc_context: MutationContext<'gc, '_>,
|
||||||
movie: Arc<SwfMovie>,
|
movie: Option<Arc<SwfMovie>>,
|
||||||
) {
|
) {
|
||||||
self.0
|
self.0
|
||||||
.write(gc_context)
|
.write(gc_context)
|
||||||
|
@ -424,13 +424,17 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
/// Replace the current MovieClipData with a completely new SwfMovie.
|
/// Replace the current MovieClipData with a completely new SwfMovie.
|
||||||
///
|
///
|
||||||
/// 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 be kept across the
|
/// be terminated, and so on. Children and AVM data will NOT be kept across
|
||||||
/// 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(
|
||||||
&mut self,
|
&mut self,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
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;
|
let total_frames = movie.header().num_frames;
|
||||||
|
|
||||||
self.base = Default::default();
|
self.base = Default::default();
|
||||||
|
|
|
@ -211,6 +211,12 @@ impl<'gc> Loader<'gc> {
|
||||||
_ => unreachable!(),
|
_ => 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 {
|
if let Some(broadcaster) = broadcaster {
|
||||||
avm.insert_stack_frame_for_method(
|
avm.insert_stack_frame_for_method(
|
||||||
clip,
|
clip,
|
||||||
|
@ -264,7 +270,7 @@ impl<'gc> Loader<'gc> {
|
||||||
.as_movie_clip()
|
.as_movie_clip()
|
||||||
.expect("Attempted to load movie into not 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);
|
mc.post_instantiation(uc.gc_context, clip, avm.prototypes().movie_clip);
|
||||||
|
|
||||||
let mut morph_shapes = fnv::FnvHashMap::default();
|
let mut morph_shapes = fnv::FnvHashMap::default();
|
||||||
|
|
Loading…
Reference in New Issue