Add a version parameter to every DisplayObject impl

This commit is contained in:
David Wendt 2019-10-09 19:46:15 -04:00
parent 8668d47403
commit feaa3dd203
10 changed files with 47 additions and 18 deletions

View File

@ -154,7 +154,8 @@ mod tests {
{ {
rootless_arena(|gc_context| { rootless_arena(|gc_context| {
let mut avm = Avm1::new(gc_context); let mut avm = Avm1::new(gc_context);
let movie_clip: Box<dyn DisplayObject> = Box::new(MovieClip::new(gc_context)); let movie_clip: Box<dyn DisplayObject> =
Box::new(MovieClip::new(swf_version, gc_context));
let root = GcCell::allocate(gc_context, movie_clip); let root = GcCell::allocate(gc_context, movie_clip);
let mut context = ActionContext { let mut context = ActionContext {
gc_context, gc_context,

View File

@ -391,7 +391,8 @@ mod tests {
{ {
rootless_arena(|gc_context| { rootless_arena(|gc_context| {
let mut avm = Avm1::new(gc_context); let mut avm = Avm1::new(gc_context);
let movie_clip: Box<dyn DisplayObject> = Box::new(MovieClip::new(gc_context)); let movie_clip: Box<dyn DisplayObject> =
Box::new(MovieClip::new(swf_version, gc_context));
let root = GcCell::allocate(gc_context, movie_clip); let root = GcCell::allocate(gc_context, movie_clip);
let mut context = ActionContext { let mut context = ActionContext {
gc_context, gc_context,

View File

@ -17,6 +17,7 @@ pub struct Button<'gc> {
impl<'gc> Button<'gc> { impl<'gc> Button<'gc> {
pub fn from_swf_tag( pub fn from_swf_tag(
swf_version: u8,
button: &swf::Button, button: &swf::Button,
_library: &crate::library::Library<'gc>, _library: &crate::library::Library<'gc>,
gc_context: gc_arena::MutationContext<'gc, '_>, gc_context: gc_arena::MutationContext<'gc, '_>,
@ -45,7 +46,7 @@ impl<'gc> Button<'gc> {
}; };
Button { Button {
base: Default::default(), base: DisplayObjectBase::new(swf_version),
static_data: gc_arena::Gc::allocate(gc_context, static_data), static_data: gc_arena::Gc::allocate(gc_context, static_data),
children: BTreeMap::new(), children: BTreeMap::new(),
hit_area: BTreeMap::new(), hit_area: BTreeMap::new(),

View File

@ -14,10 +14,13 @@ pub struct DisplayObjectBase<'gc> {
transform: Transform, transform: Transform,
name: String, name: String,
clip_depth: Depth, clip_depth: Depth,
///The version of the SWF that created this display object.
swf_version: u8,
} }
impl<'gc> Default for DisplayObjectBase<'gc> { impl<'gc> DisplayObjectBase<'gc> {
fn default() -> Self { pub fn new(swf_version: u8) -> Self {
Self { Self {
parent: Default::default(), parent: Default::default(),
place_frame: Default::default(), place_frame: Default::default(),
@ -25,6 +28,7 @@ impl<'gc> Default for DisplayObjectBase<'gc> {
transform: Default::default(), transform: Default::default(),
name: Default::default(), name: Default::default(),
clip_depth: Default::default(), clip_depth: Default::default(),
swf_version: swf_version,
} }
} }
} }
@ -82,6 +86,9 @@ impl<'gc> DisplayObject<'gc> for DisplayObjectBase<'gc> {
fn box_clone(&self) -> Box<dyn DisplayObject<'gc>> { fn box_clone(&self) -> Box<dyn DisplayObject<'gc>> {
Box::new(self.clone()) Box::new(self.clone())
} }
fn swf_version(&self) -> u8 {
self.swf_version
}
} }
pub trait DisplayObject<'gc>: 'gc + Collect + Debug { pub trait DisplayObject<'gc>: 'gc + Collect + Debug {
@ -189,6 +196,9 @@ pub trait DisplayObject<'gc>: 'gc + Collect + Debug {
_display_object: DisplayNode<'gc>, _display_object: DisplayNode<'gc>,
) { ) {
} }
/// Return the version of the SWF that created this movie clip.
fn swf_version(&self) -> u8;
} }
impl<'gc> Clone for Box<dyn DisplayObject<'gc>> { impl<'gc> Clone for Box<dyn DisplayObject<'gc>> {
@ -247,6 +257,9 @@ macro_rules! impl_display_object {
fn box_clone(&self) -> Box<dyn crate::display_object::DisplayObject<'gc>> { fn box_clone(&self) -> Box<dyn crate::display_object::DisplayObject<'gc>> {
Box::new(self.clone()) Box::new(self.clone())
} }
fn swf_version(&self) -> u8 {
self.$field.swf_version()
}
}; };
} }

View File

@ -29,7 +29,7 @@ impl<'gc> EditText<'gc> {
/// Creates a new `EditText` from an SWF `DefineEditText` tag. /// Creates a new `EditText` from an SWF `DefineEditText` tag.
pub fn from_swf_tag(context: &mut UpdateContext<'_, 'gc, '_>, swf_tag: swf::EditText) -> Self { pub fn from_swf_tag(context: &mut UpdateContext<'_, 'gc, '_>, swf_tag: swf::EditText) -> Self {
Self { Self {
base: Default::default(), base: DisplayObjectBase::new(context.swf_version),
text: swf_tag.initial_text.clone().unwrap_or_default(), text: swf_tag.initial_text.clone().unwrap_or_default(),
static_data: gc_arena::Gc::allocate(context.gc_context, EditTextStatic(swf_tag)), static_data: gc_arena::Gc::allocate(context.gc_context, EditTextStatic(swf_tag)),
} }

View File

@ -17,7 +17,7 @@ impl<'gc> Graphic<'gc> {
bounds: swf_shape.shape_bounds.clone().into(), bounds: swf_shape.shape_bounds.clone().into(),
}; };
Graphic { Graphic {
base: Default::default(), base: DisplayObjectBase::new(context.swf_version),
static_data: gc_arena::Gc::allocate(context.gc_context, static_data), static_data: gc_arena::Gc::allocate(context.gc_context, static_data),
} }
} }

View File

@ -13,11 +13,12 @@ pub struct MorphShape<'gc> {
impl<'gc> MorphShape<'gc> { impl<'gc> MorphShape<'gc> {
pub fn new( pub fn new(
swf_version: u8,
gc_context: gc_arena::MutationContext<'gc, '_>, gc_context: gc_arena::MutationContext<'gc, '_>,
static_data: MorphShapeStatic, static_data: MorphShapeStatic,
) -> Self { ) -> Self {
Self { Self {
base: Default::default(), base: DisplayObjectBase::new(swf_version),
static_data: gc_arena::Gc::allocate(gc_context, static_data), static_data: gc_arena::Gc::allocate(gc_context, static_data),
ratio: 0, ratio: 0,
} }

View File

@ -33,9 +33,9 @@ pub struct MovieClip<'gc> {
} }
impl<'gc> MovieClip<'gc> { impl<'gc> MovieClip<'gc> {
pub fn new(gc_context: MutationContext<'gc, '_>) -> Self { pub fn new(swf_version: u8, gc_context: MutationContext<'gc, '_>) -> Self {
Self { Self {
base: Default::default(), base: DisplayObjectBase::new(swf_version),
static_data: Gc::allocate(gc_context, MovieClipStatic::default()), static_data: Gc::allocate(gc_context, MovieClipStatic::default()),
tag_stream_pos: 0, tag_stream_pos: 0,
is_playing: false, is_playing: false,
@ -48,6 +48,7 @@ impl<'gc> MovieClip<'gc> {
} }
pub fn new_with_data( pub fn new_with_data(
swf_version: u8,
gc_context: MutationContext<'gc, '_>, gc_context: MutationContext<'gc, '_>,
id: CharacterId, id: CharacterId,
tag_stream_start: u64, tag_stream_start: u64,
@ -55,7 +56,7 @@ impl<'gc> MovieClip<'gc> {
num_frames: u16, num_frames: u16,
) -> Self { ) -> Self {
Self { Self {
base: Default::default(), base: DisplayObjectBase::new(swf_version),
static_data: Gc::allocate( static_data: Gc::allocate(
gc_context, gc_context,
MovieClipStatic { MovieClipStatic {
@ -951,8 +952,12 @@ impl<'gc, 'a> MovieClip<'gc> {
reader: &mut SwfStream<&'a [u8]>, reader: &mut SwfStream<&'a [u8]>,
) -> DecodeResult { ) -> DecodeResult {
let swf_button = reader.read_define_button_1()?; let swf_button = reader.read_define_button_1()?;
let button = let button = crate::button::Button::from_swf_tag(
crate::button::Button::from_swf_tag(&swf_button, &context.library, context.gc_context); context.swf_version,
&swf_button,
&context.library,
context.gc_context,
);
context context
.library .library
.register_character(swf_button.id, Character::Button(Box::new(button))); .register_character(swf_button.id, Character::Button(Box::new(button)));
@ -966,8 +971,12 @@ impl<'gc, 'a> MovieClip<'gc> {
reader: &mut SwfStream<&'a [u8]>, reader: &mut SwfStream<&'a [u8]>,
) -> DecodeResult { ) -> DecodeResult {
let swf_button = reader.read_define_button_2()?; let swf_button = reader.read_define_button_2()?;
let button = let button = crate::button::Button::from_swf_tag(
crate::button::Button::from_swf_tag(&swf_button, &context.library, context.gc_context); context.swf_version,
&swf_button,
&context.library,
context.gc_context,
);
context context
.library .library
.register_character(swf_button.id, Character::Button(Box::new(button))); .register_character(swf_button.id, Character::Button(Box::new(button)));
@ -1085,6 +1094,7 @@ impl<'gc, 'a> MovieClip<'gc> {
let id = reader.read_character_id()?; let id = reader.read_character_id()?;
let num_frames = reader.read_u16()?; let num_frames = reader.read_u16()?;
let mut movie_clip = MovieClip::new_with_data( let mut movie_clip = MovieClip::new_with_data(
context.swf_version,
context.gc_context, context.gc_context,
id, id,
reader.get_ref().position(), reader.get_ref().position(),

View File

@ -16,7 +16,7 @@ static DEVICE_FONT_TAG: &[u8] = include_bytes!("../assets/noto-sans-definefont3.
/// The newest known Flash Player version, serves as a default to /// The newest known Flash Player version, serves as a default to
/// `player_version`. /// `player_version`.
const NEWEST_PLAYER_VERSION: u8 = 32; pub const NEWEST_PLAYER_VERSION: u8 = 32;
#[derive(Collect)] #[derive(Collect)]
#[collect(empty_drop)] #[collect(empty_drop)]
@ -148,6 +148,7 @@ impl<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
root: GcCell::allocate( root: GcCell::allocate(
gc_context, gc_context,
Box::new(MovieClip::new_with_data( Box::new(MovieClip::new_with_data(
header.version,
gc_context, gc_context,
0, 0,
0, 0,
@ -460,7 +461,8 @@ impl<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
// Finalize morph shapes. // Finalize morph shapes.
for (id, static_data) in morph_shapes { for (id, static_data) in morph_shapes {
let morph_shape = crate::morph_shape::MorphShape::new(gc_context, static_data); let morph_shape =
crate::morph_shape::MorphShape::new(swf_version, gc_context, static_data);
update_context.library.register_character( update_context.library.register_character(
id, id,
crate::character::Character::MorphShape(Box::new(morph_shape)), crate::character::Character::MorphShape(Box::new(morph_shape)),

View File

@ -12,7 +12,7 @@ pub struct Text<'gc> {
impl<'gc> Text<'gc> { impl<'gc> Text<'gc> {
pub fn from_swf_tag(context: &mut UpdateContext<'_, 'gc, '_>, tag: &swf::Text) -> Self { pub fn from_swf_tag(context: &mut UpdateContext<'_, 'gc, '_>, tag: &swf::Text) -> Self {
Self { Self {
base: Default::default(), base: DisplayObjectBase::new(context.swf_version),
static_data: gc_arena::Gc::allocate( static_data: gc_arena::Gc::allocate(
context.gc_context, context.gc_context,
TextStatic { TextStatic {