Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions core/src/avm1/globals/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ fn tab_index<'gc>(
this: Avm1Button<'gc>,
_activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(index) = this.as_interactive().and_then(|this| this.tab_index()) {
if let Some(index) = this.tab_index() {
Ok(Value::Number(index as f64))
} else {
Ok(Value::Undefined)
Expand All @@ -176,18 +176,16 @@ fn set_tab_index<'gc>(
activation: &mut Activation<'_, 'gc>,
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
if let Some(this) = this.as_interactive() {
let value = match value {
Value::Undefined | Value::Null => None,
Value::Bool(_) | Value::Number(_) => {
// FIXME This coercion is not perfect, as it wraps
// instead of falling back to MIN, as FP does
let i32_value = value.coerce_to_i32(activation)?;
Some(i32_value)
}
_ => Some(i32::MIN),
};
this.set_tab_index(value);
}
let value = match value {
Value::Undefined | Value::Null => None,
Value::Bool(_) | Value::Number(_) => {
// FIXME This coercion is not perfect, as it wraps
// instead of falling back to MIN, as FP does
let i32_value = value.coerce_to_i32(activation)?;
Some(i32_value)
}
_ => Some(i32::MIN),
};
this.set_tab_index(value);
Ok(())
}
26 changes: 12 additions & 14 deletions core/src/avm1/globals/movie_clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1793,7 +1793,7 @@ fn tab_index<'gc>(
this: MovieClip<'gc>,
_activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(index) = this.as_interactive().and_then(|this| this.tab_index()) {
if let Some(index) = this.tab_index() {
Ok(Value::Number(index as f64))
} else {
Ok(Value::Undefined)
Expand All @@ -1805,18 +1805,16 @@ fn set_tab_index<'gc>(
activation: &mut Activation<'_, 'gc>,
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
if let Some(this) = this.as_interactive() {
let value = match value {
Value::Undefined | Value::Null => None,
Value::Bool(_) | Value::Number(_) => {
// FIXME This coercion is not perfect, as it wraps
// instead of falling back to MIN, as FP does
let i32_value = value.coerce_to_i32(activation)?;
Some(i32_value)
}
_ => Some(i32::MIN),
};
this.set_tab_index(value);
}
let value = match value {
Value::Undefined | Value::Null => None,
Value::Bool(_) | Value::Number(_) => {
// FIXME This coercion is not perfect, as it wraps
// instead of falling back to MIN, as FP does
let i32_value = value.coerce_to_i32(activation)?;
Some(i32_value)
}
_ => Some(i32::MIN),
};
this.set_tab_index(value);
Ok(())
}
26 changes: 12 additions & 14 deletions core/src/avm1/globals/text_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ pub fn tab_index<'gc>(
this: EditText<'gc>,
_activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(index) = this.as_interactive().and_then(|this| this.tab_index()) {
if let Some(index) = this.tab_index() {
Ok(Value::Number(index as u32 as f64))
} else {
Ok(Value::Undefined)
Expand All @@ -894,19 +894,17 @@ pub fn set_tab_index<'gc>(
activation: &mut Activation<'_, 'gc>,
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
if let Some(this) = this.as_interactive() {
let value = match value {
Value::Undefined | Value::Null => None,
_ => {
// `tabIndex` is u32 in TextField, compared to i32 in Button and MovieClip,
// but that is only a data representation difference,
// as both are interpreted as i32.
let u32_value = value.coerce_to_u32(activation)?;
Some(u32_value as i32)
}
};
this.set_tab_index(value);
}
let value = match value {
Value::Undefined | Value::Null => None,
_ => {
// `tabIndex` is u32 in TextField, compared to i32 in Button and MovieClip,
// but that is only a data representation difference,
// as both are interpreted as i32.
let u32_value = value.coerce_to_u32(activation)?;
Some(u32_value as i32)
}
};
this.set_tab_index(value);
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/avm1/globals/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::avm1::object::NativeObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::value::Value;
use crate::avm1::Object;
use crate::display_object::{TDisplayObject, Video};
use crate::display_object::Video;
use crate::string::StringContext;

macro_rules! video_method {
Expand Down
2 changes: 1 addition & 1 deletion core/src/avm2/globals/flash/display/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::avm2::error::make_error_2008;
use crate::avm2::parameters::ParametersExt;
use crate::bitmap::bitmap_data::BitmapData;
use crate::character::Character;
use crate::display_object::{Bitmap, TDisplayObject};
use crate::display_object::Bitmap;

pub fn bitmap_allocator<'gc>(
class: ClassObject<'gc>,
Expand Down
1 change: 0 additions & 1 deletion core/src/avm2/globals/flash/display/bitmap_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use crate::bitmap::bitmap_data::{BitmapData, ChannelOptions, ThresholdOperation}
use crate::bitmap::bitmap_data::{BitmapDataDrawError, IBitmapDrawable};
use crate::bitmap::{is_size_valid, operations};
use crate::character::{Character, CompressedBitmap};
use crate::display_object::TDisplayObject;
use crate::ecma_conversions::round_to_even;
use crate::swf::BlendMode;
use ruffle_render::filters::Filter;
Expand Down
2 changes: 1 addition & 1 deletion core/src/avm2/globals/flash/display/interactive_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::avm2::error::make_error_2027;
use crate::avm2::parameters::ParametersExt;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::display_object::{TDisplayObject, TInteractiveObject};
use crate::display_object::TInteractiveObject;

/// Implements `InteractiveObject.mouseEnabled`'s getter.
pub fn get_mouse_enabled<'gc>(
Expand Down
2 changes: 1 addition & 1 deletion core/src/avm2/globals/flash/display/movie_clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::avm2::object::ArrayObject;
use crate::avm2::parameters::ParametersExt;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::display_object::{MovieClip, Scene, TDisplayObject};
use crate::display_object::{MovieClip, Scene};
use crate::string::{AvmString, WString};

/// Implements `addFrameScript`, an undocumented method of `MovieClip` used to
Expand Down
2 changes: 1 addition & 1 deletion core/src/avm2/globals/flash/media/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::avm2::globals::flash::display::display_object::initialize_for_allocat
use crate::avm2::parameters::ParametersExt;
use crate::avm2::{Activation, ClassObject, Object, Value};
use crate::avm2_stub_method;
use crate::display_object::{TDisplayObject, Video};
use crate::display_object::Video;

pub fn video_allocator<'gc>(
class: ClassObject<'gc>,
Expand Down
1 change: 0 additions & 1 deletion core/src/avm2/globals/flash/text/engine/text_line.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::avm2::activation::Activation;
use crate::avm2::error::Error;
use crate::avm2::value::Value;
use crate::display_object::TDisplayObject;

pub fn get_text_width<'gc>(
activation: &mut Activation<'_, 'gc>,
Expand Down
1 change: 0 additions & 1 deletion core/src/avm2/globals/flash/text/static_text.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::avm2::{Activation, Error, Value};
use crate::prelude::TDisplayObject;
use crate::string::AvmString;

/// Implements `StaticText.text`
Expand Down
2 changes: 1 addition & 1 deletion core/src/avm2/globals/flash/text/text_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::avm2::object::{ClassObject, Object, TextFormatObject};
use crate::avm2::parameters::ParametersExt;
use crate::avm2::value::Value;
use crate::avm2::{ArrayObject, ArrayStorage, Error};
use crate::display_object::{AutoSizeMode, EditText, TDisplayObject, TextSelection};
use crate::display_object::{AutoSizeMode, EditText, TextSelection};
use crate::html::TextFormat;
use crate::string::AvmString;
use crate::{avm2_stub_getter, avm2_stub_setter};
Expand Down
2 changes: 1 addition & 1 deletion core/src/avm2/object/loaderinfo_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::avm2::object::script_object::ScriptObjectData;
use crate::avm2::object::{EventObject, Object, StageObject, TObject};
use crate::avm2::{Avm2, Error, Value};
use crate::context::UpdateContext;
use crate::display_object::{DisplayObject, TDisplayObject};
use crate::display_object::DisplayObject;
use crate::loader::ContentType;
use crate::tag_utils::SwfMovie;
use crate::utils::HasPrefixField;
Expand Down
4 changes: 2 additions & 2 deletions core/src/context_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use crate::avm1;
use crate::avm2;
use crate::context::UpdateContext;
use crate::display_object::{DisplayObject, InteractiveObject, TDisplayObject};
use crate::display_object::{DisplayObject, InteractiveObject};
use crate::display_object::{EditText, Stage};
use crate::events::TextControlCode;
use crate::i18n::core_text;
Expand Down Expand Up @@ -60,7 +60,7 @@ impl<'gc> ContextMenuState<'gc> {
// When a text field is focused and the mouse is hovering it,
// show the copy/paste menu.
if let Some(text) = context.focus_tracker.get_as_edit_text() {
if InteractiveObject::option_ptr_eq(context.mouse_data.hovered, text.as_interactive()) {
if InteractiveObject::option_ptr_eq(context.mouse_data.hovered, Some(text.into())) {
self.build_text_items(text, context);
return;
}
Expand Down
110 changes: 60 additions & 50 deletions core/src/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,11 @@ pub trait TDisplayObject<'gc>:
{
fn base(self) -> Gc<'gc, DisplayObjectBase<'gc>>;

#[no_dynamic]
fn as_ptr(self) -> *const DisplayObjectPtr {
Gc::as_ptr(self.base()).cast()
}

/// The `SCALE_ROTATION_CACHED` flag should only be set in SWFv5+.
/// So scaling/rotation values always have to get recalculated from the matrix in SWFv4.
#[no_dynamic]
Expand Down Expand Up @@ -2280,54 +2285,6 @@ pub trait TDisplayObject<'gc>:
None
}

fn as_stage(self) -> Option<Stage<'gc>> {
None
}

fn as_avm1_button(self) -> Option<Avm1Button<'gc>> {
None
}

fn as_avm2_button(self) -> Option<Avm2Button<'gc>> {
None
}

fn as_movie_clip(self) -> Option<MovieClip<'gc>> {
None
}

fn as_edit_text(self) -> Option<EditText<'gc>> {
None
}

fn as_text(self) -> Option<Text<'gc>> {
None
}

fn as_morph_shape(self) -> Option<MorphShape<'gc>> {
None
}

fn as_container(self) -> Option<DisplayObjectContainer<'gc>> {
None
}

fn as_video(self) -> Option<Video<'gc>> {
None
}

fn as_drawing(&self) -> Option<RefMut<'_, Drawing>> {
None
}

fn as_bitmap(self) -> Option<Bitmap<'gc>> {
None
}

fn as_interactive(self) -> Option<InteractiveObject<'gc>> {
None
}

#[no_dynamic]
fn apply_place_object(self, context: &mut UpdateContext<'gc>, place_object: &swf::PlaceObject) {
// PlaceObject tags only apply if this object has not been dynamically moved by AS code.
Expand Down Expand Up @@ -2448,8 +2405,6 @@ pub trait TDisplayObject<'gc>:

fn instantiate(self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc>;

fn as_ptr(self) -> *const DisplayObjectPtr;

/// Whether this object can be used as a mask.
/// If this returns false and this object is used as a mask, the mask will not be applied.
/// This is used by movie clips to disable the mask when there are no children, for example.
Expand Down Expand Up @@ -2658,10 +2613,41 @@ pub trait TDisplayObject<'gc>:
let _ = object.set(name, value, &mut activation);
}
}

fn as_drawing(&self) -> Option<RefMut<'_, Drawing>> {
None
}

#[no_dynamic]
fn as_container(self) -> Option<DisplayObjectContainer<'gc>> {
match self {
Self::Avm1Button(dobj) => Some(DisplayObjectContainer::Avm1Button(dobj)),
Self::LoaderDisplay(dobj) => Some(DisplayObjectContainer::LoaderDisplay(dobj)),
Self::MovieClip(dobj) => Some(DisplayObjectContainer::MovieClip(dobj)),
Self::Stage(dobj) => Some(DisplayObjectContainer::Stage(dobj)),
_ => None,
}
}
}

pub enum DisplayObjectPtr {}

macro_rules! impl_downcast_methods {
($(
$vis:vis fn $fn_name:ident for $variant:ident;
)*) => { $(
#[doc = concat!("Downcast this display object as a `", stringify!($variant), "`.")]
#[inline(always)]
$vis fn $fn_name(self) -> Option<$variant<'gc>> {
if let Self::$variant(obj) = self {
Some(obj)
} else {
None
}
}
)* }
}

impl<'gc> DisplayObject<'gc> {
pub fn ptr_eq(a: DisplayObject<'gc>, b: DisplayObject<'gc>) -> bool {
std::ptr::eq(a.as_ptr(), b.as_ptr())
Expand All @@ -2671,6 +2657,30 @@ impl<'gc> DisplayObject<'gc> {
a.map(|o| o.as_ptr()) == b.map(|o| o.as_ptr())
}

impl_downcast_methods! {
pub fn as_stage for Stage;
pub fn as_avm1_button for Avm1Button;
pub fn as_avm2_button for Avm2Button;
pub fn as_movie_clip for MovieClip;
pub fn as_edit_text for EditText;
pub fn as_text for Text;
pub fn as_morph_shape for MorphShape;
pub fn as_video for Video;
pub fn as_bitmap for Bitmap;
}

pub fn as_interactive(self) -> Option<InteractiveObject<'gc>> {
match self {
Self::Avm1Button(dobj) => Some(InteractiveObject::Avm1Button(dobj)),
Self::Avm2Button(dobj) => Some(InteractiveObject::Avm2Button(dobj)),
Self::EditText(dobj) => Some(InteractiveObject::EditText(dobj)),
Self::LoaderDisplay(dobj) => Some(InteractiveObject::LoaderDisplay(dobj)),
Self::MovieClip(dobj) => Some(InteractiveObject::MovieClip(dobj)),
Self::Stage(dobj) => Some(InteractiveObject::Stage(dobj)),
_ => None,
}
}

pub fn downgrade(self) -> DisplayObjectWeak<'gc> {
match self {
DisplayObject::MovieClip(mc) => DisplayObjectWeak::MovieClip(mc.downgrade()),
Expand Down
Loading
Loading