Skip to content

Commit

Permalink
update to Nightly 2022-04-03
Browse files Browse the repository at this point in the history
  • Loading branch information
P-AS committed Apr 15, 2022
1 parent 0aff256 commit ff99c78
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 65 deletions.
4 changes: 2 additions & 2 deletions core/src/avm1/globals/movie_clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ pub fn hit_test<'gc>(
HitTestOptions::AVM_HIT_TEST,
)
} else {
movie_clip.hit_test_bounds(point)
movie_clip.hit_test_bounds(point, &BoundsMode::Script)
};
return Ok(ret.into());
}
Expand Down Expand Up @@ -1198,7 +1198,7 @@ fn get_bounds<'gc>(
};

if let Some(target) = target {
let bounds = movie_clip.bounds();
let bounds = movie_clip.bounds(&BoundsMode::Script);
let out_bounds = if DisplayObject::ptr_eq(movie_clip.into(), target) {
// Getting the clips bounds in its own coordinate space; no AABB transform needed.
bounds
Expand Down
3 changes: 2 additions & 1 deletion core/src/avm1/globals/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::avm1::object::transform_object::TransformObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value};
use crate::display_object::{DisplayObject, MovieClip, TDisplayObject};
use crate::prelude::*;
use gc_arena::MutationContext;

macro_rules! tx_getter {
Expand Down Expand Up @@ -155,7 +156,7 @@ fn pixel_bounds<'gc>(
clip: MovieClip<'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
// This is equivalent to `clip.getBounds()`.
let bounds = clip.world_bounds();
let bounds = clip.world_bounds(&BoundsMode::Script);

// Return Rectangle object.
let constructor = activation.context.avm1.prototypes.rectangle_constructor;
Expand Down
3 changes: 2 additions & 1 deletion core/src/avm2/globals/flash/display/displayobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::avm2::object::{stage_allocator, LoaderInfoObject, Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::display_object::{DisplayObject, HitTestOptions, TDisplayObject};
use crate::prelude::*;
use crate::types::{Degrees, Percent};
use crate::vminterface::Instantiator;
use gc_arena::{GcCell, MutationContext};
Expand Down Expand Up @@ -523,7 +524,7 @@ pub fn hit_test_point<'gc>(
)
.into());
} else {
return Ok(dobj.hit_test_bounds((x, y)).into());
return Ok(dobj.hit_test_bounds((x, y), &BoundsMode::Script).into());
}
}

Expand Down
83 changes: 47 additions & 36 deletions core/src/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,19 @@ pub fn render_base<'gc>(this: DisplayObject<'gc>, context: &mut RenderContext<'_
context.transform_stack.pop();
}

/// Indicates `bounds`, `local_bounds`, and `world_bounds` which kind of bounds
/// should be returned.
/// In most cases it's ignored and `BoundsMode::Engine` should be used.
pub enum BoundsMode {
/// The bounds visible on the stage (e.g. takes MorphShape ratio into
/// account).
Engine,

/// The bounds used internally and returned by ActionScript (e.g. doesn't
/// take MorphShape ratio into account).
Script,
}

#[enum_trait_object(
#[derive(Clone, Collect, Debug, Copy)]
#[collect(no_drop)]
Expand Down Expand Up @@ -506,44 +519,42 @@ pub trait TDisplayObject<'gc>:
self.base_mut(gc_context).set_depth(depth)
}

/// The untransformed inherent bounding box of this object.
/// These bounds do **not** include child DisplayObjects.
/// To get the bounds including children, use `bounds`, `local_bounds`, or `world_bounds`.
///
/// Implementors must override this method.
/// Leaf DisplayObjects should return their bounds.
/// Composite DisplayObjects that only contain children should return `&Default::default()`
fn self_bounds(&self) -> BoundingBox;

/// The untransformed bounding box of this object including children.
fn bounds(&self) -> BoundingBox {
self.bounds_with_transform(&Matrix::default())
fn bounds(&self, mode: &BoundsMode) -> BoundingBox {
self.bounds_with_transform(&Matrix::default(), mode)
}

/// The local bounding box of this object including children, in its parent's coordinate system.
fn local_bounds(&self) -> BoundingBox {
self.bounds_with_transform(self.base().matrix())
fn local_bounds(&self, mode: &BoundsMode) -> BoundingBox {
self.bounds_with_transform(self.base().matrix(), mode)
}

/// The world bounding box of this object including children, relative to the stage.
fn world_bounds(&self) -> BoundingBox {
self.bounds_with_transform(&self.local_to_global_matrix())
fn world_bounds(&self, mode: &BoundsMode) -> BoundingBox {
self.bounds_with_transform(&self.local_to_global_matrix(), mode)
}

/// The untransformed inherent bounding box of this object.
/// These bounds do *not* include child DisplayObjects.
/// To get the bounds including children, use `bounds`, `local_bounds`, or `world_bounds`.
///
/// Composite DisplayObjects that only contain children should return `&Default::default()`.
///
/// Do not use directly, use `bounds`, `local_bounds`, or `world_bounds`.
fn self_bounds(&self, mode: &BoundsMode) -> BoundingBox;

/// Gets the bounds of this object and all children, transformed by a given matrix.
/// This function recurses down and transforms the AABB each child before adding
/// it to the bounding box. This gives a tighter AABB then if we simply transformed
/// the overall AABB.
fn bounds_with_transform(&self, matrix: &Matrix) -> BoundingBox {
let mut bounds = self.self_bounds().transform(matrix);

fn bounds_with_transform(&self, matrix: &Matrix, mode: &BoundsMode) -> BoundingBox {
let mut bounds = self.self_bounds(&mode).transform(matrix);
if let Some(ctr) = self.as_container() {
for child in ctr.iter_render_list() {
let matrix = *matrix * *child.base().matrix();
bounds.union(&child.bounds_with_transform(&matrix));
bounds.union(&child.bounds_with_transform(&matrix, mode));
}
}

bounds
}

Expand Down Expand Up @@ -668,20 +679,18 @@ pub trait TDisplayObject<'gc>:
self.base_mut(gc_context).set_scale_y(value);
}

/// Sets the pixel width of this display object in local space.
/// The width is based on the AABB of the object.
/// Returned by the ActionScript `_width`/`width` properties.
/// Gets the pixel width of this display object in local space.
/// Returned by the `_width`/`width` ActionScript properties.
fn width(&self) -> f64 {
let bounds = self.local_bounds();
let bounds = self.local_bounds(&BoundsMode::Script);
(bounds.x_max.saturating_sub(bounds.x_min)).to_pixels()
}

/// Sets the pixel width of this display object in local space.
/// The width is based on the AABB of the object.
/// Set by the ActionScript `_width`/`width` properties.
/// Set by the `_width`/`width` ActionScript properties.
/// This does odd things on rotated clips to match the behavior of Flash.
fn set_width(&self, gc_context: MutationContext<'gc, '_>, value: f64) {
let object_bounds = self.bounds();
let object_bounds = self.bounds(&BoundsMode::Script);
let object_width = (object_bounds.x_max - object_bounds.x_min).to_pixels();
let object_height = (object_bounds.y_max - object_bounds.y_min).to_pixels();
let aspect_ratio = object_height / object_width;
Expand Down Expand Up @@ -718,18 +727,18 @@ pub trait TDisplayObject<'gc>:
self.set_scale_y(gc_context, Percent::from_unit(new_scale_y));
}

/// Gets the pixel height of the AABB containing this display object in local space.
/// Returned by the ActionScript `_height`/`height` properties.
/// Gets the pixel height of this display object in local space.
/// Returned by the `_height`/`height` ActionScript properties.
fn height(&self) -> f64 {
let bounds = self.local_bounds();
let bounds = self.local_bounds(&BoundsMode::Script);
(bounds.y_max.saturating_sub(bounds.y_min)).to_pixels()
}

/// Sets the pixel height of this display object in local space.
/// Set by the ActionScript `_height`/`height` properties.
/// Set by the `_height`/`height` ActionScript properties.
/// This does odd things on rotated clips to match the behavior of Flash.
fn set_height(&self, gc_context: MutationContext<'gc, '_>, value: f64) {
let object_bounds = self.bounds();
let object_bounds = self.bounds(&BoundsMode::Script);
let object_width = (object_bounds.x_max - object_bounds.x_min).to_pixels();
let object_height = (object_bounds.y_max - object_bounds.y_min).to_pixels();
let aspect_ratio = object_width / object_height;
Expand Down Expand Up @@ -1257,14 +1266,16 @@ pub trait TDisplayObject<'gc>:
fn set_object2(&mut self, _mc: MutationContext<'gc, '_>, _to: Avm2Object<'gc>) {}

/// Tests if a given stage position point intersects with the world bounds of this object.
fn hit_test_bounds(&self, pos: (Twips, Twips)) -> bool {
self.world_bounds().contains(pos)
fn hit_test_bounds(&self, pos: (Twips, Twips), mode: &BoundsMode) -> bool {
self.world_bounds(mode).contains(pos)
}

/// Tests if a given object's world bounds intersects with the world bounds
/// of this object.
fn hit_test_object(&self, other: DisplayObject<'gc>) -> bool {
self.world_bounds().intersects(&other.world_bounds())
//self.world_bounds().intersects(&other.world_bounds())
self.world_bounds(&BoundsMode::Script)
.intersects(&other.world_bounds(&BoundsMode::Script))
}

/// Tests if a given stage position point intersects within this object, considering the art.
Expand All @@ -1275,7 +1286,7 @@ pub trait TDisplayObject<'gc>:
_options: HitTestOptions,
) -> bool {
// Default to using bounding box.
self.hit_test_bounds(pos)
self.hit_test_bounds(pos, &BoundsMode::Engine)
}

fn post_instantiation(
Expand Down
2 changes: 1 addition & 1 deletion core/src/display_object/avm1_button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ impl<'gc> TDisplayObject<'gc> for Avm1Button<'gc> {
self.render_children(context);
}

fn self_bounds(&self) -> BoundingBox {
fn self_bounds(&self, _mode: &BoundsMode) -> BoundingBox {
// No inherent bounds; contains child DisplayObjects.
BoundingBox::default()
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/display_object/avm2_button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> {
}
}

fn self_bounds(&self) -> BoundingBox {
fn self_bounds(&self, _mode: &BoundsMode) -> BoundingBox {
// No inherent bounds; contains child DisplayObjects.
BoundingBox::default()
}
Expand Down
7 changes: 5 additions & 2 deletions core/src/display_object/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> {
self.0.read().static_data.id
}

fn self_bounds(&self) -> BoundingBox {
fn self_bounds(&self, _mode: &BoundsMode) -> BoundingBox {
BoundingBox {
x_min: Twips::ZERO,
y_min: Twips::ZERO,
Expand Down Expand Up @@ -266,7 +266,10 @@ impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> {
}

fn render_self(&self, context: &mut RenderContext) {
if !self.world_bounds().intersects(&context.stage.view_bounds()) {
if !self
.world_bounds(&BoundsMode::Engine)
.intersects(&context.stage.view_bounds())
{
// Off-screen; culled
return;
}
Expand Down
7 changes: 5 additions & 2 deletions core/src/display_object/edit_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1541,7 +1541,7 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
self.0.write(mc).object = Some(to.into());
}

fn self_bounds(&self) -> BoundingBox {
fn self_bounds(&self, _mode: &BoundsMode) -> BoundingBox {
self.0.read().bounds.clone()
}

Expand Down Expand Up @@ -1620,7 +1620,10 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
}

fn render_self(&self, context: &mut RenderContext<'_, 'gc>) {
if !self.world_bounds().intersects(&context.stage.view_bounds()) {
if !self
.world_bounds(&BoundsMode::Engine)
.intersects(&context.stage.view_bounds())
{
// Off-screen; culled
return;
}
Expand Down
9 changes: 6 additions & 3 deletions core/src/display_object/graphic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
self.0.read().static_data.id
}

fn self_bounds(&self) -> BoundingBox {
fn self_bounds(&self, _mode: &BoundsMode) -> BoundingBox {
if let Some(drawing) = &self.0.read().drawing {
drawing.self_bounds()
} else {
Expand Down Expand Up @@ -162,7 +162,10 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
}

fn render_self(&self, context: &mut RenderContext) {
if !self.world_bounds().intersects(&context.stage.view_bounds()) {
if !self
.world_bounds(&BoundsMode::Engine)
.intersects(&context.stage.view_bounds())
{
// Off-screen; culled
return;
}
Expand All @@ -183,7 +186,7 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
_options: HitTestOptions,
) -> bool {
// Transform point to local coordinates and test.
if self.world_bounds().contains(point) {
if self.world_bounds(&BoundsMode::Engine).contains(point) {
let local_matrix = self.global_to_local_matrix();
let point = local_matrix * point;
if let Some(drawing) = &self.0.read().drawing {
Expand Down
15 changes: 9 additions & 6 deletions core/src/display_object/morph_shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl<'gc> MorphShape<'gc> {
gc_context: gc_arena::MutationContext<'gc, '_>,
static_data: MorphShapeStatic,
) -> Self {
MorphShape(GcCell::allocate(
Self(GcCell::allocate(
gc_context,
MorphShapeData {
base: Default::default(),
Expand Down Expand Up @@ -95,9 +95,12 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
}
}

fn self_bounds(&self) -> BoundingBox {
// TODO: Use the bounds of the current ratio.
if let Some(frame) = self.0.read().static_data.frames.get(&self.ratio()) {
fn self_bounds(&self, mode: &BoundsMode) -> BoundingBox {
let ratio = match mode {
BoundsMode::Engine => self.ratio(),
BoundsMode::Script => 0,
};
if let Some(frame) = self.0.read().static_data.frames.get(&ratio) {
frame.bounds.clone()
} else {
BoundingBox::default()
Expand All @@ -110,7 +113,7 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
point: (Twips, Twips),
_options: HitTestOptions,
) -> bool {
if self.world_bounds().contains(point) {
if self.world_bounds(&BoundsMode::Engine).contains(point) {
if let Some(frame) = self.0.read().static_data.frames.get(&self.ratio()) {
let local_matrix = self.global_to_local_matrix();
let point = local_matrix * point;
Expand Down Expand Up @@ -216,7 +219,7 @@ impl MorphShapeStatic {
// TODO: Feels like this could be cleaned up a bit.
// We step through both the start records and end records, interpolating edges pairwise.
// Fill style/line style changes should only appear in the start records.
// However, StyleChangeRecord move_to can appear it both start and end records,
// However, StyleChangeRecord move_to can appear in both start and end records,
// and not necessarily in matching pairs; therefore, we have to keep track of the pen position
// in case one side is missing a move_to; it will implicitly use the last pen position.
while let (Some(s), Some(e)) = (start, end) {
Expand Down
6 changes: 3 additions & 3 deletions core/src/display_object/movie_clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1866,7 +1866,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
self.render_children(context);
}

fn self_bounds(&self) -> BoundingBox {
fn self_bounds(&self, _mode: &BoundsMode) -> BoundingBox {
self.0.read().drawing.self_bounds()
}

Expand All @@ -1887,7 +1887,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
return false;
}

if self.world_bounds().contains(point) {
if self.world_bounds(&BoundsMode::Engine).contains(point) {
if let Some(masker) = self.masker() {
if !masker.hit_test_shape(context, point, HitTestOptions::SKIP_INVISIBLE) {
return false;
Expand Down Expand Up @@ -2153,7 +2153,7 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> {
}
}

if self.world_bounds().contains(point) {
if self.world_bounds(&BoundsMode::Script).contains(point) {
// This MovieClip operates in "button mode" if it has a mouse handler,
// either via on(..) or via property mc.onRelease, etc.
let is_button_mode = self.is_button_mode(context);
Expand Down
2 changes: 1 addition & 1 deletion core/src/display_object/stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ impl<'gc> TDisplayObject<'gc> for Stage<'gc> {
u16::MAX
}

fn self_bounds(&self) -> BoundingBox {
fn self_bounds(&self, _mode: &BoundsMode) -> BoundingBox {
Default::default()
}

Expand Down
Loading

0 comments on commit ff99c78

Please sign in to comment.