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 {
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)
}

View File

@ -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

View File

@ -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(),

View File

@ -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(),
);
}

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> {

View File

@ -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(

View File

@ -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(),

View File

@ -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);

View File

@ -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.