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::object::stage_object;
|
||||||
use crate::avm1::property_map::PropertyMap;
|
use crate::avm1::property_map::PropertyMap;
|
||||||
use crate::context::UpdateContext;
|
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::display_object::DisplayObject;
|
||||||
|
use crate::frame_lifecycle::FramePhase;
|
||||||
|
use crate::prelude::*;
|
||||||
use crate::tag_utils::SwfSlice;
|
use crate::tag_utils::SwfSlice;
|
||||||
|
use gc_arena::{Collect, GcCell, MutationContext};
|
||||||
|
use swf::avm1::read::Reader;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -424,12 +423,39 @@ impl<'gc> Avm1<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over all movie clips in execution order.
|
/// 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 {
|
DisplayObjectIter {
|
||||||
clip: self.clip_exec_list,
|
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.
|
/// Adds a movie clip to the execution list.
|
||||||
///
|
///
|
||||||
/// This should be called whenever a movie clip is created, and controls the order of
|
/// 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.
|
/// Removes a display object from the execution list.
|
||||||
pub fn remove_from_exec_list(
|
fn remove_from_exec_list(
|
||||||
&mut self,
|
&mut self,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
gc_context: MutationContext<'gc, '_>,
|
||||||
clip: DisplayObject<'gc>,
|
clip: DisplayObject<'gc>,
|
||||||
|
@ -642,7 +668,7 @@ pub fn start_drag<'gc>(
|
||||||
*activation.context.drag_object = Some(drag_object);
|
*activation.context.drag_object = Some(drag_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DisplayObjectIter<'gc> {
|
struct DisplayObjectIter<'gc> {
|
||||||
clip: Option<DisplayObject<'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.
|
/// Run one frame according to AVM2 frame order.
|
||||||
pub fn run_all_phases_avm2<'gc>(context: &mut UpdateContext<'_, 'gc, '_>) {
|
pub fn run_all_phases_avm2<'gc>(context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
let stage = context.stage;
|
let stage = context.stage;
|
||||||
|
|
|
@ -30,7 +30,7 @@ use crate::external::Value as ExternalValue;
|
||||||
use crate::external::{ExternalInterface, ExternalInterfaceProvider};
|
use crate::external::{ExternalInterface, ExternalInterfaceProvider};
|
||||||
use crate::focus_tracker::FocusTracker;
|
use crate::focus_tracker::FocusTracker;
|
||||||
use crate::font::Font;
|
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::library::Library;
|
||||||
use crate::loader::LoadManager;
|
use crate::loader::LoadManager;
|
||||||
use crate::locale::get_current_date_time;
|
use crate::locale::get_current_date_time;
|
||||||
|
@ -1340,7 +1340,7 @@ impl Player {
|
||||||
if context.is_action_script_3() {
|
if context.is_action_script_3() {
|
||||||
run_all_phases_avm2(context);
|
run_all_phases_avm2(context);
|
||||||
} else {
|
} else {
|
||||||
run_all_phases_avm1(context);
|
Avm1::run_frame(context);
|
||||||
}
|
}
|
||||||
context.update_sounds();
|
context.update_sounds();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue