avm1: Only delay removals on AVM1, check for dynamic unload handlers
This commit is contained in:
parent
755425ebfa
commit
a356be15fe
|
@ -1,5 +1,6 @@
|
|||
//! Container mix-in for display objects
|
||||
|
||||
use crate::avm1::{Activation, ActivationIdentifier, TObject};
|
||||
use crate::avm2::{Avm2, EventObject as Avm2EventObject, Value as Avm2Value};
|
||||
use crate::context::{RenderContext, UpdateContext};
|
||||
use crate::display_object::avm1_button::Avm1Button;
|
||||
|
@ -308,14 +309,26 @@ pub trait TDisplayObjectContainer<'gc>:
|
|||
(*self).into()
|
||||
));
|
||||
|
||||
// Check if this child should have delayed removal
|
||||
if ChildContainer::should_delay_removal(child) {
|
||||
// Check if this child should have delayed removal (AVM1 only)
|
||||
if !context.is_action_script_3() {
|
||||
let should_delay_removal = {
|
||||
let mut activation = Activation::from_stub(
|
||||
context.reborrow(),
|
||||
ActivationIdentifier::root("[Unload Handler Check]"),
|
||||
);
|
||||
|
||||
ChildContainer::should_delay_removal(&mut activation, child)
|
||||
};
|
||||
|
||||
if should_delay_removal {
|
||||
ChildContainer::queue_removal(child, context);
|
||||
} else {
|
||||
self.remove_child_directly(context, child);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.remove_child_directly(context, child);
|
||||
}
|
||||
|
||||
/// Remove (and unloads) a child display object from this container's render and depth lists.
|
||||
fn remove_child_directly(
|
||||
&self,
|
||||
|
@ -798,18 +811,28 @@ impl<'gc> ChildContainer<'gc> {
|
|||
/// Should the removal of this clip be delayed to the start of the next frame
|
||||
///
|
||||
/// Checks recursively for unload handlers
|
||||
pub fn should_delay_removal(child: DisplayObject<'gc>) -> bool {
|
||||
pub fn should_delay_removal(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
child: DisplayObject<'gc>,
|
||||
) -> bool {
|
||||
// Do we have an unload event handler
|
||||
if let Some(mc) = child.as_movie_clip() {
|
||||
// If we have an unload handler, we need the delay
|
||||
if mc.has_unload_handler() {
|
||||
return true;
|
||||
// If we were created via timeline and we have a dynamic unload handler, we need the delay
|
||||
} else if !child.placed_by_script() {
|
||||
let obj = child.object().coerce_to_object(activation);
|
||||
if obj.has_property(activation, "onUnload".into()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, check children if we have them
|
||||
if let Some(c) = child.as_container() {
|
||||
for child in c.iter_render_list() {
|
||||
if Self::should_delay_removal(child) {
|
||||
if Self::should_delay_removal(activation, child) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,36 @@
|
|||
Frame 1:
|
||||
clip = _level0.clip
|
||||
clip._x = 125.5
|
||||
clip2 = _level0.clip2
|
||||
clip3 = _level0.clip3
|
||||
clip4 = _level0.clip4
|
||||
clip5 = _level0.clip5
|
||||
End frame 1
|
||||
Unload clip4
|
||||
unload clipEvent
|
||||
Unload clip5
|
||||
Frame 2
|
||||
clip = _level0.clip
|
||||
clip._x = 125.5
|
||||
clip2 = undefined
|
||||
clip3 = undefined
|
||||
clip4 = undefined
|
||||
clip5 = _level0.clip5
|
||||
End frame 2
|
||||
unload clipEvent
|
||||
unload clipEvent 2
|
||||
Frame 3
|
||||
clip = undefined
|
||||
clip = _level0.clip
|
||||
clip._x = 429.95
|
||||
clip2 = undefined
|
||||
clip3 = undefined
|
||||
clip4 = undefined
|
||||
clip5 = undefined
|
||||
End frame 3
|
||||
Frame 4
|
||||
clip = undefined
|
||||
clip._x = undefined
|
||||
clip2 = undefined
|
||||
clip3 = undefined
|
||||
clip4 = undefined
|
||||
clip5 = undefined
|
||||
End frame 4
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue