Skip to content

Commit

Permalink
avm2: Implement DisplayObject z getter/setter
Browse files Browse the repository at this point in the history
They replace flash.display.DisplayObject z getter/setter stubs.
The z value (z translation) is now taken into account in wgpu rendering.
  • Loading branch information
cookie-s committed Feb 2, 2025
1 parent fcf91b7 commit ff05b1b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
24 changes: 17 additions & 7 deletions core/src/avm2/globals/flash/display/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,20 +412,30 @@ pub fn set_y<'gc>(
}

pub fn get_z<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Value<'gc>,
_activation: &mut Activation<'_, 'gc>,
this: Value<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
avm2_stub_getter!(activation, "flash.display.DisplayObject", "z");
Ok(0.into())
let this = this.as_object().unwrap();

if let Some(dobj) = this.as_display_object() {
return Ok(dobj.z().into());
}
Ok(Value::Undefined)
}

pub fn set_z<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Value<'gc>,
_args: &[Value<'gc>],
this: Value<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
avm2_stub_setter!(activation, "flash.display.DisplayObject", "z");
let this = this.as_object().unwrap();

if let Some(dobj) = this.as_display_object() {
let z = args.get_f64(activation, 0)?;
dobj.set_z(activation.gc(), z);
dobj.base_mut(activation.gc()).set_has_matrix3d_stub(true);
}
Ok(Value::Undefined)
}

Expand Down
11 changes: 6 additions & 5 deletions core/src/avm2/globals/flash/geom/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ pub fn get_matrix_3d<'gc>(
let display_object = get_display_object(this);
if display_object.base().has_matrix3d_stub() {
let matrix = *get_display_object(this).base().matrix();
let matrix3d = Matrix3D::from(matrix);
let mut matrix3d = Matrix3D::from(matrix);
matrix3d.set_tz(display_object.z());
matrix3d_to_object(matrix3d, activation)
} else {
Ok(Value::Null)
Expand All @@ -359,19 +360,19 @@ pub fn set_matrix_3d<'gc>(

let display_object = get_display_object(this);

let (matrix, has_matrix3d) = {
let (matrix, has_matrix3d, tz) = {
match args.try_get_object(activation, 0) {
Some(obj) => {
let matrix3d = object_to_matrix3d(obj, activation)?;
let matrix = Matrix::from(matrix3d);
let tz = matrix3d.tz();
display_object.base_mut(activation.gc()).set_tz(tz);
(matrix, true)
(matrix, true, tz)
}
None => (Matrix::IDENTITY, false),
None => (Matrix::IDENTITY, false, 0.0),
}
};

display_object.base_mut(activation.gc()).set_matrix_tz(tz);
display_object.set_matrix(activation.gc(), matrix);
if let Some(parent) = display_object.parent() {
// Self-transform changes are automatically handled,
Expand Down
36 changes: 35 additions & 1 deletion core/src/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,11 @@ impl<'gc> DisplayObjectBase<'gc> {
&mut self.transform.matrix
}

pub fn set_tz(&mut self, tz: f64) {
pub fn matrix_tz(&mut self) -> f64 {
self.transform.tz
}

pub fn set_matrix_tz(&mut self, tz: f64) {
self.transform.tz = tz;
}

Expand Down Expand Up @@ -379,6 +383,17 @@ impl<'gc> DisplayObjectBase<'gc> {
changed
}

fn z(&self) -> f64 {
self.transform.tz
}

fn set_z(&mut self, tz: f64) -> bool {
let changed = self.matrix_tz() != tz;
self.set_transformed_by_script(true);
self.set_matrix_tz(tz);
changed
}

/// Caches the scale and rotation factors for this display object, if necessary.
/// Calculating these requires heavy trig ops, so we only do it when `_xscale`, `_yscale` or
/// `_rotation` is accessed.
Expand Down Expand Up @@ -1380,6 +1395,25 @@ pub trait TDisplayObject<'gc>:
}
}

/// The `z` position in pixels of this display object in local space.
/// Returned by the `_z`/`z` ActionScript properties.
fn z(&self) -> f64 {
self.base().z()
}

/// Sets the `z` position of this display object in local space.
/// Set by the `_z`/`z` ActionScript properties.
/// This invalidates any ancestors cacheAsBitmap automatically.
fn set_z(&self, gc_context: &Mutation<'gc>, z: f64) {
if self.base_mut(gc_context).set_z(z) {
if let Some(parent) = self.parent() {
// Self-transform changes are automatically handled,
// we only want to inform ancestors to avoid unnecessary invalidations for tx/ty
parent.invalidate_cached_bitmap(gc_context);
}
}
}

/// The rotation in degrees this display object in local space.
/// Returned by the `_rotation`/`rotation` ActionScript properties.
fn rotation(&self, gc_context: &Mutation<'gc>) -> Degrees {
Expand Down

0 comments on commit ff05b1b

Please sign in to comment.