From 9d70b9c8a59e2b2720c360727dd58752519686d0 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Sat, 10 Dec 2022 03:52:58 +0000 Subject: [PATCH 01/14] avm2: Fix hittests on depth=0 children --- core/src/display_object/movie_clip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index bc2ddee073cc..3cc858690b11 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -2484,7 +2484,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> { } else { clip_depth = child.clip_depth(); } - } else if child.depth() > clip_depth + } else if child.depth() >= clip_depth && child.hit_test_shape(context, point, options) { return true; From 29a38aa9db32569645065143dd47c3a6a50f0380 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Sat, 10 Dec 2022 03:53:15 +0000 Subject: [PATCH 02/14] avm2: Fix SimpleButton bounds --- core/src/display_object/avm2_button.rs | 2 +- render/src/bounding_box.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index a327b4662207..753616ba996f 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -640,7 +640,7 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> { fn self_bounds(&self) -> BoundingBox { // No inherent bounds; contains child DisplayObjects. - BoundingBox::default() + BoundingBox::empty() } fn hit_test_shape( diff --git a/render/src/bounding_box.rs b/render/src/bounding_box.rs index f07835d933a6..18b25490195c 100644 --- a/render/src/bounding_box.rs +++ b/render/src/bounding_box.rs @@ -11,6 +11,14 @@ pub struct BoundingBox { } impl BoundingBox { + /// Create a zero-sized, valid BoundingBox + pub fn empty() -> Self { + Self { + valid: true, + .. Default::default() + } + } + /// Clamps the given point inside this bounding box. pub fn clamp(&self, (x, y): (Twips, Twips)) -> (Twips, Twips) { if self.valid { From f542c9abc4e89bf50ef8fc3d09b0d2924f3e0ee3 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Sun, 11 Dec 2022 17:18:56 +0000 Subject: [PATCH 03/14] avm2: MouseEnabled shouldn't affect abillity to select children Fixes #8694 --- core/src/display_object/movie_clip.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 3cc858690b11..699b609501bd 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -2737,7 +2737,7 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { point: (Twips, Twips), require_button_mode: bool, ) -> Option> { - if self.visible() && self.mouse_enabled() { + if self.visible() { let this: InteractiveObject<'gc> = (*self).into(); if let Some(masker) = self.masker() { @@ -2746,7 +2746,12 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { } } - if self.world_bounds().contains(point) { + // In AVM2, mouse_enabled should only impact the ability to select the current clip + // but it should still be possible to select any children where child.mouse_enabled() is + // true. + // InteractiveObject.mouseEnabled: + // "Any children of this instance on the display list are not affected." + if self.mouse_enabled() && self.world_bounds().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); @@ -2782,7 +2787,8 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { } else if result.is_none() { if let Some(child) = child.as_interactive() { result = child.mouse_pick(context, point, require_button_mode); - } else if check_non_interactive && child.hit_test_shape(context, point, options) + } else if check_non_interactive && self.mouse_enabled() && + child.hit_test_shape(context, point, options) { result = Some(this); } @@ -2797,8 +2803,8 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { return result; } - // Check drawing. - if check_non_interactive { + // Check drawing, because this selects the current clip, it must have mouse enabled + if self.mouse_enabled() && check_non_interactive { let local_matrix = self.global_to_local_matrix(); let point = local_matrix * point; if self.0.read().drawing.hit_test(point, &local_matrix) { From 6985b12173834fb753ee1d64dfefe0a6aca6d66d Mon Sep 17 00:00:00 2001 From: CUB3D Date: Sun, 11 Dec 2022 18:50:33 +0000 Subject: [PATCH 04/14] avm2: Selecting the child of a SimpleButton should select the button, not the child This fixes ingame menu buttons in BLOCnog --- core/src/display_object/avm2_button.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index 753616ba996f..bbc3b008025c 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -814,7 +814,8 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> { .as_interactive() .and_then(|c| c.mouse_pick(context, point, require_button_mode)); if mouse_pick.is_some() { - return mouse_pick; + // Selecting a child of a button is equivalent to selecting the button itself + return Some((*self).into()); } } From 4cb14686f82bb7b0597e77ea8fef5d314d2f0849 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Sun, 11 Dec 2022 19:57:07 +0000 Subject: [PATCH 05/14] avm2: Button bounds_with_transform should include bounds of current state child --- core/src/display_object/avm2_button.rs | 16 +++++++++++++++- render/src/bounding_box.rs | 8 -------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index bbc3b008025c..14f7d833e2b2 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -640,7 +640,21 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> { fn self_bounds(&self) -> BoundingBox { // No inherent bounds; contains child DisplayObjects. - BoundingBox::empty() + BoundingBox::default() + } + + fn bounds_with_transform(&self, matrix: &Matrix) -> BoundingBox { + // Get self bounds + let mut bounds = self.self_bounds().transform(matrix); + + // Add the bounds of the child, dictated by current state + let state = self.0.read().state; + if let Some(child) = self.get_state_child(state.into()) { + let child_bounds = child.bounds_with_transform(matrix); + bounds.union(&child_bounds); + } + + bounds } fn hit_test_shape( diff --git a/render/src/bounding_box.rs b/render/src/bounding_box.rs index 18b25490195c..f07835d933a6 100644 --- a/render/src/bounding_box.rs +++ b/render/src/bounding_box.rs @@ -11,14 +11,6 @@ pub struct BoundingBox { } impl BoundingBox { - /// Create a zero-sized, valid BoundingBox - pub fn empty() -> Self { - Self { - valid: true, - .. Default::default() - } - } - /// Clamps the given point inside this bounding box. pub fn clamp(&self, (x, y): (Twips, Twips)) -> (Twips, Twips) { if self.valid { From e6a899a0ac3c508e826d6e23c1baf411848094a3 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Sun, 11 Dec 2022 20:16:49 +0000 Subject: [PATCH 06/14] avm2: hitTestPoint requires the object to be on the stage --- core/src/avm2/globals/flash/display/displayobject.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/avm2/globals/flash/display/displayobject.rs b/core/src/avm2/globals/flash/display/displayobject.rs index c130d0f631c9..e8183ba7cbf8 100644 --- a/core/src/avm2/globals/flash/display/displayobject.rs +++ b/core/src/avm2/globals/flash/display/displayobject.rs @@ -653,6 +653,10 @@ pub fn hit_test_point<'gc>( args: &[Value<'gc>], ) -> Result, Error<'gc>> { if let Some(dobj) = this.and_then(|this| this.as_display_object()) { + if !dobj.is_on_stage(&mut activation.context) { + return Ok(false.into()); + } + let x = Twips::from_pixels( args.get(0) .cloned() From 9e40039585881d2b36fec2c6134ff764b3d5fc4b Mon Sep 17 00:00:00 2001 From: CUB3D Date: Mon, 12 Dec 2022 01:01:12 +0000 Subject: [PATCH 07/14] avm2: MouseUpInside clip events should be handled by avm2 buttons --- core/src/display_object/avm2_button.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index 14f7d833e2b2..a4a28cad35d7 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -794,6 +794,7 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> { ClipEvent::Press => (ButtonState::Down, static_data.over_to_down_sound.as_ref()), ClipEvent::Release => (ButtonState::Over, static_data.down_to_over_sound.as_ref()), ClipEvent::ReleaseOutside => (ButtonState::Up, static_data.over_to_up_sound.as_ref()), + ClipEvent::MouseUpInside => (ButtonState::Up, static_data.over_to_up_sound.as_ref()), ClipEvent::RollOut { .. } => (ButtonState::Up, static_data.over_to_up_sound.as_ref()), ClipEvent::RollOver { .. } => { (ButtonState::Over, static_data.up_to_over_sound.as_ref()) From 437138d77d4caf57be88811d42ff3d6029b35953 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Mon, 12 Dec 2022 02:14:59 +0000 Subject: [PATCH 08/14] avm2: Dont transform mouse_pick point in button if hit_area has a parent --- core/src/display_object/avm2_button.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index a4a28cad35d7..4ec98c4024e5 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -836,8 +836,13 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> { let hit_area = self.0.read().hit_area; if let Some(hit_area) = hit_area { - // hit_area is not actually a child, so transform point into local space before passing it down. - let point = self.global_to_local(point); + //TODO: the if below should probably always be taken, why does the hit area + // sometimes have a parent? + let mut point = point; + if hit_area.parent().is_none() { + // hit_area is not actually a child, so transform point into local space before passing it down. + point = self.global_to_local(point); + } if hit_area.hit_test_shape(context, point, HitTestOptions::MOUSE_PICK) { return Some((*self).into()); } From ced47982887e4ab03bba8fc9644a87c84cbc8b4b Mon Sep 17 00:00:00 2001 From: CUB3D Date: Mon, 12 Dec 2022 02:51:53 +0000 Subject: [PATCH 09/14] avm2: hitTestPoint requires do to be on stage, only if shape_flag=true --- core/src/avm2/globals/flash/display/displayobject.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/avm2/globals/flash/display/displayobject.rs b/core/src/avm2/globals/flash/display/displayobject.rs index e8183ba7cbf8..50c140f96d49 100644 --- a/core/src/avm2/globals/flash/display/displayobject.rs +++ b/core/src/avm2/globals/flash/display/displayobject.rs @@ -653,10 +653,6 @@ pub fn hit_test_point<'gc>( args: &[Value<'gc>], ) -> Result, Error<'gc>> { if let Some(dobj) = this.and_then(|this| this.as_display_object()) { - if !dobj.is_on_stage(&mut activation.context) { - return Ok(false.into()); - } - let x = Twips::from_pixels( args.get(0) .cloned() @@ -676,6 +672,10 @@ pub fn hit_test_point<'gc>( .coerce_to_boolean(); if shape_flag { + if !dobj.is_on_stage(&mut activation.context) { + return Ok(false.into()); + } + return Ok(dobj .hit_test_shape( &mut activation.context, From 78cdb28e4930f21373791492ceab1255f9c79216 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Mon, 12 Dec 2022 03:32:45 +0000 Subject: [PATCH 10/14] chore: Fix clippy lint --- core/src/avm2/globals/flash/display/displayobject.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/avm2/globals/flash/display/displayobject.rs b/core/src/avm2/globals/flash/display/displayobject.rs index 50c140f96d49..ebc771dfa441 100644 --- a/core/src/avm2/globals/flash/display/displayobject.rs +++ b/core/src/avm2/globals/flash/display/displayobject.rs @@ -672,7 +672,7 @@ pub fn hit_test_point<'gc>( .coerce_to_boolean(); if shape_flag { - if !dobj.is_on_stage(&mut activation.context) { + if !dobj.is_on_stage(&activation.context) { return Ok(false.into()); } From da2fba8146ee11305bbc72827aa83b061acbd413 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Mon, 12 Dec 2022 03:33:03 +0000 Subject: [PATCH 11/14] chore: Fmt --- core/src/display_object/movie_clip.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 699b609501bd..2241fb8f619b 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -2787,8 +2787,9 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { } else if result.is_none() { if let Some(child) = child.as_interactive() { result = child.mouse_pick(context, point, require_button_mode); - } else if check_non_interactive && self.mouse_enabled() && - child.hit_test_shape(context, point, options) + } else if check_non_interactive + && self.mouse_enabled() + && child.hit_test_shape(context, point, options) { result = Some(this); } From 740ff72e0f4ebd32c3c91e95eb6ad51dc6410453 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Mon, 12 Dec 2022 23:40:14 +0000 Subject: [PATCH 12/14] avm2: Ignore mouse_pick on static text --- core/src/display_object/movie_clip.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 2241fb8f619b..e85e0a9af2d6 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -2776,6 +2776,11 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { !require_button_mode || matches!(self.object2(), Avm2Value::Object(_)); for child in self.iter_render_list().rev() { + // Clicking static text is ignored + if matches!(child, DisplayObject::Text(_)) { + continue; + } + if child.clip_depth() > 0 { if result.is_some() && child.clip_depth() >= hit_depth { if child.hit_test_shape(context, point, HitTestOptions::MOUSE_PICK) { From 2e814f38a391d37a56f224dc56d56fe77a7f346a Mon Sep 17 00:00:00 2001 From: CUB3D Date: Tue, 13 Dec 2022 00:08:08 +0000 Subject: [PATCH 13/14] avm2: Check for state parent in hit_test_shape as well as mouse_pick --- core/src/display_object/avm2_button.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index 4ec98c4024e5..2fe0fe91fb67 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -666,8 +666,14 @@ impl<'gc> TDisplayObject<'gc> for Avm2Button<'gc> { if !options.contains(HitTestOptions::SKIP_INVISIBLE) || self.visible() { let state = self.0.read().state; if let Some(child) = self.get_state_child(state.into()) { - // hit_area is not actually a child, so transform point into local space before passing it down. - let point = self.global_to_local(point); + //TODO: the if below should probably always be taken, why does the hit area + // sometimes have a parent? + let mut point = point; + if child.parent().is_none() { + // hit_area is not actually a child, so transform point into local space before passing it down. + point = self.global_to_local(point); + } + if child.hit_test_shape(context, point, options) { return true; } From 26360241a6f11b95e3a00d2c059e5ac0771fb236 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Fri, 16 Dec 2022 19:10:08 +0000 Subject: [PATCH 14/14] tests: Add tests for button hittests, update hitTestPoint with onStage tests --- tests/tests/regression_tests.rs | 1 + .../tests/swfs/avm2/button_hittest/output.txt | 2 ++ tests/tests/swfs/avm2/button_hittest/test.fla | Bin 0 -> 7107 bytes tests/tests/swfs/avm2/button_hittest/test.swf | Bin 0 -> 754 bytes .../displayobject_hittestpoint/output.txt | 4 ++++ .../avm2/displayobject_hittestpoint/test.fla | Bin 5655 -> 5730 bytes .../avm2/displayobject_hittestpoint/test.swf | Bin 1135 -> 960 bytes 7 files changed, 7 insertions(+) create mode 100644 tests/tests/swfs/avm2/button_hittest/output.txt create mode 100644 tests/tests/swfs/avm2/button_hittest/test.fla create mode 100644 tests/tests/swfs/avm2/button_hittest/test.swf diff --git a/tests/tests/regression_tests.rs b/tests/tests/regression_tests.rs index 4052318be196..ed6e572da867 100644 --- a/tests/tests/regression_tests.rs +++ b/tests/tests/regression_tests.rs @@ -210,6 +210,7 @@ swf_tests! { (as3_boolean_constr, "avm2/boolean_constr", 1), (as3_boolean_negation, "avm2/boolean_negation", 1), (as3_boolean_tostring, "avm2/boolean_tostring", 1), + (as3_button_hittest, "avm2/button_hittest", 1), (as3_bytearray_readobject_amf0, "avm2/bytearray_readobject_amf0", 1), (as3_bytearray_readobject_amf3, "avm2/bytearray_readobject_amf3", 1), (as3_bytearray_writeobject, "avm2/bytearray_writeobject", 1), diff --git a/tests/tests/swfs/avm2/button_hittest/output.txt b/tests/tests/swfs/avm2/button_hittest/output.txt new file mode 100644 index 000000000000..da9cb5363cc4 --- /dev/null +++ b/tests/tests/swfs/avm2/button_hittest/output.txt @@ -0,0 +1,2 @@ +// MP.hitTestObject(Btn1) +true diff --git a/tests/tests/swfs/avm2/button_hittest/test.fla b/tests/tests/swfs/avm2/button_hittest/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..90cf347995268f60eadb707f73846eba6c97a8f8 GIT binary patch literal 7107 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 literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/button_hittest/test.swf b/tests/tests/swfs/avm2/button_hittest/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..700bf0f97ab3f54ac910abe1956593f7cea128b5 GIT binary patch literal 754 zcmVfh`u?40Fb8p`}g;@aqi$MAL-#xfIpz5Bxzk3RST>G_wT&o!8U zeKXW9LExdT6G?N|%K7@4Wv4Gr~>5 zR`e&8KZz>@BXa8pf408d;`zGc3f>GA8j5ye#~k zihPB;q7}R-w+vPwkEdf;^{C zK{yu%&#N%6qRsY@s!@!bPvjz`81X6w?g%v`G}JCxjGhLsV&}6up3x{}ZsZXuLv0aJD!a3IN@On%m6acGTvw5hw@ebyxS=5lXhiyw21q~nizF$H zqrQY?+k!`4LR=On3@<2Go)FDs!AwyzsJd=Haro-pO@j3B;Z?S6;HntkEN5yUEBb_?*=Kj z5s?*}cqAg@8BB=!lq0ZkZ~bM#fHA#>UoYc$vBf+YyLRtLdT4NzxFH#M;_t1EPXof% z3-bG)W2Y}Uj_NqW;pog9UX0ERbBNFE5jM^Sx@vSCJb&m|ol%C#?1!4E^M}p_{{s6i z9*hio*fqODJTM&T2va5K;<2HjxcT`K&Z4<(+R1n3LMLW8;5uF|s z#gC#r<$uZ4dn_;2C&7RPvngT}L8ibrUJOXv*0@NZC~(LoNgT3Z^NYxx23(sZOCs$t zX0*aIEe>o&FS$XkD1N`?ig6G__5G@!#8Eq~m7R%M4LFMBVc3sw!1;c`Upm#?3k z!Oh?+OI(kfNQ%PdG?nL+-H?=B$24LmuowJ>#1Bz6r{~h?`TKVn;J7un-B_2>o5I+v zEKsyRD)HzO&uQfe2;*A*SD-JLpPqmF_7N6SjTH8j`f2Y$UGp<5RgM>@vZ>Dcb*#OX zI)6SH%w}-7ZT2MO&EdF$r7p|zsZ^t4-fI4*)O=AOJ598jd8mY{ELR~f6>$w_SRTkK zphoknAy*@RxKaL&peoDZ4hLzbSy!%$!%31S-EAwP*j1h4FOm zag+5J-dI0p?~wURwUoc%33`-)f~g{)K7<@7D@` z4V9wVy8O1U{QO$!DU}bbYJHNP@@!8~kcjqVNsm)0X>tm{rlI=Sj4d=@^VY~?zo&Pd zKnzJTA&kM5VrO8noCY+V|3TqmkbkWA)vmKKzD7`PH=+OW?oLOQHcz-ayi06pSTiiu zdfJ*kOk&#QBpp+)PGVRGNc2u+5)Jc}R?32n>MWYB7g$tFH7vt0wgV2CF7NUNa}DNh zDYItm3^ZfL#Y_rjj63a^)h;e)RQwPH38M8mSJw#+3Ne)7nTNn`Qu$i`V z**1+*V%6GNK#ho1?Etaa&f~6Kx=M8TJ`&@eQaH%OVY&Ht{m1_SlQ0e%v)~1e2m}+4 ztlX1w4kIb%2MhoO01yBY02BZ#000020000908@EwVsC69F#rhwQ+aJ-Z)_kkv%U^j z1qwD%Zqqph006unlOGgK0uct2ZWKWRLDb6d2nS=O9ci1 U0000C01N;W0{{SS6951J0NjM!qyPW_ delta 1494 zcmV;{1u6RCESD^hxqqinx%ch_006)q000jF002Z!O+;^Fb!}yCbS`*pZ0%XuZreB% zeJ{{|;AmbFpq8kGS{gZkJ&HR9k~V-d3s4k+7CL4}iy_gCJzrl^k{vsiZ7pb!hbTy3 zi}##!dGF;K+xc?iB>p18F$K#gjI)o+jP!*WrSp%H^!WHFK7XoWl0HZZgtGMS&Gp2e z;mGZgIHPXtW1&E85OF5DLE>T2Pa1+i+OaqNeS0E1bIr!36536MpWcmafo8;qj}2ZTj@ z<1V2%;=*X^%O0A#J;)!K2Rd{!dXoe^ZUL(T9U4%z5QKtMLsY3Ps;mB5)H^7uJc-)U zv##5;EPvH!!C(VsUBn<}nPR^2VgT}{#`6T`1?(G>kZaR)frTB$f;KnJ z_8T^$*W92~%s=0A#UxBv_5BXvh&>w*N*O@12@Y8a9}(UXnR34mxv=X@-bKKM7hd)S zHd6k>D;8ennPn*EQI##8vc~Nh@=_DmqKDOitOIJ*zXoy*@~5=Q-w9N0IYs9n z8KI_%6~Nk}M(!!wqBj+-0JaG1u{<6JwF_$ly?tD}pf-@)#~m3Q_bq3eQ@93_^=F*Z z$W}c)It`qFwd`jj$wPBb4x!2X?4|clO@DSLY11E*UeLIR+xzF;8X^k(rnmDJ7;n^i)b@tX;k zXC}{myT0Vm7JhegAm20Z=K5s{<^ENaiVCf_TB(nJp;}RPYejhtl_FcJ_%^Tn`hQxn zrP>Qtz4N{;9lhJiN%A|jiilw49g?_)4hd#o3a?Jd_uJQhjE# zl3CWa8rm@{u$oy>^lr@1RH~Vwf`2+P8;6)-$7pC(8Pt(!Sg>O>G!<1do2J!~*{}{U z^9%k?%;-Qg49n=sT#-S}EL&YOxK*~h%xc#-E7d;hmeH-AEo4*?tC|73xojb=k{B9W z1E>`-ln)T2ZXTOfJ|wYaJ)%?H6fbLyRoT z)btah+Lrd##eD5u|I7OFC$kX-s0aj^iG!Duy$&NO?@hZDMb1ATj_608@EwVsC69F|!E|R|N{EP`UT+1ONcQ9+PSmO#;RRlPv}rlhPC@ z0{I1#UDb6d2nS=O9ci10000C01N;W0{{Rc6951J0I5`~J^%m! diff --git a/tests/tests/swfs/avm2/displayobject_hittestpoint/test.swf b/tests/tests/swfs/avm2/displayobject_hittestpoint/test.swf index e404bc03ad7854adbebf8099773b0842d6797442..1d17a25effc0a27e5a6841caec6740c3b18799c2 100644 GIT binary patch literal 960 zcmV;x13&yjS5qrp2><|ioUK+(Y#T)sezSk$zx+CO($J>c;QZEEuPvoWaG=N`w4lmJ zDTo76ytQZRMfTd-U7|$2^i5y4)Am_#lEoXpK97(mA~ zD0Jo^7+VR4*v^68)-pFV!@Oy9NZT;U1O@Dt(lqQ|TRTqP=pGuR+BSN*ko|U)4cI>J z-0HT=$>4ra4v>nZTUv*d{aZzJEUiISN+qXd*hVBlkxZ*xN9(m=A$kkEo$`!^eZ*Pyg;4M$OqP{xUSH|N9Um81{G5E1) zhVf}7pYeLiqxnO&RvFiWACNk}1AjrULz? z(QcECk6yEaM`;PR)9p=a&E_s^3wsUA=s8mD))%DVWc^C-_RhIl3TzVDBq2Z; zv2Ke5L@$aWluYri`T>PRluCc%s{4uJL@j~#6K)BW(AsX2_kInSuHnF_{5=J|;83F9f&{k7g-^V|iYTk_Q@cgdCzNnszP4tjj~+!khnn zk!~#wbbEQWy*XEPufu+(0In_-kgMZbMxaK4qeZsnss!p2YJF0zPpS23wLYWPXVp4K zug~CuKU%C*-pww8e>ey~?n>zof&6mm?;n4Ec`5r? zzIvLR_6`;Z?n$iffi9#c4=GFME9^h8@Z`lW2!i%O4S8nZsp0(PJHp+*<$&6tN^Lyz z=idLT@2`6VEjah{@$wJPuRX4F_rHawPyXC`aRd*4g4O1O=ie_sefWsG*Me)`Y|a+G i0{yNZlMu$lhcV4D*CI76e)`YX5W22-)_(!Q&|eR8S?8_* literal 1135 zcmV-#1d#hfS5qr03IG6joQ;;xZyQAv$7lA3$G?&|zg*|HldkhSyK9%EA{<)ekT!@a zphT!bj$+52mA7(i%ex5)z4TPkUXVCZaVbbtNT}y>%Yh3=^AD7s+XD_9ka`Jk_J_Mh zPU4k4`}{udz3-dZoso}_xQkHFQ-oq1TI=;AgwovE+1W(oU`R?z^q#bL{MEYbck z-q!bNNiS2S>D6kveVXhjDz$J)l-KKby@_N(P+!Zqo6je0JOREhU<@T%INr#VqQET-42NsP<_^FPpQftS-i_LCcj4I`_et zt0a4sR-JVSdy{9{6#mvpXP6rEaOk;&!dP7|(MrBmwp zb3L~oyLqMKb~=b}>84#g?1D>{CwXyvn@1~ms$e&yb}nEi2!>gycIOI(b@rZa7?EU52+`C8fX4pP8=pikeM$bp=wgx9i&de8St!vFbOzhC!jj~DMG%)o;YI~wB zJY6Z9AV6!rt!hm->5YxmOuAB_nc9J-m1rhksnHDU%*YsDYDOk^xSz^6$5q9uunTi# z0aZ5F42g7;}Ce@gmQNzy^^GK8!HIEEo$IKH$YT5ajFXEpUlA7}D$N zj(;(7+S|aJe%#=8{B;E@cxFAov)=;1erAXOq}06YC*U7ohTln;c0droATvUCg6j{1 zAjbs%<}JnO=@na%XY!6zi?q*`Caux|S33AV>98x^)hgWs{unbN;MaJsMjxOdX7pRg zqcR9&m>JP#l3OnZXoML^J@I>! zNx&wUk!Y55)n)+2nKApWq|4@kO)_KQT}hWM0h?lm%$VTql0BKL%t%_uvmV!gNX&Sz zndH`60hD0IbvMZ+@7FhjsIdxMBLqu$t{sv)yX8N6kjmY_FQ-;Byy^*;f&ts*M<=+~^;+Uw_p0a6mWF37W7XGE?{e z5MP0zu|GY7)yMI-EmyFCpsX%WEi=l_0#T