avm2: Add initial implementation of `Matrix`
This implements the `a, b, c, d, tx, ty` properties, as well as the constructor, `identity`, and `scale` methods.
This commit is contained in:
parent
e9167cf43c
commit
e87ad52deb
|
@ -814,6 +814,7 @@ pub fn load_player_globals<'gc>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// package `flash.geom`
|
// package `flash.geom`
|
||||||
|
class(activation, flash::geom::matrix::create_class(mc), script)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
point,
|
point,
|
||||||
activation,
|
activation,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//! `flash.geom` namespace
|
//! `flash.geom` namespace
|
||||||
|
|
||||||
|
pub mod matrix;
|
||||||
pub mod point;
|
pub mod point;
|
||||||
pub mod rectangle;
|
pub mod rectangle;
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
//! `flash.geom.Matrix` builtin/prototype
|
||||||
|
|
||||||
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::{Method, NativeMethodImpl};
|
||||||
|
use crate::avm2::{Activation, Error, Namespace, Object, QName, TObject, Value};
|
||||||
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn set_values<'gc>(
|
||||||
|
this: &mut Object<'gc>,
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
a: f64,
|
||||||
|
b: f64,
|
||||||
|
c: f64,
|
||||||
|
d: f64,
|
||||||
|
tx: f64,
|
||||||
|
ty: f64,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "a").into(),
|
||||||
|
a.into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "b").into(),
|
||||||
|
b.into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "c").into(),
|
||||||
|
c.into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "d").into(),
|
||||||
|
d.into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "tx").into(),
|
||||||
|
tx.into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "ty").into(),
|
||||||
|
ty.into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements `flash.geom.Matrix`'s instance constructor.
|
||||||
|
pub fn instance_init<'gc>(
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
this: Option<Object<'gc>>,
|
||||||
|
args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
if let Some(mut this) = this {
|
||||||
|
let a = args
|
||||||
|
.get(0)
|
||||||
|
.unwrap_or(&1f64.into())
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
|
||||||
|
let b = args
|
||||||
|
.get(1)
|
||||||
|
.unwrap_or(&0f64.into())
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
|
||||||
|
let c = args
|
||||||
|
.get(2)
|
||||||
|
.unwrap_or(&0f64.into())
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
|
||||||
|
let d = args
|
||||||
|
.get(3)
|
||||||
|
.unwrap_or(&1f64.into())
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
|
||||||
|
let tx = args
|
||||||
|
.get(4)
|
||||||
|
.unwrap_or(&0f64.into())
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
|
||||||
|
let ty = args
|
||||||
|
.get(5)
|
||||||
|
.unwrap_or(&0f64.into())
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
|
||||||
|
set_values(&mut this, activation, a, b, c, d, tx, ty)?;
|
||||||
|
}
|
||||||
|
Ok(Value::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements `flash.geom.Matrix`'s class initializer.
|
||||||
|
pub fn class_init<'gc>(
|
||||||
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
Ok(Value::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements `identity'
|
||||||
|
pub fn identity<'gc>(
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
this: Option<Object<'gc>>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
if let Some(mut this) = this {
|
||||||
|
set_values(&mut this, activation, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0)?;
|
||||||
|
}
|
||||||
|
Ok(Value::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements `scale'
|
||||||
|
pub fn scale<'gc>(
|
||||||
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
this: Option<Object<'gc>>,
|
||||||
|
args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
if let Some(mut this) = this {
|
||||||
|
let sx = if let Some(sx) = args.get(0) {
|
||||||
|
sx.coerce_to_number(activation)?
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"Expected 2 arguments in flash.geom::Matrix/scale(), got {}",
|
||||||
|
args.len()
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
};
|
||||||
|
let sy = if let Some(sy) = args.get(1) {
|
||||||
|
sy.coerce_to_number(activation)?
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"Expected 2 arguments in flash.geom::Matrix/scale(), got {}",
|
||||||
|
args.len()
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
let a = this
|
||||||
|
.get_property(&QName::new(Namespace::public(), "a").into(), activation)?
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
let d = this
|
||||||
|
.get_property(&QName::new(Namespace::public(), "d").into(), activation)?
|
||||||
|
.coerce_to_number(activation)?;
|
||||||
|
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "a").into(),
|
||||||
|
(sx * a).into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
this.set_property(
|
||||||
|
&QName::new(Namespace::public(), "d").into(),
|
||||||
|
(sy * d).into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(Value::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct `Matrix`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
let class = Class::new(
|
||||||
|
QName::new(Namespace::package("flash.geom"), "Matrix"),
|
||||||
|
Some(QName::new(Namespace::public(), "Object").into()),
|
||||||
|
Method::from_builtin(instance_init, "<Matrix instance initializer>", mc),
|
||||||
|
Method::from_builtin(class_init, "<Matrix class initializer>", mc),
|
||||||
|
mc,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut write = class.write(mc);
|
||||||
|
|
||||||
|
const PUBLIC_INSTANCE_NUMBER_SLOTS: &[(&str, Option<f64>)] = &[
|
||||||
|
("a", None),
|
||||||
|
("b", None),
|
||||||
|
("c", None),
|
||||||
|
("d", None),
|
||||||
|
("tx", None),
|
||||||
|
("ty", None),
|
||||||
|
];
|
||||||
|
write.define_public_slot_number_instance_traits(PUBLIC_INSTANCE_NUMBER_SLOTS);
|
||||||
|
|
||||||
|
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] =
|
||||||
|
&[("identity", identity), ("scale", scale)];
|
||||||
|
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
|
||||||
|
|
||||||
|
class
|
||||||
|
}
|
Loading…
Reference in New Issue