avm2: Respect SKIP_INVISIBLE for DisplayObject

Previously, we allowed mouse picks of certain invisible
DisplayObjects, even when HitTestOptions::SKIP_INVISIBLE
was set.
This commit is contained in:
Aaron Hill 2023-05-09 14:52:40 -05:00
parent 330766d668
commit 6025878aab
10 changed files with 136 additions and 8 deletions

View File

@ -1633,10 +1633,11 @@ pub trait TDisplayObject<'gc>:
&self, &self,
_context: &mut UpdateContext<'_, 'gc>, _context: &mut UpdateContext<'_, 'gc>,
point: Point<Twips>, point: Point<Twips>,
_options: HitTestOptions, options: HitTestOptions,
) -> bool { ) -> bool {
// Default to using bounding box. // Default to using bounding box.
self.hit_test_bounds(point) (!options.contains(HitTestOptions::SKIP_INVISIBLE) || self.visible())
&& self.hit_test_bounds(point)
} }
fn post_instantiation( fn post_instantiation(

View File

@ -201,10 +201,12 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
&self, &self,
_context: &mut UpdateContext<'_, 'gc>, _context: &mut UpdateContext<'_, 'gc>,
point: Point<Twips>, point: Point<Twips>,
_options: HitTestOptions, options: HitTestOptions,
) -> bool { ) -> bool {
// Transform point to local coordinates and test. // Transform point to local coordinates and test.
if self.world_bounds().contains(point) { if (!options.contains(HitTestOptions::SKIP_INVISIBLE) || self.visible())
&& self.world_bounds().contains(point)
{
let Some(local_matrix) = self.global_to_local_matrix() else { return false; }; let Some(local_matrix) = self.global_to_local_matrix() else { return false; };
let point = local_matrix * point; let point = local_matrix * point;
if let Some(drawing) = &self.0.read().drawing { if let Some(drawing) = &self.0.read().drawing {

View File

@ -151,9 +151,11 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> {
&self, &self,
_context: &mut UpdateContext<'_, 'gc>, _context: &mut UpdateContext<'_, 'gc>,
point: Point<Twips>, point: Point<Twips>,
_options: HitTestOptions, options: HitTestOptions,
) -> bool { ) -> bool {
if self.world_bounds().contains(point) { if (!options.contains(HitTestOptions::SKIP_INVISIBLE) || self.visible())
&& self.world_bounds().contains(point)
{
if let Some(frame) = self.0.read().static_data.frames.borrow().get(&self.ratio()) { if let Some(frame) = self.0.read().static_data.frames.borrow().get(&self.ratio()) {
let Some(local_matrix) = self.global_to_local_matrix() else { return false; }; let Some(local_matrix) = self.global_to_local_matrix() else { return false; };
return ruffle_render::shape_utils::shape_hit_test( return ruffle_render::shape_utils::shape_hit_test(

View File

@ -171,9 +171,11 @@ impl<'gc> TDisplayObject<'gc> for Text<'gc> {
&self, &self,
context: &mut UpdateContext<'_, 'gc>, context: &mut UpdateContext<'_, 'gc>,
mut point: Point<Twips>, mut point: Point<Twips>,
_options: HitTestOptions, options: HitTestOptions,
) -> bool { ) -> bool {
if self.world_bounds().contains(point) { if (!options.contains(HitTestOptions::SKIP_INVISIBLE) || self.visible())
&& self.world_bounds().contains(point)
{
// Texts using the "Advanced text rendering" always hit test using their bounding box. // Texts using the "Advanced text rendering" always hit test using their bounding box.
if self.0.read().render_settings.is_advanced() { if self.0.read().render_settings.is_advanced() {
return true; return true;

View File

@ -0,0 +1,46 @@
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Shape;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.text.TextField;
public class Test extends MovieClip {
public function Test() {
var shapeContainer = new Sprite();
shapeContainer.name = "MyShapeContainer";
var shape = new Shape();
shape.graphics.beginFill(0xFF0000);
shape.graphics.drawRect(0, 0, 100, 100);
shape.graphics.endFill();
shapeContainer.addChild(shape);
this.addChild(shapeContainer);
var bitmapContainer = new Sprite();
bitmapContainer.name = "MyBitmapContainer";
var bitmapData = new BitmapData(120, 120, false, 0);
var bitmap = new Bitmap(bitmapData);
bitmap.x = 150;
bitmap.name = "MyBitmap";
bitmapContainer.addChild(bitmap);
this.addChild(bitmapContainer);
var text = new TextField();
text.text = "Some text";
text.x = 300;
text.name = "MyText";
this.addChild(text);
shape.visible = false;
bitmap.visible = false;
text.visible = false;
this.stage.addEventListener(MouseEvent.CLICK, function(e) {
trace("Clicked " + e.target.name + " (" + e.stageX + ", " + e.stageY + ")");
});
}
}
}

View File

@ -0,0 +1,71 @@
[
{
"type": "MouseMove",
"pos": [
67,
49
]
},
{
"type": "MouseDown",
"pos": [
67,
49
],
"btn": "Left"
},
{
"type": "MouseUp",
"pos": [
67,
49
],
"btn": "Left"
},
{
"type": "MouseMove",
"pos": [
222,
61
]
},
{
"type": "MouseDown",
"pos": [
222,
61
],
"btn": "Left"
},
{
"type": "MouseUp",
"pos": [
222,
61
],
"btn": "Left"
},
{
"type": "MouseMove",
"pos": [
316,
12
]
},
{
"type": "MouseDown",
"pos": [
316,
12
],
"btn": "Left"
},
{
"type": "MouseUp",
"pos": [
316,
12
],
"btn": "Left"
}
]

View File

@ -0,0 +1,3 @@
Clicked null (67, 49)
Clicked null (222, 61)
Clicked null (316, 12)

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
num_frames = 1