Skip to content

Commit c5dfc2d

Browse files
core: Improve AVM2 in AVM1
AVM2 movies loaded into AVM1 will now fire events to AVM1
1 parent 8e144db commit c5dfc2d

File tree

4 files changed

+25
-13
lines changed

4 files changed

+25
-13
lines changed

core/src/display_object.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,9 @@ pub trait TDisplayObject<'gc>:
17651765
/// Returns the dot-syntax path to this display object, e.g. `_level0.foo.clip`
17661766
#[no_dynamic]
17671767
fn path(self) -> WString {
1768+
// FIXME this method doesn't work correclty when this DO is from an
1769+
// AVM2 movie that was loaded into AVM1
1770+
17681771
if let Some(parent) = self.avm1_parent() {
17691772
let mut path = parent.path();
17701773
path.push_byte(b'.');

core/src/display_object/movie_clip.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,6 @@ pub struct MovieClipData<'gc> {
187187
attached_audio: Lock<Option<NetStream<'gc>>>,
188188

189189
/// The next MovieClip in the AVM1 execution list.
190-
///
191-
/// `None` in an AVM2 movie.
192190
next_avm1_clip: Lock<Option<MovieClip<'gc>>>,
193191

194192
audio_stream: Cell<Option<SoundInstanceHandle>>,
@@ -421,8 +419,8 @@ impl<'gc> MovieClip<'gc> {
421419

422420
/// Execute all other timeline actions on this object.
423421
pub fn run_frame_avm1(self, context: &mut UpdateContext<'gc>) {
424-
if !self.movie().is_action_script_3() {
425-
// Run my load/enterFrame clip event.
422+
// Run my load/enterFrame clip event.
423+
if !self.movie().is_action_script_3() || !context.root_swf.is_action_script_3() {
426424
let is_load_frame = !self.0.contains_flag(MovieClipFlags::INITIALIZED);
427425
if is_load_frame {
428426
self.event_dispatch(context, ClipEvent::Load);
@@ -2608,7 +2606,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
26082606

26092607
self.set_default_instance_name(context);
26102608

2611-
if !self.movie().is_action_script_3() {
2609+
if !self.movie().is_action_script_3() || !context.root_swf.is_action_script_3() {
26122610
context.avm1.add_to_exec_list(context.gc(), self);
26132611

26142612
self.construct_as_avm1_object(context, init_object, instantiated_by, run_frame);

core/src/frame_lifecycle.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,30 +73,40 @@ pub fn run_all_phases_avm2(context: &mut UpdateContext<'_>) {
7373
let stage = context.stage;
7474

7575
// We may still have AVM2 orphans that we need to run frames for even though
76-
// the root movie is AVM1 (TODO: is that correct?)
76+
// the root movie is AVM1. However, we don't run any stage phases if the
77+
// root movie is AVM1.
78+
let is_as3_root = stage.movie().is_action_script_3();
7779

7880
*context.frame_phase = FramePhase::Enter;
7981
OrphanManager::each_orphan_obj(context, |orphan, context| {
8082
orphan.enter_frame(context);
8183
});
82-
stage.enter_frame(context);
84+
if is_as3_root {
85+
stage.enter_frame(context);
86+
}
8387

8488
*context.frame_phase = FramePhase::Construct;
8589
OrphanManager::each_orphan_obj(context, |orphan, context| {
8690
orphan.construct_frame(context);
8791
});
88-
stage.construct_frame(context);
89-
stage.frame_constructed(context);
92+
if is_as3_root {
93+
stage.construct_frame(context);
94+
stage.frame_constructed(context);
95+
}
9096

9197
*context.frame_phase = FramePhase::FrameScripts;
9298
OrphanManager::each_orphan_obj(context, |orphan, context| {
9399
orphan.run_frame_scripts(context);
94100
});
95-
stage.run_frame_scripts(context);
101+
if is_as3_root {
102+
stage.run_frame_scripts(context);
103+
}
96104
MovieClip::run_frame_script_cleanup(context);
97105

98106
*context.frame_phase = FramePhase::Exit;
99-
stage.exit_frame(context);
107+
if is_as3_root {
108+
stage.exit_frame(context);
109+
}
100110

101111
// We cannot easily remove dead `GcWeak` instances from the orphan list
102112
// inside `each_orphan_movie`, since the callback may modify the orphan list.

core/src/orphan_manager.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ impl<'gc> OrphanManager<'gc> {
9090
// any orphan we see that has 'placed_by_script()' should stay on the orphan
9191
// list, because it was not removed by a RemoveObject tag.
9292
//
93-
// Also, AVM2 MovieClips with an AVM1 parent are always orphans, since they
94-
// would not run their frames if they weren't.
93+
// Also, we consider AVM2 MovieClips loaded into an AVM1 parent to always
94+
// be orphans, since we know they were placed by AVM1 code and not by
95+
// the timeline.
9596
dobj.placed_by_script() || has_avm1_parent
9697
} else {
9798
false

0 commit comments

Comments
 (0)