avm1: Refactor to expose `avm, context` in `post_instantiate`
This commit is contained in:
parent
223edb9bc1
commit
d850443c84
|
@ -940,7 +940,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
/// If the level does not exist, then it will be created and instantiated
|
/// If the level does not exist, then it will be created and instantiated
|
||||||
/// with a script object.
|
/// with a script object.
|
||||||
pub fn resolve_level(
|
pub fn resolve_level(
|
||||||
&self,
|
&mut self,
|
||||||
level_id: u32,
|
level_id: u32,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> DisplayObject<'gc> {
|
) -> DisplayObject<'gc> {
|
||||||
|
@ -950,7 +950,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
let mut level: DisplayObject<'_> =
|
let mut level: DisplayObject<'_> =
|
||||||
MovieClip::new(NEWEST_PLAYER_VERSION, context.gc_context).into();
|
MovieClip::new(NEWEST_PLAYER_VERSION, context.gc_context).into();
|
||||||
|
|
||||||
level.post_instantiation(context.gc_context, level, self.prototypes.movie_clip);
|
level.post_instantiation(self, context, level);
|
||||||
level.set_depth(context.gc_context, level_id as i32);
|
level.set_depth(context.gc_context, level_id as i32);
|
||||||
context.levels.insert(level_id, level);
|
context.levels.insert(level_id, level);
|
||||||
|
|
||||||
|
@ -1765,7 +1765,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
if let Some(clip) = self.target_clip() {
|
if let Some(clip) = self.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
// The frame on the stack is 0-based, not 1-based.
|
// The frame on the stack is 0-based, not 1-based.
|
||||||
clip.goto_frame(context, frame + 1, true);
|
clip.goto_frame(self, context, frame + 1, true);
|
||||||
} else {
|
} else {
|
||||||
log::error!("GotoFrame failed: Target is not a MovieClip");
|
log::error!("GotoFrame failed: Target is not a MovieClip");
|
||||||
}
|
}
|
||||||
|
@ -1811,7 +1811,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
if let Some(clip) = self.target_clip() {
|
if let Some(clip) = self.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
if let Some(frame) = clip.frame_label_to_number(label) {
|
if let Some(frame) = clip.frame_label_to_number(label) {
|
||||||
clip.goto_frame(context, frame, true);
|
clip.goto_frame(self, context, frame, true);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("GoToLabel: Frame label '{}' not found", label);
|
log::warn!("GoToLabel: Frame label '{}' not found", label);
|
||||||
}
|
}
|
||||||
|
@ -2013,7 +2013,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
fn action_next_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
fn action_next_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
||||||
if let Some(clip) = self.target_clip() {
|
if let Some(clip) = self.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
clip.next_frame(context);
|
clip.next_frame(self, context);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("NextFrame: Target is not a MovieClip");
|
log::warn!("NextFrame: Target is not a MovieClip");
|
||||||
}
|
}
|
||||||
|
@ -2126,7 +2126,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
fn action_prev_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
fn action_prev_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
||||||
if let Some(clip) = self.target_clip() {
|
if let Some(clip) = self.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
clip.prev_frame(context);
|
clip.prev_frame(self, context);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("PrevFrame: Target is not a MovieClip");
|
log::warn!("PrevFrame: Target is not a MovieClip");
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,14 +229,13 @@ fn attach_movie<'gc>(
|
||||||
.library
|
.library
|
||||||
.library_for_movie(movie_clip.movie().unwrap())
|
.library_for_movie(movie_clip.movie().unwrap())
|
||||||
.ok_or_else(|| "Movie is missing!".into())
|
.ok_or_else(|| "Movie is missing!".into())
|
||||||
.and_then(|l| {
|
.and_then(|l| l.instantiate_by_export_name(&export_name, context.gc_context))
|
||||||
l.instantiate_by_export_name(&export_name, context.gc_context, &avm.prototypes)
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
|
new_clip.post_instantiation(avm, context, new_clip);
|
||||||
// Set name and attach to parent.
|
// Set name and attach to parent.
|
||||||
new_clip.set_name(context.gc_context, &new_instance_name);
|
new_clip.set_name(context.gc_context, &new_instance_name);
|
||||||
movie_clip.add_child_from_avm(context, new_clip, depth);
|
movie_clip.add_child_from_avm(context, new_clip, depth);
|
||||||
new_clip.run_frame(context);
|
new_clip.run_frame(avm, context);
|
||||||
|
|
||||||
// Copy properties from init_object to the movieclip.
|
// Copy properties from init_object to the movieclip.
|
||||||
let new_clip = new_clip.object().as_object().unwrap();
|
let new_clip = new_clip.object().as_object().unwrap();
|
||||||
|
@ -272,16 +271,12 @@ fn create_empty_movie_clip<'gc>(
|
||||||
|
|
||||||
// Create empty movie clip.
|
// Create empty movie clip.
|
||||||
let mut new_clip = MovieClip::new(avm.current_swf_version(), context.gc_context);
|
let mut new_clip = MovieClip::new(avm.current_swf_version(), context.gc_context);
|
||||||
new_clip.post_instantiation(
|
new_clip.post_instantiation(avm, context, new_clip.into());
|
||||||
context.gc_context,
|
|
||||||
new_clip.into(),
|
|
||||||
avm.prototypes.movie_clip,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set name and attach to parent.
|
// Set name and attach to parent.
|
||||||
new_clip.set_name(context.gc_context, &new_instance_name);
|
new_clip.set_name(context.gc_context, &new_instance_name);
|
||||||
movie_clip.add_child_from_avm(context, new_clip.into(), depth);
|
movie_clip.add_child_from_avm(context, new_clip.into(), depth);
|
||||||
new_clip.run_frame(context);
|
new_clip.run_frame(avm, context);
|
||||||
|
|
||||||
Ok(new_clip.object().into())
|
Ok(new_clip.object().into())
|
||||||
}
|
}
|
||||||
|
@ -326,7 +321,7 @@ fn create_text_field<'gc>(
|
||||||
|
|
||||||
let mut text_field: DisplayObject<'gc> =
|
let mut text_field: DisplayObject<'gc> =
|
||||||
EditText::new(context, movie, x, y, width, height).into();
|
EditText::new(context, movie, x, y, width, height).into();
|
||||||
text_field.post_instantiation(context.gc_context, text_field, avm.prototypes().text_field);
|
text_field.post_instantiation(avm, context, text_field);
|
||||||
text_field.set_name(context.gc_context, &instance_name);
|
text_field.set_name(context.gc_context, &instance_name);
|
||||||
movie_clip.add_child_from_avm(context, text_field, depth as Depth);
|
movie_clip.add_child_from_avm(context, text_field, depth as Depth);
|
||||||
|
|
||||||
|
@ -384,8 +379,10 @@ pub fn duplicate_movie_clip_with_bias<'gc>(
|
||||||
.library
|
.library
|
||||||
.library_for_movie(movie_clip.movie().unwrap())
|
.library_for_movie(movie_clip.movie().unwrap())
|
||||||
.ok_or_else(|| "Movie is missing!".into())
|
.ok_or_else(|| "Movie is missing!".into())
|
||||||
.and_then(|l| l.instantiate_by_id(movie_clip.id(), context.gc_context, &avm.prototypes))
|
.and_then(|l| l.instantiate_by_id(movie_clip.id(), context.gc_context))
|
||||||
{
|
{
|
||||||
|
new_clip.post_instantiation(avm, context, new_clip);
|
||||||
|
|
||||||
// Set name and attach to parent.
|
// Set name and attach to parent.
|
||||||
new_clip.set_name(context.gc_context, &new_instance_name);
|
new_clip.set_name(context.gc_context, &new_instance_name);
|
||||||
parent.add_child_from_avm(context, new_clip, depth);
|
parent.add_child_from_avm(context, new_clip, depth);
|
||||||
|
@ -395,7 +392,7 @@ pub fn duplicate_movie_clip_with_bias<'gc>(
|
||||||
new_clip.set_color_transform(context.gc_context, &*movie_clip.color_transform());
|
new_clip.set_color_transform(context.gc_context, &*movie_clip.color_transform());
|
||||||
// TODO: Any other properties we should copy...?
|
// TODO: Any other properties we should copy...?
|
||||||
// Definitely not ScriptObject properties.
|
// Definitely not ScriptObject properties.
|
||||||
new_clip.run_frame(context);
|
new_clip.run_frame(avm, context);
|
||||||
|
|
||||||
// Copy properties from init_object to the movieclip.
|
// Copy properties from init_object to the movieclip.
|
||||||
let new_clip = new_clip.object().as_object().unwrap();
|
let new_clip = new_clip.object().as_object().unwrap();
|
||||||
|
@ -506,7 +503,7 @@ pub fn goto_frame<'gc>(
|
||||||
frame = frame.wrapping_sub(1);
|
frame = frame.wrapping_sub(1);
|
||||||
frame = frame.wrapping_add(i32::from(scene_offset));
|
frame = frame.wrapping_add(i32::from(scene_offset));
|
||||||
if frame >= 0 {
|
if frame >= 0 {
|
||||||
movie_clip.goto_frame(context, frame.saturating_add(1) as u16, stop);
|
movie_clip.goto_frame(avm, context, frame.saturating_add(1) as u16, stop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val => {
|
val => {
|
||||||
|
@ -514,7 +511,7 @@ pub fn goto_frame<'gc>(
|
||||||
let frame_label = val.clone().coerce_to_string(avm, context)?;
|
let frame_label = val.clone().coerce_to_string(avm, context)?;
|
||||||
if let Some(mut frame) = movie_clip.frame_label_to_number(&frame_label) {
|
if let Some(mut frame) = movie_clip.frame_label_to_number(&frame_label) {
|
||||||
frame = frame.wrapping_add(scene_offset);
|
frame = frame.wrapping_add(scene_offset);
|
||||||
movie_clip.goto_frame(context, frame, stop);
|
movie_clip.goto_frame(avm, context, frame, stop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,11 +520,11 @@ pub fn goto_frame<'gc>(
|
||||||
|
|
||||||
fn next_frame<'gc>(
|
fn next_frame<'gc>(
|
||||||
movie_clip: MovieClip<'gc>,
|
movie_clip: MovieClip<'gc>,
|
||||||
_avm: &mut Avm1<'gc>,
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<ReturnValue<'gc>, Error> {
|
) -> Result<ReturnValue<'gc>, Error> {
|
||||||
movie_clip.next_frame(context);
|
movie_clip.next_frame(avm, context);
|
||||||
Ok(Value::Undefined.into())
|
Ok(Value::Undefined.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,11 +540,11 @@ fn play<'gc>(
|
||||||
|
|
||||||
fn prev_frame<'gc>(
|
fn prev_frame<'gc>(
|
||||||
movie_clip: MovieClip<'gc>,
|
movie_clip: MovieClip<'gc>,
|
||||||
_avm: &mut Avm1<'gc>,
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<ReturnValue<'gc>, Error> {
|
) -> Result<ReturnValue<'gc>, Error> {
|
||||||
movie_clip.prev_frame(context);
|
movie_clip.prev_frame(avm, context);
|
||||||
Ok(Value::Undefined.into())
|
Ok(Value::Undefined.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -587,7 +587,6 @@ mod tests {
|
||||||
let mut avm = Avm1::new(gc_context, swf_version);
|
let mut avm = Avm1::new(gc_context, swf_version);
|
||||||
let swf = Arc::new(SwfMovie::empty(swf_version));
|
let swf = Arc::new(SwfMovie::empty(swf_version));
|
||||||
let mut root: DisplayObject<'_> = MovieClip::new(swf_version, gc_context).into();
|
let mut root: DisplayObject<'_> = MovieClip::new(swf_version, gc_context).into();
|
||||||
root.post_instantiation(gc_context, root, avm.prototypes().movie_clip);
|
|
||||||
root.set_depth(gc_context, 0);
|
root.set_depth(gc_context, 0);
|
||||||
let mut levels = BTreeMap::new();
|
let mut levels = BTreeMap::new();
|
||||||
levels.insert(0, root);
|
levels.insert(0, root);
|
||||||
|
@ -620,6 +619,8 @@ mod tests {
|
||||||
load_manager: &mut LoadManager::new(),
|
load_manager: &mut LoadManager::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
root.post_instantiation(&mut avm, &mut context, root);
|
||||||
|
|
||||||
let object = ScriptObject::object(gc_context, Some(avm.prototypes().object)).into();
|
let object = ScriptObject::object(gc_context, Some(avm.prototypes().object)).into();
|
||||||
|
|
||||||
let globals = avm.global_object_cell();
|
let globals = avm.global_object_cell();
|
||||||
|
|
|
@ -26,7 +26,6 @@ where
|
||||||
let mut avm = Avm1::new(gc_context, swf_version);
|
let mut avm = Avm1::new(gc_context, swf_version);
|
||||||
let swf = Arc::new(SwfMovie::empty(swf_version));
|
let swf = Arc::new(SwfMovie::empty(swf_version));
|
||||||
let mut root: DisplayObject<'_> = MovieClip::new(swf_version, gc_context).into();
|
let mut root: DisplayObject<'_> = MovieClip::new(swf_version, gc_context).into();
|
||||||
root.post_instantiation(gc_context, root, avm.prototypes().movie_clip);
|
|
||||||
root.set_depth(gc_context, 0);
|
root.set_depth(gc_context, 0);
|
||||||
let mut levels = BTreeMap::new();
|
let mut levels = BTreeMap::new();
|
||||||
levels.insert(0, root);
|
levels.insert(0, root);
|
||||||
|
@ -58,6 +57,7 @@ where
|
||||||
player: None,
|
player: None,
|
||||||
load_manager: &mut LoadManager::new(),
|
load_manager: &mut LoadManager::new(),
|
||||||
};
|
};
|
||||||
|
root.post_instantiation(&mut avm, &mut context, root);
|
||||||
|
|
||||||
let globals = avm.global_object_cell();
|
let globals = avm.global_object_cell();
|
||||||
avm.insert_stack_frame(GcCell::allocate(
|
avm.insert_stack_frame(GcCell::allocate(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::avm1::{Object, TObject, Value};
|
use crate::avm1::{Avm1, TObject, Value};
|
||||||
use crate::context::{RenderContext, UpdateContext};
|
use crate::context::{RenderContext, UpdateContext};
|
||||||
use crate::player::NEWEST_PLAYER_VERSION;
|
use crate::player::NEWEST_PLAYER_VERSION;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -726,7 +726,7 @@ pub trait TDisplayObject<'gc>: 'gc + Collect + Debug + Into<DisplayObject<'gc>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, _context: &mut UpdateContext<'_, 'gc, '_>) {}
|
fn run_frame(&mut self, _avm: &mut Avm1<'gc>, _context: &mut UpdateContext<'_, 'gc, '_>) {}
|
||||||
fn render(&self, _context: &mut RenderContext<'_, 'gc>) {}
|
fn render(&self, _context: &mut RenderContext<'_, 'gc>) {}
|
||||||
fn unload(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
fn unload(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
self.set_removed(context.gc_context, true);
|
self.set_removed(context.gc_context, true);
|
||||||
|
@ -823,9 +823,9 @@ pub trait TDisplayObject<'gc>: 'gc + Collect + Debug + Into<DisplayObject<'gc>>
|
||||||
|
|
||||||
fn post_instantiation(
|
fn post_instantiation(
|
||||||
&mut self,
|
&mut self,
|
||||||
_gc_context: MutationContext<'gc, '_>,
|
_avm: &mut Avm1<'gc>,
|
||||||
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_display_object: DisplayObject<'gc>,
|
_display_object: DisplayObject<'gc>,
|
||||||
_proto: Object<'gc>,
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Bitmap display object
|
//! Bitmap display object
|
||||||
|
|
||||||
|
use crate::avm1::Avm1;
|
||||||
use crate::backend::render::BitmapHandle;
|
use crate::backend::render::BitmapHandle;
|
||||||
use crate::context::{RenderContext, UpdateContext};
|
use crate::context::{RenderContext, UpdateContext};
|
||||||
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
||||||
|
@ -79,7 +80,7 @@ impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, _context: &mut UpdateContext) {
|
fn run_frame(&mut self, _avm: &mut Avm1<'gc>, _context: &mut UpdateContext) {
|
||||||
// Noop
|
// Noop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::avm1::{Object, StageObject, Value};
|
use crate::avm1::{Avm1, Object, StageObject, Value};
|
||||||
use crate::context::{ActionType, RenderContext, UpdateContext};
|
use crate::context::{ActionType, RenderContext, UpdateContext};
|
||||||
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
||||||
use crate::events::{ButtonEvent, ButtonEventResult, ButtonKeyCode};
|
use crate::events::{ButtonEvent, ButtonEventResult, ButtonKeyCode};
|
||||||
|
@ -79,12 +79,13 @@ impl<'gc> Button<'gc> {
|
||||||
|
|
||||||
pub fn handle_button_event(
|
pub fn handle_button_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||||
event: ButtonEvent,
|
event: ButtonEvent,
|
||||||
) {
|
) {
|
||||||
self.0
|
self.0
|
||||||
.write(context.gc_context)
|
.write(context.gc_context)
|
||||||
.handle_button_event((*self).into(), context, event)
|
.handle_button_event((*self).into(), avm, context, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_sounds(self, gc_context: MutationContext<'gc, '_>, sounds: swf::ButtonSounds) {
|
pub fn set_sounds(self, gc_context: MutationContext<'gc, '_>, sounds: swf::ButtonSounds) {
|
||||||
|
@ -128,21 +129,25 @@ impl<'gc> TDisplayObject<'gc> for Button<'gc> {
|
||||||
|
|
||||||
fn post_instantiation(
|
fn post_instantiation(
|
||||||
&mut self,
|
&mut self,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
_avm: &mut Avm1<'gc>,
|
||||||
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
display_object: DisplayObject<'gc>,
|
display_object: DisplayObject<'gc>,
|
||||||
proto: Object<'gc>,
|
|
||||||
) {
|
) {
|
||||||
let mut mc = self.0.write(gc_context);
|
let mut mc = self.0.write(context.gc_context);
|
||||||
if mc.object.is_none() {
|
if mc.object.is_none() {
|
||||||
let object = StageObject::for_display_object(gc_context, display_object, Some(proto));
|
let object = StageObject::for_display_object(
|
||||||
|
context.gc_context,
|
||||||
|
display_object,
|
||||||
|
Some(context.system_prototypes.object),
|
||||||
|
);
|
||||||
mc.object = Some(object.into());
|
mc.object = Some(object.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
fn run_frame(&mut self, avm: &mut Avm1<'gc>, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
self.0
|
self.0
|
||||||
.write(context.gc_context)
|
.write(context.gc_context)
|
||||||
.run_frame((*self).into(), context)
|
.run_frame((*self).into(), avm, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, context: &mut RenderContext<'_, 'gc>) {
|
fn render(&self, context: &mut RenderContext<'_, 'gc>) {
|
||||||
|
@ -222,6 +227,7 @@ impl<'gc> ButtonData<'gc> {
|
||||||
fn set_state(
|
fn set_state(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||||
state: ButtonState,
|
state: ButtonState,
|
||||||
) {
|
) {
|
||||||
|
@ -237,8 +243,9 @@ impl<'gc> ButtonData<'gc> {
|
||||||
if let Ok(mut child) = context
|
if let Ok(mut child) = context
|
||||||
.library
|
.library
|
||||||
.library_for_movie_mut(self.movie())
|
.library_for_movie_mut(self.movie())
|
||||||
.instantiate_by_id(record.id, context.gc_context, &context.system_prototypes)
|
.instantiate_by_id(record.id, context.gc_context)
|
||||||
{
|
{
|
||||||
|
child.post_instantiation(avm, context, child);
|
||||||
child.set_parent(context.gc_context, Some(self_display_object));
|
child.set_parent(context.gc_context, Some(self_display_object));
|
||||||
child.set_matrix(context.gc_context, &record.matrix.clone().into());
|
child.set_matrix(context.gc_context, &record.matrix.clone().into());
|
||||||
child.set_color_transform(
|
child.set_color_transform(
|
||||||
|
@ -255,25 +262,24 @@ impl<'gc> ButtonData<'gc> {
|
||||||
fn run_frame(
|
fn run_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) {
|
) {
|
||||||
// TODO: Move this to post_instantiation.
|
// TODO: Move this to post_instantiation.
|
||||||
if !self.initialized {
|
if !self.initialized {
|
||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
self.set_state(self_display_object, context, ButtonState::Up);
|
self.set_state(self_display_object, avm, context, ButtonState::Up);
|
||||||
|
|
||||||
for record in &self.static_data.read().records {
|
for record in &self.static_data.read().records {
|
||||||
if record.states.contains(&swf::ButtonState::HitTest) {
|
if record.states.contains(&swf::ButtonState::HitTest) {
|
||||||
match context
|
match context
|
||||||
.library
|
.library
|
||||||
.library_for_movie_mut(self.static_data.read().swf.clone())
|
.library_for_movie_mut(self.static_data.read().swf.clone())
|
||||||
.instantiate_by_id(
|
.instantiate_by_id(record.id, context.gc_context)
|
||||||
record.id,
|
{
|
||||||
context.gc_context,
|
|
||||||
&context.system_prototypes,
|
|
||||||
) {
|
|
||||||
Ok(mut child) => {
|
Ok(mut child) => {
|
||||||
{
|
{
|
||||||
|
child.post_instantiation(avm, context, child);
|
||||||
child.set_matrix(context.gc_context, &record.matrix.clone().into());
|
child.set_matrix(context.gc_context, &record.matrix.clone().into());
|
||||||
child.set_parent(context.gc_context, Some(self_display_object));
|
child.set_parent(context.gc_context, Some(self_display_object));
|
||||||
child.set_depth(context.gc_context, record.depth.into());
|
child.set_depth(context.gc_context, record.depth.into());
|
||||||
|
@ -294,13 +300,14 @@ impl<'gc> ButtonData<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for child in self.children.values_mut() {
|
for child in self.children.values_mut() {
|
||||||
child.run_frame(context);
|
child.run_frame(avm, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_button_event(
|
fn handle_button_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
|
||||||
event: ButtonEvent,
|
event: ButtonEvent,
|
||||||
) {
|
) {
|
||||||
|
@ -340,7 +347,7 @@ impl<'gc> ButtonData<'gc> {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_state(self_display_object, context, new_state);
|
self.set_state(self_display_object, avm, context, new_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn play_sound(
|
fn play_sound(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! `EditText` display object and support code.
|
//! `EditText` display object and support code.
|
||||||
use crate::avm1::globals::text_field::attach_virtual_properties;
|
use crate::avm1::globals::text_field::attach_virtual_properties;
|
||||||
use crate::avm1::{Object, StageObject, Value};
|
use crate::avm1::{Avm1, Object, StageObject, Value};
|
||||||
use crate::context::{RenderContext, UpdateContext};
|
use crate::context::{RenderContext, UpdateContext};
|
||||||
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
||||||
use crate::font::{Glyph, TextFormat};
|
use crate::font::{Glyph, TextFormat};
|
||||||
|
@ -426,7 +426,7 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
|
||||||
Some(self.0.read().static_data.swf.clone())
|
Some(self.0.read().static_data.swf.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, _context: &mut UpdateContext) {
|
fn run_frame(&mut self, _avm: &mut Avm1<'gc>, _context: &mut UpdateContext) {
|
||||||
// Noop
|
// Noop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,16 +436,20 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
|
||||||
|
|
||||||
fn post_instantiation(
|
fn post_instantiation(
|
||||||
&mut self,
|
&mut self,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
_avm: &mut Avm1<'gc>,
|
||||||
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
display_object: DisplayObject<'gc>,
|
display_object: DisplayObject<'gc>,
|
||||||
proto: Object<'gc>,
|
|
||||||
) {
|
) {
|
||||||
let mut text = self.0.write(gc_context);
|
let mut text = self.0.write(context.gc_context);
|
||||||
if text.object.is_none() {
|
if text.object.is_none() {
|
||||||
let object =
|
let object = StageObject::for_display_object(
|
||||||
StageObject::for_display_object(gc_context, display_object, Some(proto)).into();
|
context.gc_context,
|
||||||
|
display_object,
|
||||||
|
Some(context.system_prototypes.text_field),
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
|
||||||
attach_virtual_properties(gc_context, object);
|
attach_virtual_properties(context.gc_context, object);
|
||||||
|
|
||||||
text.object = Some(object);
|
text.object = Some(object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::avm1::Avm1;
|
||||||
use crate::backend::render::ShapeHandle;
|
use crate::backend::render::ShapeHandle;
|
||||||
use crate::context::{RenderContext, UpdateContext};
|
use crate::context::{RenderContext, UpdateContext};
|
||||||
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
||||||
|
@ -42,7 +43,18 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
|
||||||
self.0.read().static_data.bounds.clone()
|
self.0.read().static_data.bounds.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, _context: &mut UpdateContext) {
|
fn world_bounds(&self) -> BoundingBox {
|
||||||
|
// TODO: Use dirty flags and cache this.
|
||||||
|
let mut bounds = self.local_bounds();
|
||||||
|
let mut node = self.parent();
|
||||||
|
while let Some(display_object) = node {
|
||||||
|
bounds = bounds.transform(&*display_object.matrix());
|
||||||
|
node = display_object.parent();
|
||||||
|
}
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_frame(&mut self, _avm: &mut Avm1<'gc>, _context: &mut UpdateContext) {
|
||||||
// Noop
|
// Noop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::avm1::Avm1;
|
||||||
use crate::backend::render::{RenderBackend, ShapeHandle};
|
use crate::backend::render::{RenderBackend, ShapeHandle};
|
||||||
use crate::context::{RenderContext, UpdateContext};
|
use crate::context::{RenderContext, UpdateContext};
|
||||||
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
||||||
|
@ -51,7 +52,7 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
|
||||||
Some(*self)
|
Some(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, _context: &mut UpdateContext) {
|
fn run_frame(&mut self, _avm: &mut Avm1<'gc>, _context: &mut UpdateContext) {
|
||||||
// Noop
|
// Noop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! `MovieClip` display object and support code.
|
//! `MovieClip` display object and support code.
|
||||||
use crate::avm1::{Object, StageObject, Value};
|
use crate::avm1::{Avm1, Object, StageObject, Value};
|
||||||
use crate::backend::audio::AudioStreamHandle;
|
use crate::backend::audio::AudioStreamHandle;
|
||||||
use crate::character::Character;
|
use crate::character::Character;
|
||||||
use crate::context::{ActionType, RenderContext, UpdateContext};
|
use crate::context::{ActionType, RenderContext, UpdateContext};
|
||||||
|
@ -133,9 +133,9 @@ impl<'gc> MovieClip<'gc> {
|
||||||
self.0.read().playing()
|
self.0.read().playing()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_frame(self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
pub fn next_frame(self, avm: &mut Avm1<'gc>, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
if self.current_frame() < self.total_frames() {
|
if self.current_frame() < self.total_frames() {
|
||||||
self.goto_frame(context, self.current_frame() + 1, true);
|
self.goto_frame(avm, context, self.current_frame() + 1, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,9 +143,9 @@ impl<'gc> MovieClip<'gc> {
|
||||||
self.0.write(context.gc_context).play()
|
self.0.write(context.gc_context).play()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prev_frame(self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
pub fn prev_frame(self, avm: &mut Avm1<'gc>, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
if self.current_frame() > 1 {
|
if self.current_frame() > 1 {
|
||||||
self.goto_frame(context, self.current_frame() - 1, true);
|
self.goto_frame(avm, context, self.current_frame() - 1, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,13 +157,14 @@ impl<'gc> MovieClip<'gc> {
|
||||||
/// `frame` should be 1-based.
|
/// `frame` should be 1-based.
|
||||||
pub fn goto_frame(
|
pub fn goto_frame(
|
||||||
self,
|
self,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
frame: FrameNumber,
|
frame: FrameNumber,
|
||||||
stop: bool,
|
stop: bool,
|
||||||
) {
|
) {
|
||||||
self.0
|
self.0
|
||||||
.write(context.gc_context)
|
.write(context.gc_context)
|
||||||
.goto_frame(self.into(), context, frame, stop)
|
.goto_frame(self.into(), avm, context, frame, stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_frame(self) -> FrameNumber {
|
pub fn current_frame(self) -> FrameNumber {
|
||||||
|
@ -314,10 +315,10 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
Some(self.0.read().movie())
|
Some(self.0.read().movie())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
fn run_frame(&mut self, avm: &mut Avm1<'gc>, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
// Children must run first.
|
// Children must run first.
|
||||||
for mut child in self.children() {
|
for mut child in self.children() {
|
||||||
child.run_frame(context);
|
child.run_frame(avm, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run my load/enterFrame clip event.
|
// Run my load/enterFrame clip event.
|
||||||
|
@ -332,7 +333,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
|
|
||||||
// Run my SWF tags.
|
// Run my SWF tags.
|
||||||
if mc.playing() {
|
if mc.playing() {
|
||||||
mc.run_frame_internal((*self).into(), context, true);
|
mc.run_frame_internal((*self).into(), avm, context, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_load_frame {
|
if is_load_frame {
|
||||||
|
@ -385,13 +386,17 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
|
|
||||||
fn post_instantiation(
|
fn post_instantiation(
|
||||||
&mut self,
|
&mut self,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
_avm: &mut Avm1<'gc>,
|
||||||
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
display_object: DisplayObject<'gc>,
|
display_object: DisplayObject<'gc>,
|
||||||
proto: Object<'gc>,
|
|
||||||
) {
|
) {
|
||||||
let mut mc = self.0.write(gc_context);
|
let mut mc = self.0.write(context.gc_context);
|
||||||
if mc.object.is_none() {
|
if mc.object.is_none() {
|
||||||
let object = StageObject::for_display_object(gc_context, display_object, Some(proto));
|
let object = StageObject::for_display_object(
|
||||||
|
context.gc_context,
|
||||||
|
display_object,
|
||||||
|
Some(context.system_prototypes.movie_clip),
|
||||||
|
);
|
||||||
mc.object = Some(object.into());
|
mc.object = Some(object.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,6 +526,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
pub fn goto_frame(
|
pub fn goto_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
mut frame: FrameNumber,
|
mut frame: FrameNumber,
|
||||||
stop: bool,
|
stop: bool,
|
||||||
|
@ -538,13 +544,14 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if frame != self.current_frame() {
|
if frame != self.current_frame() {
|
||||||
self.run_goto(self_display_object, context, frame);
|
self.run_goto(self_display_object, avm, context, frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame_internal(
|
fn run_frame_internal(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
run_display_actions: bool,
|
run_display_actions: bool,
|
||||||
) {
|
) {
|
||||||
|
@ -555,7 +562,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
// Looping acts exactly like a gotoAndPlay(1).
|
// Looping acts exactly like a gotoAndPlay(1).
|
||||||
// Specifically, object that existed on frame 1 should not be destroyed
|
// Specifically, object that existed on frame 1 should not be destroyed
|
||||||
// and recreated.
|
// and recreated.
|
||||||
self.run_goto(self_display_object, context, 1);
|
self.run_goto(self_display_object, avm, context, 1);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// Single frame clips do not play.
|
// Single frame clips do not play.
|
||||||
|
@ -571,16 +578,16 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
let tag_callback = |reader: &mut _, tag_code, tag_len| match tag_code {
|
let tag_callback = |reader: &mut _, tag_code, tag_len| match tag_code {
|
||||||
TagCode::DoAction => self.do_action(self_display_object, context, reader, tag_len),
|
TagCode::DoAction => self.do_action(self_display_object, context, reader, tag_len),
|
||||||
TagCode::PlaceObject if run_display_actions => {
|
TagCode::PlaceObject if run_display_actions => {
|
||||||
self.place_object(self_display_object, context, reader, tag_len, 1)
|
self.place_object(self_display_object, avm, context, reader, tag_len, 1)
|
||||||
}
|
}
|
||||||
TagCode::PlaceObject2 if run_display_actions => {
|
TagCode::PlaceObject2 if run_display_actions => {
|
||||||
self.place_object(self_display_object, context, reader, tag_len, 2)
|
self.place_object(self_display_object, avm, context, reader, tag_len, 2)
|
||||||
}
|
}
|
||||||
TagCode::PlaceObject3 if run_display_actions => {
|
TagCode::PlaceObject3 if run_display_actions => {
|
||||||
self.place_object(self_display_object, context, reader, tag_len, 3)
|
self.place_object(self_display_object, avm, context, reader, tag_len, 3)
|
||||||
}
|
}
|
||||||
TagCode::PlaceObject4 if run_display_actions => {
|
TagCode::PlaceObject4 if run_display_actions => {
|
||||||
self.place_object(self_display_object, context, reader, tag_len, 4)
|
self.place_object(self_display_object, avm, context, reader, tag_len, 4)
|
||||||
}
|
}
|
||||||
TagCode::RemoveObject if run_display_actions => self.remove_object(context, reader, 1),
|
TagCode::RemoveObject if run_display_actions => self.remove_object(context, reader, 1),
|
||||||
TagCode::RemoveObject2 if run_display_actions => self.remove_object(context, reader, 2),
|
TagCode::RemoveObject2 if run_display_actions => self.remove_object(context, reader, 2),
|
||||||
|
@ -602,9 +609,11 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn instantiate_child(
|
fn instantiate_child(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
depth: Depth,
|
depth: Depth,
|
||||||
|
@ -614,8 +623,10 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
if let Ok(mut child) = context
|
if let Ok(mut child) = context
|
||||||
.library
|
.library
|
||||||
.library_for_movie_mut(self.movie())
|
.library_for_movie_mut(self.movie())
|
||||||
.instantiate_by_id(id, context.gc_context, &context.system_prototypes)
|
.instantiate_by_id(id, context.gc_context)
|
||||||
{
|
{
|
||||||
|
child.post_instantiation(avm, context, child);
|
||||||
|
|
||||||
// Remove previous child from children list,
|
// Remove previous child from children list,
|
||||||
// and add new childonto front of the list.
|
// and add new childonto front of the list.
|
||||||
let prev_child = self.children.insert(depth, child);
|
let prev_child = self.children.insert(depth, child);
|
||||||
|
@ -635,7 +646,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
}
|
}
|
||||||
// Run first frame.
|
// Run first frame.
|
||||||
child.apply_place_object(context.gc_context, place_object);
|
child.apply_place_object(context.gc_context, place_object);
|
||||||
child.run_frame(context);
|
child.run_frame(avm, context);
|
||||||
}
|
}
|
||||||
Some(child)
|
Some(child)
|
||||||
} else {
|
} else {
|
||||||
|
@ -684,6 +695,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
pub fn run_goto(
|
pub fn run_goto(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
frame: FrameNumber,
|
frame: FrameNumber,
|
||||||
) {
|
) {
|
||||||
|
@ -786,6 +798,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
|
|
||||||
// Run the list of goto commands to actually create and update the display objects.
|
// Run the list of goto commands to actually create and update the display objects.
|
||||||
let run_goto_command = |clip: &mut MovieClipData<'gc>,
|
let run_goto_command = |clip: &mut MovieClipData<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
params: &GotoPlaceObject| {
|
params: &GotoPlaceObject| {
|
||||||
let child_entry = clip.children.get_mut(¶ms.depth()).copied();
|
let child_entry = clip.children.get_mut(¶ms.depth()).copied();
|
||||||
|
@ -803,6 +816,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(mut child) = clip.instantiate_child(
|
if let Some(mut child) = clip.instantiate_child(
|
||||||
self_display_object,
|
self_display_object,
|
||||||
|
avm,
|
||||||
context,
|
context,
|
||||||
params.id(),
|
params.id(),
|
||||||
params.depth(),
|
params.depth(),
|
||||||
|
@ -828,7 +842,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
goto_commands
|
goto_commands
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|params| params.frame < frame)
|
.filter(|params| params.frame < frame)
|
||||||
.for_each(|goto| run_goto_command(self, context, goto));
|
.for_each(|goto| run_goto_command(self, avm, context, goto));
|
||||||
|
|
||||||
// Next, run the final frame for the parent clip.
|
// Next, run the final frame for the parent clip.
|
||||||
// Re-run the final frame without display tags (DoAction, StartSound, etc.)
|
// Re-run the final frame without display tags (DoAction, StartSound, etc.)
|
||||||
|
@ -837,7 +851,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
if hit_target_frame {
|
if hit_target_frame {
|
||||||
self.current_frame -= 1;
|
self.current_frame -= 1;
|
||||||
self.tag_stream_pos = frame_pos;
|
self.tag_stream_pos = frame_pos;
|
||||||
self.run_frame_internal(self_display_object, context, false);
|
self.run_frame_internal(self_display_object, avm, context, false);
|
||||||
} else {
|
} else {
|
||||||
self.current_frame = clamped_frame;
|
self.current_frame = clamped_frame;
|
||||||
}
|
}
|
||||||
|
@ -846,7 +860,7 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
goto_commands
|
goto_commands
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|params| params.frame >= frame)
|
.filter(|params| params.frame >= frame)
|
||||||
.for_each(|goto| run_goto_command(self, context, goto));
|
.for_each(|goto| run_goto_command(self, avm, context, goto));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a PlaceObject tag when running a goto action.
|
/// Handles a PlaceObject tag when running a goto action.
|
||||||
|
@ -1816,6 +1830,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn place_object(
|
fn place_object(
|
||||||
&mut self,
|
&mut self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<&'a [u8]>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
|
@ -1831,6 +1846,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
PlaceObjectAction::Place(id) | PlaceObjectAction::Replace(id) => {
|
PlaceObjectAction::Place(id) | PlaceObjectAction::Replace(id) => {
|
||||||
if let Some(child) = self.instantiate_child(
|
if let Some(child) = self.instantiate_child(
|
||||||
self_display_object,
|
self_display_object,
|
||||||
|
avm,
|
||||||
context,
|
context,
|
||||||
id,
|
id,
|
||||||
place_object.depth.into(),
|
place_object.depth.into(),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::avm1::Avm1;
|
||||||
use crate::context::{RenderContext, UpdateContext};
|
use crate::context::{RenderContext, UpdateContext};
|
||||||
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
use crate::display_object::{DisplayObjectBase, TDisplayObject};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -52,7 +53,7 @@ impl<'gc> TDisplayObject<'gc> for Text<'gc> {
|
||||||
Some(self.0.read().static_data.swf.clone())
|
Some(self.0.read().static_data.swf.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_frame(&mut self, _context: &mut UpdateContext) {
|
fn run_frame(&mut self, _avm: &mut Avm1<'gc>, _context: &mut UpdateContext) {
|
||||||
// Noop
|
// Noop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use crate::avm1::globals::SystemPrototypes;
|
|
||||||
use crate::avm1::Object;
|
|
||||||
use crate::backend::audio::SoundHandle;
|
use crate::backend::audio::SoundHandle;
|
||||||
use crate::character::Character;
|
use crate::character::Character;
|
||||||
use crate::display_object::TDisplayObject;
|
use crate::display_object::TDisplayObject;
|
||||||
|
@ -79,14 +77,14 @@ impl<'gc> MovieLibrary<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiates the library item with the given character ID into a display object.
|
/// Instantiates the library item with the given character ID into a display object.
|
||||||
|
/// The object must then be post-instantiated before being used.
|
||||||
pub fn instantiate_by_id(
|
pub fn instantiate_by_id(
|
||||||
&self,
|
&self,
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
gc_context: MutationContext<'gc, '_>,
|
||||||
prototypes: &SystemPrototypes<'gc>,
|
|
||||||
) -> Result<DisplayObject<'gc>, Box<dyn std::error::Error>> {
|
) -> Result<DisplayObject<'gc>, Box<dyn std::error::Error>> {
|
||||||
if let Some(character) = self.characters.get(&id) {
|
if let Some(character) = self.characters.get(&id) {
|
||||||
self.instantiate_display_object(character, gc_context, prototypes)
|
self.instantiate_display_object(character, gc_context)
|
||||||
} else {
|
} else {
|
||||||
log::error!("Tried to instantiate non-registered character ID {}", id);
|
log::error!("Tried to instantiate non-registered character ID {}", id);
|
||||||
Err("Character id doesn't exist".into())
|
Err("Character id doesn't exist".into())
|
||||||
|
@ -94,14 +92,14 @@ impl<'gc> MovieLibrary<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiates the library item with the given export name into a display object.
|
/// Instantiates the library item with the given export name into a display object.
|
||||||
|
/// The object must then be post-instantiated before being used.
|
||||||
pub fn instantiate_by_export_name(
|
pub fn instantiate_by_export_name(
|
||||||
&self,
|
&self,
|
||||||
export_name: &str,
|
export_name: &str,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
gc_context: MutationContext<'gc, '_>,
|
||||||
prototypes: &SystemPrototypes<'gc>,
|
|
||||||
) -> Result<DisplayObject<'gc>, Box<dyn std::error::Error>> {
|
) -> Result<DisplayObject<'gc>, Box<dyn std::error::Error>> {
|
||||||
if let Some(character) = self.export_characters.get(export_name) {
|
if let Some(character) = self.export_characters.get(export_name) {
|
||||||
self.instantiate_display_object(character, gc_context, prototypes)
|
self.instantiate_display_object(character, gc_context)
|
||||||
} else {
|
} else {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Tried to instantiate non-registered character {}",
|
"Tried to instantiate non-registered character {}",
|
||||||
|
@ -112,30 +110,22 @@ impl<'gc> MovieLibrary<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiates the given character into a display object.
|
/// Instantiates the given character into a display object.
|
||||||
|
/// The object must then be post-instantiated before being used.
|
||||||
fn instantiate_display_object(
|
fn instantiate_display_object(
|
||||||
&self,
|
&self,
|
||||||
character: &Character<'gc>,
|
character: &Character<'gc>,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
gc_context: MutationContext<'gc, '_>,
|
||||||
prototypes: &SystemPrototypes<'gc>,
|
|
||||||
) -> Result<DisplayObject<'gc>, Box<dyn std::error::Error>> {
|
) -> Result<DisplayObject<'gc>, Box<dyn std::error::Error>> {
|
||||||
let (mut obj, proto): (DisplayObject<'gc>, Object<'gc>) = match character {
|
match character {
|
||||||
Character::Bitmap(bitmap) => (bitmap.instantiate(gc_context), prototypes.object),
|
Character::Bitmap(bitmap) => Ok(bitmap.instantiate(gc_context)),
|
||||||
Character::EditText(edit_text) => {
|
Character::EditText(edit_text) => Ok(edit_text.instantiate(gc_context)),
|
||||||
(edit_text.instantiate(gc_context), prototypes.text_field)
|
Character::Graphic(graphic) => Ok(graphic.instantiate(gc_context)),
|
||||||
|
Character::MorphShape(morph_shape) => Ok(morph_shape.instantiate(gc_context)),
|
||||||
|
Character::MovieClip(movie_clip) => Ok(movie_clip.instantiate(gc_context)),
|
||||||
|
Character::Button(button) => Ok(button.instantiate(gc_context)),
|
||||||
|
Character::Text(text) => Ok(text.instantiate(gc_context)),
|
||||||
|
_ => Err("Not a DisplayObject".into()),
|
||||||
}
|
}
|
||||||
Character::Graphic(graphic) => (graphic.instantiate(gc_context), prototypes.object),
|
|
||||||
Character::MorphShape(morph_shape) => {
|
|
||||||
(morph_shape.instantiate(gc_context), prototypes.object)
|
|
||||||
}
|
|
||||||
Character::MovieClip(movie_clip) => {
|
|
||||||
(movie_clip.instantiate(gc_context), prototypes.movie_clip)
|
|
||||||
}
|
|
||||||
Character::Button(button) => (button.instantiate(gc_context), prototypes.object),
|
|
||||||
Character::Text(text) => (text.instantiate(gc_context), prototypes.object),
|
|
||||||
_ => return Err("Not a DisplayObject".into()),
|
|
||||||
};
|
|
||||||
obj.post_instantiation(gc_context, obj, proto);
|
|
||||||
Ok(obj)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_font(&self, id: CharacterId) -> Option<Font<'gc>> {
|
pub fn get_font(&self, id: CharacterId) -> Option<Font<'gc>> {
|
||||||
|
|
|
@ -321,7 +321,7 @@ impl<'gc> Loader<'gc> {
|
||||||
.expect("Attempted to load movie into not movie clip");
|
.expect("Attempted to load movie into not movie clip");
|
||||||
|
|
||||||
mc.replace_with_movie(uc.gc_context, Some(movie.clone()));
|
mc.replace_with_movie(uc.gc_context, Some(movie.clone()));
|
||||||
mc.post_instantiation(uc.gc_context, clip, avm.prototypes().movie_clip);
|
mc.post_instantiation(avm, uc, clip);
|
||||||
|
|
||||||
let mut morph_shapes = fnv::FnvHashMap::default();
|
let mut morph_shapes = fnv::FnvHashMap::default();
|
||||||
mc.preload(uc, &mut morph_shapes);
|
mc.preload(uc, &mut morph_shapes);
|
||||||
|
|
|
@ -193,9 +193,6 @@ impl Player {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut library = Library::default();
|
let mut library = Library::default();
|
||||||
let root = MovieClip::from_movie(gc_context, movie.clone()).into();
|
|
||||||
let mut levels = BTreeMap::new();
|
|
||||||
levels.insert(0, root);
|
|
||||||
|
|
||||||
library
|
library
|
||||||
.library_for_movie_mut(movie.clone())
|
.library_for_movie_mut(movie.clone())
|
||||||
|
@ -205,7 +202,7 @@ impl Player {
|
||||||
gc_context,
|
gc_context,
|
||||||
GcRootData {
|
GcRootData {
|
||||||
library,
|
library,
|
||||||
levels,
|
levels: BTreeMap::new(),
|
||||||
mouse_hovered_object: None,
|
mouse_hovered_object: None,
|
||||||
drag_object: None,
|
drag_object: None,
|
||||||
avm: Avm1::new(gc_context, NEWEST_PLAYER_VERSION),
|
avm: Avm1::new(gc_context, NEWEST_PLAYER_VERSION),
|
||||||
|
@ -236,14 +233,12 @@ impl Player {
|
||||||
self_reference: None,
|
self_reference: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
player.gc_arena.mutate(|gc_context, gc_root| {
|
player.mutate_with_update_context(|avm, context| {
|
||||||
let mut root_data = gc_root.0.write(gc_context);
|
let mut root: DisplayObject =
|
||||||
let mc_proto = root_data.avm.prototypes().movie_clip;
|
MovieClip::from_movie(context.gc_context, movie.clone()).into();
|
||||||
|
root.post_instantiation(avm, context, root);
|
||||||
for (_i, level) in root_data.levels.iter_mut() {
|
root.set_depth(context.gc_context, 0);
|
||||||
level.post_instantiation(gc_context, *level, mc_proto);
|
context.levels.insert(0, root);
|
||||||
level.set_depth(gc_context, 0);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
player.build_matrices();
|
player.build_matrices();
|
||||||
|
@ -430,13 +425,13 @@ impl Player {
|
||||||
PlayerEvent::MouseDown { .. } => {
|
PlayerEvent::MouseDown { .. } => {
|
||||||
is_mouse_down = true;
|
is_mouse_down = true;
|
||||||
needs_render = true;
|
needs_render = true;
|
||||||
button.handle_button_event(context, ButtonEvent::Press);
|
button.handle_button_event(avm, context, ButtonEvent::Press);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerEvent::MouseUp { .. } => {
|
PlayerEvent::MouseUp { .. } => {
|
||||||
is_mouse_down = false;
|
is_mouse_down = false;
|
||||||
needs_render = true;
|
needs_render = true;
|
||||||
button.handle_button_event(context, ButtonEvent::Release);
|
button.handle_button_event(avm, context, ButtonEvent::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -508,7 +503,7 @@ impl Player {
|
||||||
// RollOut of previous node.
|
// RollOut of previous node.
|
||||||
if let Some(node) = cur_hovered {
|
if let Some(node) = cur_hovered {
|
||||||
if let Some(mut button) = node.as_button() {
|
if let Some(mut button) = node.as_button() {
|
||||||
button.handle_button_event(context, ButtonEvent::RollOut);
|
button.handle_button_event(avm, context, ButtonEvent::RollOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,7 +511,7 @@ impl Player {
|
||||||
new_cursor = MouseCursor::Arrow;
|
new_cursor = MouseCursor::Arrow;
|
||||||
if let Some(node) = new_hovered {
|
if let Some(node) = new_hovered {
|
||||||
if let Some(mut button) = node.as_button() {
|
if let Some(mut button) = node.as_button() {
|
||||||
button.handle_button_event(context, ButtonEvent::RollOver);
|
button.handle_button_event(avm, context, ButtonEvent::RollOver);
|
||||||
new_cursor = MouseCursor::Hand;
|
new_cursor = MouseCursor::Hand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,7 +558,7 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_frame(&mut self) {
|
pub fn run_frame(&mut self) {
|
||||||
self.update(|_avm, update_context| {
|
self.update(|avm, update_context| {
|
||||||
// TODO: In what order are levels run?
|
// TODO: In what order are levels run?
|
||||||
// NOTE: We have to copy all the layer pointers into a separate list
|
// NOTE: We have to copy all the layer pointers into a separate list
|
||||||
// because level updates can create more levels, which we don't
|
// because level updates can create more levels, which we don't
|
||||||
|
@ -571,7 +566,7 @@ impl Player {
|
||||||
let levels: Vec<_> = update_context.levels.values().copied().collect();
|
let levels: Vec<_> = update_context.levels.values().copied().collect();
|
||||||
|
|
||||||
for mut level in levels {
|
for mut level in levels {
|
||||||
level.run_frame(update_context);
|
level.run_frame(avm, update_context);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue