core: Implement Object.registerClass (merge #344)
Implement Object.registerClass
This commit is contained in:
commit
4df1128c19
|
@ -979,7 +979,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> {
|
||||||
|
@ -989,7 +989,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);
|
||||||
|
|
||||||
|
@ -1804,7 +1804,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");
|
||||||
}
|
}
|
||||||
|
@ -1850,7 +1850,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);
|
||||||
}
|
}
|
||||||
|
@ -2052,7 +2052,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");
|
||||||
}
|
}
|
||||||
|
@ -2165,7 +2165,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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,12 +179,7 @@ pub fn create_globals<'gc>(
|
||||||
boolean::create_proto(gc_context, object_proto, function_proto);
|
boolean::create_proto(gc_context, object_proto, function_proto);
|
||||||
|
|
||||||
//TODO: These need to be constructors and should also set `.prototype` on each one
|
//TODO: These need to be constructors and should also set `.prototype` on each one
|
||||||
let object = FunctionObject::function(
|
let object = object::create_object_object(gc_context, object_proto, function_proto);
|
||||||
gc_context,
|
|
||||||
Executable::Native(object::constructor),
|
|
||||||
Some(function_proto),
|
|
||||||
Some(object_proto),
|
|
||||||
);
|
|
||||||
|
|
||||||
let color = FunctionObject::function(
|
let color = FunctionObject::function(
|
||||||
gc_context,
|
gc_context,
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
//! Object prototype
|
//! Object prototype
|
||||||
|
use crate::avm1::function::{Executable, FunctionObject};
|
||||||
use crate::avm1::property::Attribute::{self, *};
|
use crate::avm1::property::Attribute::{self, *};
|
||||||
use crate::avm1::return_value::ReturnValue;
|
use crate::avm1::return_value::ReturnValue;
|
||||||
use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext, Value};
|
use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext, Value};
|
||||||
|
use crate::character::Character;
|
||||||
use enumset::EnumSet;
|
use enumset::EnumSet;
|
||||||
use gc_arena::MutationContext;
|
use gc_arena::MutationContext;
|
||||||
|
|
||||||
|
@ -129,6 +131,30 @@ fn value_of<'gc>(
|
||||||
Ok(ReturnValue::Immediate(this.into()))
|
Ok(ReturnValue::Immediate(this.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implements `Object.registerClass`
|
||||||
|
pub fn register_class<'gc>(
|
||||||
|
avm: &mut Avm1<'gc>,
|
||||||
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
|
_this: Object<'gc>,
|
||||||
|
args: &[Value<'gc>],
|
||||||
|
) -> Result<ReturnValue<'gc>, Error> {
|
||||||
|
if let Some(class_name) = args.get(0).cloned() {
|
||||||
|
let class_name = class_name.coerce_to_string(avm, context)?;
|
||||||
|
if let Some(Character::MovieClip(movie_clip)) = context
|
||||||
|
.library
|
||||||
|
.library_for_movie_mut(context.swf.clone())
|
||||||
|
.get_character_by_export_name(&class_name)
|
||||||
|
{
|
||||||
|
if let Some(constructor) = args.get(1) {
|
||||||
|
movie_clip.set_avm1_constructor(context.gc_context, Some(constructor.as_object()?));
|
||||||
|
} else {
|
||||||
|
movie_clip.set_avm1_constructor(context.gc_context, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Value::Undefined.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// Partially construct `Object.prototype`.
|
/// Partially construct `Object.prototype`.
|
||||||
///
|
///
|
||||||
/// `__proto__` and other cross-linked properties of this object will *not*
|
/// `__proto__` and other cross-linked properties of this object will *not*
|
||||||
|
@ -259,3 +285,27 @@ pub fn as_set_prop_flags<'gc>(
|
||||||
|
|
||||||
Ok(Value::Undefined.into())
|
Ok(Value::Undefined.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_object_object<'gc>(
|
||||||
|
gc_context: MutationContext<'gc, '_>,
|
||||||
|
proto: Object<'gc>,
|
||||||
|
fn_proto: Object<'gc>,
|
||||||
|
) -> Object<'gc> {
|
||||||
|
let object_function = FunctionObject::function(
|
||||||
|
gc_context,
|
||||||
|
Executable::Native(constructor),
|
||||||
|
Some(fn_proto),
|
||||||
|
Some(proto),
|
||||||
|
);
|
||||||
|
let mut object = object_function.as_script_object().unwrap();
|
||||||
|
|
||||||
|
object.force_set_function(
|
||||||
|
"registerClass",
|
||||||
|
register_class,
|
||||||
|
gc_context,
|
||||||
|
Attribute::DontEnum | Attribute::DontDelete | Attribute::ReadOnly,
|
||||||
|
Some(fn_proto),
|
||||||
|
);
|
||||||
|
|
||||||
|
object_function
|
||||||
|
}
|
||||||
|
|
|
@ -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::{Font, Glyph, TextFormat};
|
use crate::font::{Font, Glyph, TextFormat};
|
||||||
|
@ -419,7 +419,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,16 +429,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, TObject, 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};
|
||||||
|
@ -41,6 +41,7 @@ pub struct MovieClipData<'gc> {
|
||||||
object: Option<Object<'gc>>,
|
object: Option<Object<'gc>>,
|
||||||
clip_actions: SmallVec<[ClipAction; 2]>,
|
clip_actions: SmallVec<[ClipAction; 2]>,
|
||||||
flags: EnumSet<MovieClipFlags>,
|
flags: EnumSet<MovieClipFlags>,
|
||||||
|
avm1_constructor: Option<Object<'gc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gc> MovieClip<'gc> {
|
impl<'gc> MovieClip<'gc> {
|
||||||
|
@ -58,6 +59,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
object: None,
|
object: None,
|
||||||
clip_actions: SmallVec::new(),
|
clip_actions: SmallVec::new(),
|
||||||
flags: EnumSet::empty(),
|
flags: EnumSet::empty(),
|
||||||
|
avm1_constructor: None,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -89,6 +91,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
object: None,
|
object: None,
|
||||||
clip_actions: SmallVec::new(),
|
clip_actions: SmallVec::new(),
|
||||||
flags: MovieClipFlags::Playing.into(),
|
flags: MovieClipFlags::Playing.into(),
|
||||||
|
avm1_constructor: None,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -133,9 +136,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 +146,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 +160,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 {
|
||||||
|
@ -179,6 +183,14 @@ impl<'gc> MovieClip<'gc> {
|
||||||
self.0.read().static_data.total_frames
|
self.0.read().static_data.total_frames
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_avm1_constructor(
|
||||||
|
self,
|
||||||
|
gc_context: MutationContext<'gc, '_>,
|
||||||
|
prototype: Option<Object<'gc>>,
|
||||||
|
) {
|
||||||
|
self.0.write(gc_context).avm1_constructor = prototype;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn frame_label_to_number(self, frame_label: &str) -> Option<FrameNumber> {
|
pub fn frame_label_to_number(self, frame_label: &str) -> Option<FrameNumber> {
|
||||||
// Frame labels are case insensitive.
|
// Frame labels are case insensitive.
|
||||||
let label = frame_label.to_ascii_lowercase();
|
let label = frame_label.to_ascii_lowercase();
|
||||||
|
@ -314,10 +326,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 +344,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 +397,37 @@ 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));
|
if let Some(constructor) = mc.avm1_constructor {
|
||||||
|
if let Ok(prototype) = constructor
|
||||||
|
.get("prototype", avm, context)
|
||||||
|
.and_then(|v| v.resolve(avm, context))
|
||||||
|
.and_then(|v| v.as_object())
|
||||||
|
{
|
||||||
|
let object: Object<'gc> = StageObject::for_display_object(
|
||||||
|
context.gc_context,
|
||||||
|
display_object,
|
||||||
|
Some(prototype),
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
mc.object = Some(object);
|
||||||
|
if let Ok(result) = constructor.call(avm, context, object, &[]) {
|
||||||
|
let _ = result.resolve(avm, context);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,6 +463,7 @@ unsafe impl<'gc> Collect for MovieClipData<'gc> {
|
||||||
self.base.trace(cc);
|
self.base.trace(cc);
|
||||||
self.static_data.trace(cc);
|
self.static_data.trace(cc);
|
||||||
self.object.trace(cc);
|
self.object.trace(cc);
|
||||||
|
self.avm1_constructor.trace(cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,6 +558,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 +576,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 +594,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 +610,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 +641,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 +655,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 +678,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 +727,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 +830,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 +848,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 +874,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 +883,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 +892,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 +1862,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 +1878,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::Graphic(graphic) => (graphic.instantiate(gc_context), prototypes.object),
|
Character::MovieClip(movie_clip) => Ok(movie_clip.instantiate(gc_context)),
|
||||||
Character::MorphShape(morph_shape) => {
|
Character::Button(button) => Ok(button.instantiate(gc_context)),
|
||||||
(morph_shape.instantiate(gc_context), prototypes.object)
|
Character::Text(text) => Ok(text.instantiate(gc_context)),
|
||||||
}
|
_ => Err("Not a DisplayObject".into()),
|
||||||
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>> {
|
||||||
|
|
|
@ -334,7 +334,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);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,7 @@ swf_tests! {
|
||||||
(equals2_swf5, "avm1/equals2_swf5", 1),
|
(equals2_swf5, "avm1/equals2_swf5", 1),
|
||||||
(equals2_swf6, "avm1/equals2_swf6", 1),
|
(equals2_swf6, "avm1/equals2_swf6", 1),
|
||||||
(equals2_swf7, "avm1/equals2_swf7", 1),
|
(equals2_swf7, "avm1/equals2_swf7", 1),
|
||||||
|
(register_class, "avm1/register_class", 1),
|
||||||
(set_variable_scope, "avm1/set_variable_scope", 1),
|
(set_variable_scope, "avm1/set_variable_scope", 1),
|
||||||
(slash_syntax, "avm1/slash_syntax", 2),
|
(slash_syntax, "avm1/slash_syntax", 2),
|
||||||
(strictequals_swf6, "avm1/strictequals_swf6", 1),
|
(strictequals_swf6, "avm1/strictequals_swf6", 1),
|
||||||
|
|
|
@ -1,15 +1,51 @@
|
||||||
|
// mc = _root.attachMovie("Clip", "clip", 0)
|
||||||
|
// clip
|
||||||
_level0.clip
|
_level0.clip
|
||||||
|
|
||||||
|
// clip == mc
|
||||||
true
|
true
|
||||||
|
|
||||||
|
// mc._x
|
||||||
0
|
0
|
||||||
|
|
||||||
|
// mc._y
|
||||||
0
|
0
|
||||||
|
|
||||||
|
// mc = _root.attachMovie("BOGUS", "clip", 0)
|
||||||
|
// mc
|
||||||
undefined
|
undefined
|
||||||
|
|
||||||
|
// clip == mc
|
||||||
false
|
false
|
||||||
|
|
||||||
|
// mc = _root.attachMovie("Clip", "clip", 0, {_x: 100, _y: 50, foo: "foo"})
|
||||||
|
// clip == mc
|
||||||
true
|
true
|
||||||
|
|
||||||
|
// mc._x
|
||||||
100
|
100
|
||||||
|
|
||||||
|
// mc._y
|
||||||
50
|
50
|
||||||
|
|
||||||
|
// mc.foo
|
||||||
foo
|
foo
|
||||||
|
|
||||||
|
// mc = _root.attachMovie("Clip", "clip", -1)
|
||||||
|
// clip == mc
|
||||||
true
|
true
|
||||||
|
|
||||||
|
// mc._x
|
||||||
0
|
0
|
||||||
|
|
||||||
|
// mc._y
|
||||||
0
|
0
|
||||||
|
|
||||||
|
// mc2 = _root.attachMovie("Clip", "clip2", 2130690044)
|
||||||
|
// mc2
|
||||||
_level0.clip2
|
_level0.clip2
|
||||||
|
|
||||||
|
// mc3 = _root.attachMovie("Clip", "clip2", 2130690045)
|
||||||
|
// mc3
|
||||||
undefined
|
undefined
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,18 @@
|
||||||
|
Custom movieclip!
|
||||||
|
// typeof custom_movieclip
|
||||||
|
movieclip
|
||||||
|
// custom_movieclip.__proto__ == custom_mc.prototype
|
||||||
|
true
|
||||||
|
// custom_movieclip.__proto__ == MovieClip.prototype
|
||||||
|
false
|
||||||
|
// custom_movieclip.isCustom()
|
||||||
|
true
|
||||||
|
|
||||||
|
// typeof normal_movieclip
|
||||||
|
movieclip
|
||||||
|
// normal_movieclip.__proto__ == custom_mc.prototype
|
||||||
|
false
|
||||||
|
// normal_movieclip.__proto__ == MovieClip.prototype
|
||||||
|
true
|
||||||
|
// normal_movieclip.isCustom()
|
||||||
|
undefined
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue