-
-
Notifications
You must be signed in to change notification settings - Fork 885
avm2: Store PerspectiveProjection to DisplayObject #19670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
de8be6b
1ede9d0
6da5290
5a92253
e624855
ce0b9ad
60b626a
744856c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ use crate::avm2::globals::slots::flash_geom_color_transform as ct_slots; | |
use crate::avm2::globals::slots::flash_geom_matrix as matrix_slots; | ||
use crate::avm2::globals::slots::flash_geom_matrix_3d as matrix3d_slots; | ||
use crate::avm2::globals::slots::flash_geom_perspective_projection as pp_slots; | ||
use crate::avm2::globals::slots::flash_geom_point as point_slots; | ||
use crate::avm2::globals::slots::flash_geom_transform as transform_slots; | ||
use crate::avm2::object::VectorObject; | ||
use crate::avm2::parameters::ParametersExt; | ||
|
@@ -11,6 +12,7 @@ use crate::display_object::TDisplayObject; | |
use crate::prelude::{DisplayObject, Matrix, Twips}; | ||
use crate::{avm2_stub_getter, avm2_stub_setter}; | ||
use ruffle_render::matrix3d::Matrix3D; | ||
use ruffle_render::perspective_projection::PerspectiveProjection; | ||
use ruffle_render::quality::StageQuality; | ||
use swf::{ColorTransform, Fixed8, Rectangle}; | ||
|
||
|
@@ -248,6 +250,32 @@ fn object_to_matrix3d<'gc>( | |
Ok(Matrix3D { raw_data }) | ||
} | ||
|
||
pub fn object_to_perspective_projection<'gc>( | ||
object: Object<'gc>, | ||
_activation: &mut Activation<'_, 'gc>, | ||
) -> Result<PerspectiveProjection, Error<'gc>> { | ||
if let Some(display_object) = object.get_slot(pp_slots::DISPLAY_OBJECT).as_object() { | ||
return Ok(display_object | ||
.as_display_object() | ||
.unwrap() | ||
.base() | ||
.perspective_projection() | ||
.copied() | ||
.unwrap_or_default()); | ||
} | ||
|
||
let fov = object.get_slot(pp_slots::FOV).as_f64(); | ||
|
||
let center = object.get_slot(pp_slots::CENTER).as_object().unwrap(); | ||
let x = center.get_slot(point_slots::X).as_f64(); | ||
let y = center.get_slot(point_slots::Y).as_f64(); | ||
|
||
Ok(PerspectiveProjection { | ||
field_of_view: fov, | ||
center: (x, y), | ||
}) | ||
} | ||
|
||
pub fn matrix_to_object<'gc>( | ||
matrix: Matrix, | ||
activation: &mut Activation<'_, 'gc>, | ||
|
@@ -389,44 +417,25 @@ pub fn get_perspective_projection<'gc>( | |
) -> Result<Value<'gc>, Error<'gc>> { | ||
let this = this.as_object().unwrap(); | ||
|
||
avm2_stub_getter!(activation, "flash.geom.Transform", "perspectiveProjection"); | ||
|
||
let display_object = get_display_object(this); | ||
let has_perspective_projection = if display_object.is_root() { | ||
true | ||
} else { | ||
display_object.base().has_perspective_projection_stub() | ||
}; | ||
|
||
if has_perspective_projection { | ||
let result = activation | ||
if get_display_object(this) | ||
.base() | ||
.perspective_projection() | ||
.is_some() | ||
{ | ||
let object = activation | ||
.avm2() | ||
.classes() | ||
.perspectiveprojection | ||
.construct(activation, &[])?; | ||
.construct(activation, &[])? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, does this really return a new PerspectiveProjection each time the getter is called? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, to make it clear, I added a test case |
||
.as_object() | ||
.unwrap(); | ||
|
||
let object = result.as_object().unwrap(); | ||
object.set_slot( | ||
pp_slots::DISPLAY_OBJECT, | ||
this.get_slot(transform_slots::DISPLAY_OBJECT), | ||
activation, | ||
)?; | ||
|
||
if display_object.is_root() && display_object.as_stage().is_none() { | ||
// TODO: Move this special PerspectiveProjection assignment to `root` object initialization time. | ||
// This should be assigned to `root.transform` from the beginning. | ||
|
||
let (width, height) = activation.context.stage.stage_size(); | ||
|
||
let center = activation.avm2().classes().point.construct( | ||
activation, | ||
&[(width as f64 / 2.0).into(), (height as f64 / 2.0).into()], | ||
)?; | ||
|
||
object.set_slot(pp_slots::CENTER, center, activation)?; | ||
} | ||
|
||
Ok(result) | ||
Ok(object.into()) | ||
} else { | ||
Ok(Value::Null) | ||
} | ||
|
@@ -439,15 +448,15 @@ pub fn set_perspective_projection<'gc>( | |
) -> Result<Value<'gc>, Error<'gc>> { | ||
let this = this.as_object().unwrap(); | ||
|
||
// FIXME: Render with the given PerspectiveProjection. | ||
avm2_stub_setter!(activation, "flash.geom.Transform", "perspectiveProjection"); | ||
|
||
let set = args | ||
.get(0) | ||
.map(|arg| arg.as_object().is_some()) | ||
.unwrap_or_default(); | ||
let display_object = get_display_object(this); | ||
display_object | ||
.base() | ||
.set_has_perspective_projection_stub(set); | ||
let perspective_projection = args | ||
.try_get_object(activation, 0) | ||
.map(|object| object_to_perspective_projection(object, activation)) | ||
.transpose()?; | ||
|
||
get_display_object(this).set_perspective_projection(activation.gc(), perspective_projection); | ||
|
||
Ok(Value::Undefined) | ||
} |
Uh oh!
There was an error while loading. Please reload this page.