avm1: Move frame lifecycle logic to `Avm1::run_frame`
This allows better encapsulation of AVM1.
This commit is contained in:
parent
397de91a2a
commit
0b7d8ea007
|
@ -3,13 +3,12 @@ use crate::avm1::globals::create_globals;
|
|||
use crate::avm1::object::stage_object;
|
||||
use crate::avm1::property_map::PropertyMap;
|
||||
use crate::context::UpdateContext;
|
||||
use crate::prelude::*;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
|
||||
use swf::avm1::read::Reader;
|
||||
|
||||
use crate::display_object::DisplayObject;
|
||||
use crate::frame_lifecycle::FramePhase;
|
||||
use crate::prelude::*;
|
||||
use crate::tag_utils::SwfSlice;
|
||||
use gc_arena::{Collect, GcCell, MutationContext};
|
||||
use swf::avm1::read::Reader;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
|
@ -424,12 +423,39 @@ impl<'gc> Avm1<'gc> {
|
|||
}
|
||||
|
||||
/// Returns an iterator over all movie clips in execution order.
|
||||
pub fn clip_exec_iter(&self) -> DisplayObjectIter<'gc> {
|
||||
fn clip_exec_iter(&self) -> DisplayObjectIter<'gc> {
|
||||
DisplayObjectIter {
|
||||
clip: self.clip_exec_list,
|
||||
}
|
||||
}
|
||||
|
||||
// Run a single frame.
|
||||
pub fn run_frame(context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
// In AVM1, we only ever execute the update phase, and all the work that
|
||||
// would ordinarily be phased is instead run all at once in whatever order
|
||||
// the SWF requests it.
|
||||
*context.frame_phase = FramePhase::Update;
|
||||
|
||||
// AVM1 execution order is determined by the global execution list, based on instantiation order.
|
||||
for clip in context.avm1.clip_exec_iter() {
|
||||
if clip.removed() {
|
||||
// Clean up removed objects from this frame or a previous frame.
|
||||
// Can be safely removed while iterating here, because the iterator advances
|
||||
// to the next node before returning the current node.
|
||||
context.avm1.remove_from_exec_list(context.gc_context, clip);
|
||||
} else {
|
||||
clip.run_frame(context);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire "onLoadInit" events.
|
||||
context
|
||||
.load_manager
|
||||
.movie_clip_on_load(context.action_queue);
|
||||
|
||||
*context.frame_phase = FramePhase::Idle;
|
||||
}
|
||||
|
||||
/// Adds a movie clip to the execution list.
|
||||
///
|
||||
/// This should be called whenever a movie clip is created, and controls the order of
|
||||
|
@ -450,7 +476,7 @@ impl<'gc> Avm1<'gc> {
|
|||
}
|
||||
|
||||
/// Removes a display object from the execution list.
|
||||
pub fn remove_from_exec_list(
|
||||
fn remove_from_exec_list(
|
||||
&mut self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
clip: DisplayObject<'gc>,
|
||||
|
@ -642,7 +668,7 @@ pub fn start_drag<'gc>(
|
|||
*activation.context.drag_object = Some(drag_object);
|
||||
}
|
||||
|
||||
pub struct DisplayObjectIter<'gc> {
|
||||
struct DisplayObjectIter<'gc> {
|
||||
clip: Option<DisplayObject<'gc>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -75,33 +75,6 @@ impl Default for FramePhase {
|
|||
}
|
||||
}
|
||||
|
||||
/// Run one frame according to AVM1 frame order.
|
||||
pub fn run_all_phases_avm1<'gc>(context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
// In AVM1, we only ever execute the update phase, and all the work that
|
||||
// would ordinarily be phased is instead run all at once in whatever order
|
||||
// the SWF requests it.
|
||||
*context.frame_phase = FramePhase::Update;
|
||||
|
||||
// AVM1 execution order is determined by the global execution list, based on instantiation order.
|
||||
for clip in context.avm1.clip_exec_iter() {
|
||||
if clip.removed() {
|
||||
// Clean up removed objects from this frame or a previous frame.
|
||||
// Can be safely removed while iterating here, because the iterator advances
|
||||
// to the next node before returning the current node.
|
||||
context.avm1.remove_from_exec_list(context.gc_context, clip);
|
||||
} else {
|
||||
clip.run_frame(context);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire "onLoadInit" events.
|
||||
context
|
||||
.load_manager
|
||||
.movie_clip_on_load(context.action_queue);
|
||||
|
||||
*context.frame_phase = FramePhase::Idle;
|
||||
}
|
||||
|
||||
/// Run one frame according to AVM2 frame order.
|
||||
pub fn run_all_phases_avm2<'gc>(context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
let stage = context.stage;
|
||||
|
|
|
@ -30,7 +30,7 @@ use crate::external::Value as ExternalValue;
|
|||
use crate::external::{ExternalInterface, ExternalInterfaceProvider};
|
||||
use crate::focus_tracker::FocusTracker;
|
||||
use crate::font::Font;
|
||||
use crate::frame_lifecycle::{run_all_phases_avm1, run_all_phases_avm2, FramePhase};
|
||||
use crate::frame_lifecycle::{run_all_phases_avm2, FramePhase};
|
||||
use crate::library::Library;
|
||||
use crate::loader::LoadManager;
|
||||
use crate::locale::get_current_date_time;
|
||||
|
@ -1340,7 +1340,7 @@ impl Player {
|
|||
if context.is_action_script_3() {
|
||||
run_all_phases_avm2(context);
|
||||
} else {
|
||||
run_all_phases_avm1(context);
|
||||
Avm1::run_frame(context);
|
||||
}
|
||||
context.update_sounds();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue