core: Add a `root_clip` method for `Stage` and make everything grabbing depth 0 off the stage use it

This commit is contained in:
David Wendt 2021-04-17 15:38:11 -04:00 committed by Mike Welsh
parent 36e486b1d0
commit 7f4a99ca60
9 changed files with 24 additions and 20 deletions

View File

@ -343,7 +343,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
) -> Self { ) -> Self {
let version = context.swf.version(); let version = context.swf.version();
let globals = context.avm1.global_object_cell(); 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) Self::from_nothing(context, id, version, globals, level0)
} }

View File

@ -8,7 +8,7 @@ use crate::avm1::property::Attribute;
use crate::avm1::{Object, ScriptObject, SoundObject, TObject, Value}; use crate::avm1::{Object, ScriptObject, SoundObject, TObject, Value};
use crate::avm_warn; use crate::avm_warn;
use crate::character::Character; use crate::character::Character;
use crate::display_object::{SoundTransform, TDisplayObject, TDisplayObjectContainer}; use crate::display_object::{SoundTransform, TDisplayObject};
use gc_arena::MutationContext; use gc_arena::MutationContext;
/// Implements `Sound` /// Implements `Sound`
@ -204,8 +204,8 @@ fn attach_sound<'gc>(
let name = name.coerce_to_string(activation)?; let name = name.coerce_to_string(activation)?;
let movie = sound_object let movie = sound_object
.owner() .owner()
.or_else(|| activation.context.stage.child_by_depth(0)) .unwrap_or_else(|| activation.context.stage.root_clip())
.and_then(|o| o.movie()); .movie();
if let Some(movie) = movie { if let Some(movie) = movie {
if let Some(Character::Sound(sound)) = activation if let Some(Character::Sound(sound)) = activation
.context .context
@ -539,8 +539,8 @@ fn stop<'gc>(
let name = name.coerce_to_string(activation)?; let name = name.coerce_to_string(activation)?;
let movie = sound let movie = sound
.owner() .owner()
.or_else(|| activation.context.stage.child_by_depth(0)) .unwrap_or_else(|| activation.context.stage.root_clip())
.and_then(|o| o.movie()); .movie();
if let Some(movie) = movie { if let Some(movie) = movie {
if let Some(Character::Sound(sound)) = activation if let Some(Character::Sound(sound)) = activation
.context .context

View File

@ -9,7 +9,6 @@
use crate::avm1::object::search_prototype; use crate::avm1::object::search_prototype;
use crate::avm1::{Activation, ActivationIdentifier, Object, TObject, Value}; use crate::avm1::{Activation, ActivationIdentifier, Object, TObject, Value};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use crate::display_object::TDisplayObjectContainer;
use gc_arena::Collect; use gc_arena::Collect;
use std::collections::{binary_heap::PeekMut, BinaryHeap}; use std::collections::{binary_heap::PeekMut, BinaryHeap};
@ -40,7 +39,7 @@ impl<'gc> Timers<'gc> {
let version = context.swf.header().version; let version = context.swf.header().version;
let globals = context.avm1.global_object_cell(); 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( let mut activation = Activation::from_nothing(
context.reborrow(), context.reborrow(),

View File

@ -160,7 +160,7 @@ impl<'a, 'gc, 'gc_context> UpdateContext<'a, 'gc, 'gc_context> {
self.audio, self.audio,
self.gc_context, self.gc_context,
self.action_queue, self.action_queue,
self.stage.child_by_depth(0).expect("root movie"), self.stage.root_clip(),
); );
} }

View File

@ -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> { impl<'gc> TDisplayObject<'gc> for Stage<'gc> {

View File

@ -7,7 +7,6 @@ use crate::avm1::{
AvmString as Avm1String, Object as Avm1Object, ScriptObject as Avm1ScriptObject, AvmString as Avm1String, Object as Avm1Object, ScriptObject as Avm1ScriptObject,
}; };
use crate::context::UpdateContext; use crate::context::UpdateContext;
use crate::display_object::TDisplayObjectContainer;
use gc_arena::Collect; use gc_arena::Collect;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@ -204,7 +203,7 @@ impl<'gc> Callback<'gc> {
) -> Value { ) -> Value {
match self { match self {
Callback::Avm1 { this, method } => { 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 swf_version = context.swf.version();
let globals = context.avm1.global_object_cell(); let globals = context.avm1.global_object_cell();
let mut activation = Avm1Activation::from_nothing( let mut activation = Avm1Activation::from_nothing(

View File

@ -43,7 +43,7 @@ impl<'gc> FocusTracker<'gc> {
log::info!("Focus is now on {:?}", focused_element); 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( Avm1::notify_system_listeners(
level0, level0,
context.swf.version(), context.swf.version(),

View File

@ -5,7 +5,7 @@ use crate::avm1::{Avm1, AvmString, Object, TObject, Value};
use crate::avm2::Domain as Avm2Domain; use crate::avm2::Domain as Avm2Domain;
use crate::backend::navigator::OwnedFuture; use crate::backend::navigator::OwnedFuture;
use crate::context::{ActionQueue, ActionType}; 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::player::{Player, NEWEST_PLAYER_VERSION};
use crate::property_map::PropertyMap; use crate::property_map::PropertyMap;
use crate::tag_utils::SwfMovie; use crate::tag_utils::SwfMovie;
@ -454,9 +454,7 @@ impl<'gc> Loader<'gc> {
_ => unreachable!(), _ => unreachable!(),
}; };
if let Some(root) = uc.stage.child_by_depth(0) { replacing_root_movie = DisplayObject::ptr_eq(clip, uc.stage.root_clip());
replacing_root_movie = DisplayObject::ptr_eq(clip, root);
}
clip.as_movie_clip().unwrap().unload(uc); clip.as_movie_clip().unwrap().unload(uc);

View File

@ -777,7 +777,7 @@ impl Player {
// Fire event listener on appropriate object // Fire event listener on appropriate object
if let Some((listener_type, event_name, args)) = listener { if let Some((listener_type, event_name, args)) = listener {
context.action_queue.queue_actions( context.action_queue.queue_actions(
context.stage.child_by_depth(0).expect("root level"), context.stage.root_clip(),
ActionType::NotifyListeners { ActionType::NotifyListeners {
listener: listener_type, listener: listener_type,
method: event_name, method: event_name,
@ -917,7 +917,7 @@ impl Player {
let mut is_action_script_3 = false; let mut is_action_script_3 = false;
self.mutate_with_update_context(|context| { self.mutate_with_update_context(|context| {
let mut morph_shapes = fnv::FnvHashMap::default(); 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() root.as_movie_clip()
.unwrap() .unwrap()
.preload(context, &mut morph_shapes); .preload(context, &mut morph_shapes);
@ -1249,8 +1249,8 @@ impl Player {
*current_frame = update_context *current_frame = update_context
.stage .stage
.child_by_depth(0) .root_clip()
.and_then(|root| root.as_movie_clip()) .as_movie_clip()
.map(|clip| clip.current_frame()); .map(|clip| clip.current_frame());
// Hovered object may have been updated; copy it back to the GC root. // Hovered object may have been updated; copy it back to the GC root.