From bd3cec0d205969f41ec84a11b7c11f60be29362f Mon Sep 17 00:00:00 2001 From: David Wendt Date: Fri, 13 Aug 2021 23:34:51 -0400 Subject: [PATCH] avm2: Impl `flash.media.SoundTransform` --- core/src/avm2/class.rs | 13 ++ core/src/avm2/globals.rs | 6 + core/src/avm2/globals/flash/media.rs | 1 + .../globals/flash/media/soundtransform.rs | 168 ++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 core/src/avm2/globals/flash/media/soundtransform.rs diff --git a/core/src/avm2/class.rs b/core/src/avm2/class.rs index 874b8d939..5d0a48a79 100644 --- a/core/src/avm2/class.rs +++ b/core/src/avm2/class.rs @@ -505,6 +505,19 @@ impl<'gc> Class<'gc> { } } #[inline(never)] + pub fn define_public_slot_number_class_traits( + &mut self, + items: &[(&'static str, Option)], + ) { + for &(name, value) in items { + self.define_class_trait(Trait::from_slot( + QName::new(Namespace::public(), name), + QName::new(Namespace::public(), "Number").into(), + value.map(|v| v.into()), + )); + } + } + #[inline(never)] pub fn define_public_constant_uint_class_traits(&mut self, items: &[(&'static str, u32)]) { for &(name, value) in items { self.define_class_trait(Trait::from_const( diff --git a/core/src/avm2/globals.rs b/core/src/avm2/globals.rs index 72a485ac5..3a23e4396 100644 --- a/core/src/avm2/globals.rs +++ b/core/src/avm2/globals.rs @@ -802,6 +802,12 @@ pub fn load_player_globals<'gc>( domain, script, )?; + class( + activation, + flash::media::soundtransform::create_class(mc), + domain, + script, + )?; // package `flash.text` avm2_system_class!( diff --git a/core/src/avm2/globals/flash/media.rs b/core/src/avm2/globals/flash/media.rs index 5a61e5886..997eef6ba 100644 --- a/core/src/avm2/globals/flash/media.rs +++ b/core/src/avm2/globals/flash/media.rs @@ -1,4 +1,5 @@ //! `flash.media` namespace pub mod sound; +pub mod soundtransform; pub mod video; diff --git a/core/src/avm2/globals/flash/media/soundtransform.rs b/core/src/avm2/globals/flash/media/soundtransform.rs new file mode 100644 index 000000000..666debb3f --- /dev/null +++ b/core/src/avm2/globals/flash/media/soundtransform.rs @@ -0,0 +1,168 @@ +//! `flash.media.SoundTransform` builtin/prototype + +use crate::avm2::activation::Activation; +use crate::avm2::class::{Class, ClassAttributes}; +use crate::avm2::method::{Method, NativeMethodImpl}; +use crate::avm2::names::{Namespace, QName}; +use crate::avm2::object::{Object, TObject}; +use crate::avm2::value::Value; +use crate::avm2::Error; +use gc_arena::{GcCell, MutationContext}; + +/// Implements `flash.media.SoundTransform`'s instance constructor. +pub fn instance_init<'gc>( + activation: &mut Activation<'_, 'gc, '_>, + this: Option>, + args: &[Value<'gc>], +) -> Result, Error> { + if let Some(mut this) = this { + activation.super_init(this, &[])?; + + let volume = args + .get(0) + .cloned() + .unwrap_or_else(|| 1.0.into()) + .coerce_to_number(activation)?; + let pan = args + .get(1) + .cloned() + .unwrap_or_else(|| 0.0.into()) + .coerce_to_number(activation)?; + + this.set_property( + this, + &QName::new(Namespace::public(), "volume"), + volume.into(), + activation, + )?; + this.set_property( + this, + &QName::new(Namespace::public(), "pan"), + pan.into(), + activation, + )?; + } + + Ok(Value::Undefined) +} + +/// Implements `flash.media.SoundTransform`'s class constructor. +pub fn class_init<'gc>( + _activation: &mut Activation<'_, 'gc, '_>, + _this: Option>, + _args: &[Value<'gc>], +) -> Result, Error> { + Ok(Value::Undefined) +} + +/// Implements `SoundTransform.pan`'s getter. +pub fn pan<'gc>( + activation: &mut Activation<'_, 'gc, '_>, + this: Option>, + _args: &[Value<'gc>], +) -> Result, Error> { + if let Some(this) = this { + let left_to_left = this + .get_property( + this, + &QName::new(Namespace::public(), "leftToLeft"), + activation, + )? + .coerce_to_number(activation)?; + + return Ok((1.0 - left_to_left.abs()).into()); + } + + Ok(Value::Undefined) +} + +/// Implements `SoundTransform.pan`'s setter. +pub fn set_pan<'gc>( + activation: &mut Activation<'_, 'gc, '_>, + this: Option>, + args: &[Value<'gc>], +) -> Result, Error> { + if let Some(mut this) = this { + let pan = args + .get(0) + .cloned() + .unwrap_or(Value::Undefined) + .coerce_to_number(activation)?; + + if pan >= 0.0 { + this.set_property( + this, + &QName::new(Namespace::public(), "leftToLeft"), + (1.0 - pan).into(), + activation, + )?; + this.set_property( + this, + &QName::new(Namespace::public(), "rightToRight"), + (1.0).into(), + activation, + )?; + } else { + this.set_property( + this, + &QName::new(Namespace::public(), "leftToLeft"), + (1.0).into(), + activation, + )?; + this.set_property( + this, + &QName::new(Namespace::public(), "rightToRight"), + (1.0 + pan).into(), + activation, + )?; + } + + this.set_property( + this, + &QName::new(Namespace::public(), "leftToRight"), + (0.0).into(), + activation, + )?; + this.set_property( + this, + &QName::new(Namespace::public(), "rightToLeft"), + (0.0).into(), + activation, + )?; + } + + Ok(Value::Undefined) +} + +/// Construct `SoundTransform`'s class. +pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> { + let class = Class::new( + QName::new(Namespace::package("flash.media"), "SoundTransform"), + Some(QName::new(Namespace::package("flash.media"), "DisplayObject").into()), + Method::from_builtin(instance_init, "", mc), + Method::from_builtin(class_init, "", mc), + mc, + ); + + let mut write = class.write(mc); + + write.set_attributes(ClassAttributes::SEALED); + + const PUBLIC_INSTANCE_PROPERTIES: &[( + &str, + Option, + Option, + )] = &[("pan", Some(pan), Some(set_pan))]; + write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES); + + const PUBLIC_INSTANCE_SLOTS: &[(&str, Option)] = &[ + ("leftToLeft", None), + ("leftToRight", None), + ("rightToLeft", None), + ("rightToRight", None), + ("volume", None), + ]; + write.define_public_slot_number_class_traits(PUBLIC_INSTANCE_SLOTS); + + class +}