From 8096146a0deba6dfdeead1cb09a677bd59c75e05 Mon Sep 17 00:00:00 2001 From: Lord-McSweeney Date: Mon, 6 Nov 2023 19:05:18 -0800 Subject: [PATCH] avm1: Correctly mark unloaded movies as unloaded instead of relying on depth --- core/src/display_object.rs | 25 +++++++++++++++++++++---- core/src/display_object/container.rs | 1 + 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/core/src/display_object.rs b/core/src/display_object.rs index 073c186fe..c865b4ab3 100644 --- a/core/src/display_object.rs +++ b/core/src/display_object.rs @@ -556,6 +556,11 @@ impl<'gc> DisplayObjectBase<'gc> { self.flags.contains(DisplayObjectFlags::AVM1_REMOVED) } + fn avm1_pending_removal(&self) -> bool { + self.flags + .contains(DisplayObjectFlags::AVM1_PENDING_REMOVAL) + } + pub fn should_skip_next_enter_frame(&self) -> bool { self.flags .contains(DisplayObjectFlags::SKIP_NEXT_ENTER_FRAME) @@ -570,6 +575,11 @@ impl<'gc> DisplayObjectBase<'gc> { self.flags.set(DisplayObjectFlags::AVM1_REMOVED, value); } + fn set_avm1_pending_removal(&mut self, value: bool) { + self.flags + .set(DisplayObjectFlags::AVM1_PENDING_REMOVAL, value); + } + fn scale_rotation_cached(&self) -> bool { self.flags .contains(DisplayObjectFlags::SCALE_ROTATION_CACHED) @@ -1650,7 +1660,11 @@ pub trait TDisplayObject<'gc>: /// Is this object waiting to be removed on the start of the next frame fn avm1_pending_removal(&self) -> bool { - self.depth() < 0 + self.base().avm1_pending_removal() + } + + fn set_avm1_pending_removal(&self, gc_context: &Mutation<'gc>, value: bool) { + self.base_mut(gc_context).set_avm1_pending_removal(value) } /// Whether this display object is visible. @@ -2394,7 +2408,7 @@ bitflags! { struct DisplayObjectFlags: u16 { /// Whether this object has been removed from the display list. /// Necessary in AVM1 to throw away queued actions from removed movie clips. - const AVM1_REMOVED = 1 << 0; + const AVM1_REMOVED = 1 << 0; /// If this object is visible (`_visible` property). const VISIBLE = 1 << 1; @@ -2436,10 +2450,13 @@ bitflags! { /// This is set for objects constructed from ActionScript, /// which are observed to lag behind objects placed by the timeline /// (even if they are both placed in the same frame) - const SKIP_NEXT_ENTER_FRAME = 1 << 11; + const SKIP_NEXT_ENTER_FRAME = 1 << 11; /// If this object has already had `invalidate_cached_bitmap` called this frame - const CACHE_INVALIDATED = 1 << 12; + const CACHE_INVALIDATED = 1 << 12; + + /// If this AVM1 object is pending removal (will be removed on the next frame). + const AVM1_PENDING_REMOVAL = 1 << 13; } } diff --git a/core/src/display_object/container.rs b/core/src/display_object/container.rs index 21a3419a1..39c25fcdd 100644 --- a/core/src/display_object/container.rs +++ b/core/src/display_object/container.rs @@ -1018,6 +1018,7 @@ impl<'gc> ChildContainer<'gc> { let cur_depth = child.depth(); // Note that the depth returned by AS will be offset by the `AVM_DEPTH_BIAS`, so this is really `-(cur_depth+1+AVM_DEPTH_BIAS)` child.set_depth(context.gc_context, -cur_depth - 1); + child.set_avm1_pending_removal(context.gc_context, true); if let Some(mc) = child.as_movie_clip() { // Clip events should still fire