From 192c6e24c310275dde93eeb32c7c0ca7e13c74b0 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 13 Jan 2016 11:14:46 -0800 Subject: [PATCH] Handle degenerate transforms better No you can't hit things inside degenerate transforms. Tranforming from global coordaintes to degenerate local coordinates gives you Point.origin. Also, upgrade vector_math to get a better invert constructor. Fixes #1161 Fixes #1224 --- packages/flutter/lib/src/rendering/box.dart | 8 ++++++-- packages/flutter/lib/src/rendering/proxy_box.dart | 11 ++++++++--- packages/flutter/pubspec.yaml | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 9de60517f6f..fff8822acc9 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -636,6 +636,9 @@ abstract class RenderBox extends RenderObject { /// Convert the given point from the global coodinate system to the local /// coordinate system for this box. + /// + /// If the transform from global coordinates to local coordinates is + /// degenerate, this function returns Point.origin. Point globalToLocal(Point point) { assert(attached); Matrix4 transform = new Matrix4.identity(); @@ -645,8 +648,9 @@ abstract class RenderBox extends RenderObject { rendererParent.applyPaintTransform(renderer, transform); renderer = rendererParent; } - /* double det = */ transform.invert(); - // TODO(abarth): Check the determinant for degeneracy. + double det = transform.invert(); + if (det == 0.0) + return Point.origin; return _transformPoint(transform, point); } diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 07b1855a12e..ac1e8b9bf37 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -991,9 +991,14 @@ class RenderTransform extends RenderProxyBox { bool hitTest(HitTestResult result, { Point position }) { if (transformHitTests) { - Matrix4 inverse = new Matrix4.zero(); - // TODO(abarth): Check the determinant for degeneracy. - inverse.copyInverse(_effectiveTransform); + Matrix4 inverse; + try { + inverse = new Matrix4.inverted(_effectiveTransform); + } catch (e) { + // We cannot invert the effective transform. That means the child + // doesn't appear on screen and cannot be hit. + return false; + } Vector3 position3 = new Vector3(position.x, position.y, 0.0); Vector3 transformed3 = inverse.transform3(position3); position = new Point(transformed3.x, transformed3.y); diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index aca4524a81c..c33631bda35 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: material_design_icons: '>=0.0.3 <0.1.0' sky_engine: 0.0.81 sky_services: 0.0.81 - vector_math: '>=1.4.3 <2.0.0' + vector_math: '>=1.4.5 <2.0.0' quiver: '>=0.21.4 <0.22.0' # See the comment in flutter_tools' pubspec.yaml. We have to pin it