From 7f4a99ca60402a3d9f75d30e072f645532446c30 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sat, 17 Apr 2021 15:38:11 -0400 Subject: [PATCH] core: Add a `root_clip` method for `Stage` and make everything grabbing depth 0 off the stage use it --- core/src/avm1/activation.rs | 2 +- core/src/avm1/globals/sound.rs | 10 +++++----- core/src/avm1/timer.rs | 3 +-- core/src/context.rs | 2 +- core/src/display_object/stage.rs | 8 ++++++++ core/src/external.rs | 3 +-- core/src/focus_tracker.rs | 2 +- core/src/loader.rs | 6 ++---- core/src/player.rs | 8 ++++---- 9 files changed, 24 insertions(+), 20 deletions(-) diff --git a/core/src/avm1/activation.rs b/core/src/avm1/activation.rs index 9a46f0a4e..b4f6ee547 100644 --- a/core/src/avm1/activation.rs +++ b/core/src/avm1/activation.rs @@ -343,7 +343,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> { ) -> Self { let version = context.swf.version(); let globals = context.avm1.global_object_cell(); - let level0 = context.stage.child_by_depth(0).unwrap(); + let level0 = context.stage.root_clip(); Self::from_nothing(context, id, version, globals, level0) } diff --git a/core/src/avm1/globals/sound.rs b/core/src/avm1/globals/sound.rs index 3a6474bb9..355024aa3 100644 --- a/core/src/avm1/globals/sound.rs +++ b/core/src/avm1/globals/sound.rs @@ -8,7 +8,7 @@ use crate::avm1::property::Attribute; use crate::avm1::{Object, ScriptObject, SoundObject, TObject, Value}; use crate::avm_warn; use crate::character::Character; -use crate::display_object::{SoundTransform, TDisplayObject, TDisplayObjectContainer}; +use crate::display_object::{SoundTransform, TDisplayObject}; use gc_arena::MutationContext; /// Implements `Sound` @@ -204,8 +204,8 @@ fn attach_sound<'gc>( let name = name.coerce_to_string(activation)?; let movie = sound_object .owner() - .or_else(|| activation.context.stage.child_by_depth(0)) - .and_then(|o| o.movie()); + .unwrap_or_else(|| activation.context.stage.root_clip()) + .movie(); if let Some(movie) = movie { if let Some(Character::Sound(sound)) = activation .context @@ -539,8 +539,8 @@ fn stop<'gc>( let name = name.coerce_to_string(activation)?; let movie = sound .owner() - .or_else(|| activation.context.stage.child_by_depth(0)) - .and_then(|o| o.movie()); + .unwrap_or_else(|| activation.context.stage.root_clip()) + .movie(); if let Some(movie) = movie { if let Some(Character::Sound(sound)) = activation .context diff --git a/core/src/avm1/timer.rs b/core/src/avm1/timer.rs index b0c70a4e2..422baece7 100644 --- a/core/src/avm1/timer.rs +++ b/core/src/avm1/timer.rs @@ -9,7 +9,6 @@ use crate::avm1::object::search_prototype; use crate::avm1::{Activation, ActivationIdentifier, Object, TObject, Value}; use crate::context::UpdateContext; -use crate::display_object::TDisplayObjectContainer; use gc_arena::Collect; use std::collections::{binary_heap::PeekMut, BinaryHeap}; @@ -40,7 +39,7 @@ impl<'gc> Timers<'gc> { let version = context.swf.header().version; let globals = context.avm1.global_object_cell(); - let level0 = context.stage.child_by_depth(0).expect("root movie"); + let level0 = context.stage.root_clip(); let mut activation = Activation::from_nothing( context.reborrow(), diff --git a/core/src/context.rs b/core/src/context.rs index 4968796fe..eb43b0212 100644 --- a/core/src/context.rs +++ b/core/src/context.rs @@ -160,7 +160,7 @@ impl<'a, 'gc, 'gc_context> UpdateContext<'a, 'gc, 'gc_context> { self.audio, self.gc_context, self.action_queue, - self.stage.child_by_depth(0).expect("root movie"), + self.stage.root_clip(), ); } diff --git a/core/src/display_object/stage.rs b/core/src/display_object/stage.rs index 3898f959d..d481ac434 100644 --- a/core/src/display_object/stage.rs +++ b/core/src/display_object/stage.rs @@ -236,6 +236,14 @@ impl<'gc> Stage<'gc> { ); } } + + /// Obtain the root movie on the stage. + /// + /// `Stage` guarantees that there is always a movie clip at depth 0. + pub fn root_clip(self) -> DisplayObject<'gc> { + self.child_by_depth(0) + .expect("Stage must always have a root movie") + } } impl<'gc> TDisplayObject<'gc> for Stage<'gc> { diff --git a/core/src/external.rs b/core/src/external.rs index 666dc2737..b26272e1b 100644 --- a/core/src/external.rs +++ b/core/src/external.rs @@ -7,7 +7,6 @@ use crate::avm1::{ AvmString as Avm1String, Object as Avm1Object, ScriptObject as Avm1ScriptObject, }; use crate::context::UpdateContext; -use crate::display_object::TDisplayObjectContainer; use gc_arena::Collect; use std::collections::BTreeMap; @@ -204,7 +203,7 @@ impl<'gc> Callback<'gc> { ) -> Value { match self { Callback::Avm1 { this, method } => { - let base_clip = context.stage.child_by_depth(0).unwrap(); + let base_clip = context.stage.root_clip(); let swf_version = context.swf.version(); let globals = context.avm1.global_object_cell(); let mut activation = Avm1Activation::from_nothing( diff --git a/core/src/focus_tracker.rs b/core/src/focus_tracker.rs index d3a92bce2..c7e66bd2e 100644 --- a/core/src/focus_tracker.rs +++ b/core/src/focus_tracker.rs @@ -43,7 +43,7 @@ impl<'gc> FocusTracker<'gc> { log::info!("Focus is now on {:?}", focused_element); - let level0 = context.stage.child_by_depth(0).unwrap(); + let level0 = context.stage.root_clip(); Avm1::notify_system_listeners( level0, context.swf.version(), diff --git a/core/src/loader.rs b/core/src/loader.rs index e2a937999..011f5c200 100644 --- a/core/src/loader.rs +++ b/core/src/loader.rs @@ -5,7 +5,7 @@ use crate::avm1::{Avm1, AvmString, Object, TObject, Value}; use crate::avm2::Domain as Avm2Domain; use crate::backend::navigator::OwnedFuture; use crate::context::{ActionQueue, ActionType}; -use crate::display_object::{DisplayObject, MorphShape, TDisplayObject, TDisplayObjectContainer}; +use crate::display_object::{DisplayObject, MorphShape, TDisplayObject}; use crate::player::{Player, NEWEST_PLAYER_VERSION}; use crate::property_map::PropertyMap; use crate::tag_utils::SwfMovie; @@ -454,9 +454,7 @@ impl<'gc> Loader<'gc> { _ => unreachable!(), }; - if let Some(root) = uc.stage.child_by_depth(0) { - replacing_root_movie = DisplayObject::ptr_eq(clip, root); - } + replacing_root_movie = DisplayObject::ptr_eq(clip, uc.stage.root_clip()); clip.as_movie_clip().unwrap().unload(uc); diff --git a/core/src/player.rs b/core/src/player.rs index 570ecfa34..704f13b0a 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -777,7 +777,7 @@ impl Player { // Fire event listener on appropriate object if let Some((listener_type, event_name, args)) = listener { context.action_queue.queue_actions( - context.stage.child_by_depth(0).expect("root level"), + context.stage.root_clip(), ActionType::NotifyListeners { listener: listener_type, method: event_name, @@ -917,7 +917,7 @@ impl Player { let mut is_action_script_3 = false; self.mutate_with_update_context(|context| { let mut morph_shapes = fnv::FnvHashMap::default(); - let root = context.stage.child_by_depth(0).expect("root level"); + let root = context.stage.root_clip(); root.as_movie_clip() .unwrap() .preload(context, &mut morph_shapes); @@ -1249,8 +1249,8 @@ impl Player { *current_frame = update_context .stage - .child_by_depth(0) - .and_then(|root| root.as_movie_clip()) + .root_clip() + .as_movie_clip() .map(|clip| clip.current_frame()); // Hovered object may have been updated; copy it back to the GC root.