From 33dbef12bc919ad24353559c0e98be9bde4f0f3b Mon Sep 17 00:00:00 2001 From: Pavel fljot Date: Fri, 31 May 2013 18:06:08 +0300 Subject: [PATCH 1/5] Update gitignore for IntelliJ IDEA --- .gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9955068..5d2c6e0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,10 @@ wiki/ Thumbs.db .DS_Store -build.properties \ No newline at end of file +build.properties + +# Intellij project files +*.iml +*.ipr +*.iws +.idea/ \ No newline at end of file From 46919cf710f0e04abb3a2557c17c603c5dd91905 Mon Sep 17 00:00:00 2001 From: Pavel fljot Date: Thu, 13 Jun 2013 09:33:49 +0400 Subject: [PATCH 2/5] Minor syntax fix --- src/org/gestouch/gestures/Gesture.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/gestouch/gestures/Gesture.as b/src/org/gestouch/gestures/Gesture.as index a0e69a5..9a614ac 100644 --- a/src/org/gestouch/gestures/Gesture.as +++ b/src/org/gestouch/gestures/Gesture.as @@ -424,7 +424,7 @@ package org.gestouch.gestures */ protected function ignoreTouch(touch:Touch):void { - if (_touchesMap.hasOwnProperty(touch.id)) + if (touch.id in _touchesMap) { delete _touchesMap[touch.id]; _touchesCount--; From 8d5e3387151b495c3d9a9d439ffda913d4b9192c Mon Sep 17 00:00:00 2001 From: Pavel fljot Date: Thu, 13 Jun 2013 11:17:52 +0400 Subject: [PATCH 3/5] Refactor hit-test and default (native) related bootstrapping --- src/org/gestouch/core/Gestouch.as | 26 +++-- src/org/gestouch/core/GesturesManager.as | 13 ++- src/org/gestouch/core/ITouchHitTester.as | 3 +- src/org/gestouch/core/TouchesManager.as | 7 +- .../extensions/native/DisplayObjectUtils.as | 94 +++++++++++++++++++ .../extensions/native/NativeTouchHitTester.as | 33 +++++-- .../starling/StarlingTouchHitTester.as | 25 +++-- 7 files changed, 159 insertions(+), 42 deletions(-) create mode 100644 src/org/gestouch/extensions/native/DisplayObjectUtils.as diff --git a/src/org/gestouch/core/Gestouch.as b/src/org/gestouch/core/Gestouch.as index 718f811..b3c23df 100644 --- a/src/org/gestouch/core/Gestouch.as +++ b/src/org/gestouch/core/Gestouch.as @@ -1,12 +1,11 @@ package org.gestouch.core { - import org.gestouch.extensions.native.NativeDisplayListAdapter; - import org.gestouch.extensions.native.NativeTouchHitTester; - import flash.display.DisplayObject; import flash.utils.Dictionary; import flash.utils.getQualifiedClassName; + import org.gestouch.extensions.native.NativeDisplayListAdapter; + /** * @author Pavel fljot @@ -15,10 +14,6 @@ package org.gestouch.core { private static const _displayListAdaptersMap:Dictionary = new Dictionary(); - { - initClass(); - } - /** @private */ private static var _inputAdapter:IInputAdapter; @@ -91,7 +86,15 @@ package org.gestouch.core gestouch_internal static function createGestureTargetAdapter(target:Object):IDisplayListAdapter { - const adapter:IDisplayListAdapter = Gestouch.gestouch_internal::getDisplayListAdapter(target); + var adapter:IDisplayListAdapter = Gestouch.gestouch_internal::getDisplayListAdapter(target); + + // Lazy add display list adapter for flash.display::DisplayObject + if (!adapter && target is flash.display.DisplayObject) + { + adapter = new NativeDisplayListAdapter(); + Gestouch.addDisplayListAdapter(DisplayObject, adapter); + } + if (adapter) { return new (adapter.reflect())(target); @@ -114,12 +117,5 @@ package org.gestouch.core return null; } - - - private static function initClass():void - { - addTouchHitTester(new NativeTouchHitTester()); - addDisplayListAdapter(DisplayObject, new NativeDisplayListAdapter()); - } } } diff --git a/src/org/gestouch/core/GesturesManager.as b/src/org/gestouch/core/GesturesManager.as index b3b5e21..67c8251 100644 --- a/src/org/gestouch/core/GesturesManager.as +++ b/src/org/gestouch/core/GesturesManager.as @@ -1,17 +1,19 @@ package org.gestouch.core { - import flash.errors.IllegalOperationError; - import org.gestouch.gestures.Gesture; - import org.gestouch.input.NativeInputAdapter; - import flash.display.DisplayObject; import flash.display.Shape; import flash.display.Stage; + import flash.errors.IllegalOperationError; import flash.events.Event; import flash.events.IEventDispatcher; import flash.utils.Dictionary; import flash.utils.getQualifiedClassName; + import org.gestouch.extensions.native.NativeTouchHitTester; + import org.gestouch.gestures.Gesture; + import org.gestouch.input.NativeInputAdapter; + + /** * @author Pavel fljot */ @@ -48,6 +50,7 @@ package org.gestouch.core _stage = stage; Gestouch.inputAdapter ||= new NativeInputAdapter(stage); + Gestouch.addTouchHitTester(new NativeTouchHitTester(stage)); } @@ -104,7 +107,7 @@ package org.gestouch.core } else { - targetAsDO.addEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler); + targetAsDO.addEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler, false,0, true); } } } diff --git a/src/org/gestouch/core/ITouchHitTester.as b/src/org/gestouch/core/ITouchHitTester.as index b56cbe4..bd9d13f 100644 --- a/src/org/gestouch/core/ITouchHitTester.as +++ b/src/org/gestouch/core/ITouchHitTester.as @@ -1,6 +1,5 @@ package org.gestouch.core { - import flash.display.InteractiveObject; import flash.geom.Point; @@ -9,6 +8,6 @@ package org.gestouch.core */ public interface ITouchHitTester { - function hitTest(point:Point, nativeTarget:InteractiveObject):Object; + function hitTest(point:Point, possibleTarget:Object = null):Object; } } diff --git a/src/org/gestouch/core/TouchesManager.as b/src/org/gestouch/core/TouchesManager.as index 4108b7c..28ed99f 100644 --- a/src/org/gestouch/core/TouchesManager.as +++ b/src/org/gestouch/core/TouchesManager.as @@ -1,6 +1,5 @@ package org.gestouch.core { - import flash.display.InteractiveObject; import flash.display.Stage; import flash.geom.Point; import flash.utils.Dictionary; @@ -90,8 +89,8 @@ package org.gestouch.core } - gestouch_internal function onTouchBegin(touchID:uint, x:Number, y:Number, nativeTarget:InteractiveObject = null):Boolean - { + gestouch_internal function onTouchBegin(touchID:uint, x:Number, y:Number, possibleTarget:Object = null):Boolean + { if (touchID in _touchesMap) return false;// touch with specified ID is already registered and being tracked @@ -119,7 +118,7 @@ package org.gestouch.core var altTarget:Object; for each (var hitTester:ITouchHitTester in _hitTesters) { - target = hitTester.hitTest(location, nativeTarget); + target = hitTester.hitTest(location, possibleTarget); if (target) { if ((target is Stage)) diff --git a/src/org/gestouch/extensions/native/DisplayObjectUtils.as b/src/org/gestouch/extensions/native/DisplayObjectUtils.as new file mode 100644 index 0000000..0d85c57 --- /dev/null +++ b/src/org/gestouch/extensions/native/DisplayObjectUtils.as @@ -0,0 +1,94 @@ +package org.gestouch.extensions.native +{ +import flash.display.DisplayObject; +import flash.display.DisplayObjectContainer; +import flash.display.InteractiveObject; +import flash.display.Stage; +import flash.geom.Point; + + +/** + * @author Valentin Simonov + */ +public class DisplayObjectUtils +{ + /** + * Searches display list for top most instance of InteractiveObject. + * Checks if mouseEnabled is true and (optionally) parent's mouseChildren. + * @param stage Stage object. + * @param point Global point to test. + * @param mouseChildren If true also checks parents chain for mouseChildren == true. + * @param startFrom An index to start looking from in objects under point array. + * @return Top most InteractiveObject or Stage. + */ + public static function getTopTarget(stage:Stage, point:Point, mouseChildren:Boolean = true, startFrom:uint = 0):InteractiveObject + { + var targets:Array = stage.getObjectsUnderPoint(point); + if (!targets.length) return stage; + + var startIndex:int = targets.length - 1 - startFrom; + if (startIndex < 0) return stage; + + outer: + for (var i:int = startIndex; i >= 0; i--) + { + var target:DisplayObject = targets[i] as DisplayObject; + while (target != stage) + { + if (target is InteractiveObject) + { + if ((target as InteractiveObject).mouseEnabled) + { + if (mouseChildren) + { + var lastMouseActive:InteractiveObject = target as InteractiveObject; + var parent:DisplayObjectContainer = target.parent; + while (parent) + { + if (!lastMouseActive && parent.mouseEnabled) + { + lastMouseActive = parent; + } + else if (!parent.mouseChildren) + { + if (parent.mouseEnabled) + { + lastMouseActive = parent; + } + else + { + lastMouseActive = null; + } + } + parent = parent.parent; + } + if (lastMouseActive) + { + return lastMouseActive; + } + else + { + return stage; + } + } + else + { + return target as InteractiveObject; + } + } + else + { + continue outer; + } + } + else + { + target = target.parent; + } + } + } + + return stage; + } +} +} diff --git a/src/org/gestouch/extensions/native/NativeTouchHitTester.as b/src/org/gestouch/extensions/native/NativeTouchHitTester.as index f7c9273..77c042e 100644 --- a/src/org/gestouch/extensions/native/NativeTouchHitTester.as +++ b/src/org/gestouch/extensions/native/NativeTouchHitTester.as @@ -1,19 +1,40 @@ package org.gestouch.extensions.native { - import org.gestouch.core.ITouchHitTester; - - import flash.display.InteractiveObject; + import flash.display.DisplayObject; + import flash.display.Stage; import flash.geom.Point; + import org.gestouch.core.ITouchHitTester; + /** * @author Pavel fljot */ - final public class NativeTouchHitTester implements ITouchHitTester + public class NativeTouchHitTester implements ITouchHitTester { - public function hitTest(point:Point, nativeTarget:InteractiveObject):Object + private var stage:Stage; + + + public function NativeTouchHitTester(stage:Stage) { - return nativeTarget; + if (!stage) + { + throw ArgumentError("Missing stage argument."); + } + + this.stage = stage; + } + + + public function hitTest(point:Point, possibleTarget:Object = null):Object + { + if (possibleTarget && possibleTarget is DisplayObject) + { + return possibleTarget; + } + + // Fallback target detection through getObjectsUnderPoint + return DisplayObjectUtils.getTopTarget(stage, point); } } } diff --git a/src/org/gestouch/extensions/starling/StarlingTouchHitTester.as b/src/org/gestouch/extensions/starling/StarlingTouchHitTester.as index 9abe7fe..a961be8 100644 --- a/src/org/gestouch/extensions/starling/StarlingTouchHitTester.as +++ b/src/org/gestouch/extensions/starling/StarlingTouchHitTester.as @@ -1,34 +1,39 @@ package org.gestouch.extensions.starling { - import starling.core.Starling; + import flash.geom.Point; import org.gestouch.core.ITouchHitTester; - import flash.display.InteractiveObject; - import flash.geom.Point; + import starling.core.Starling; + import starling.display.DisplayObject; /** * @author Pavel fljot */ - final public class StarlingTouchHitTester implements ITouchHitTester + public class StarlingTouchHitTester implements ITouchHitTester { private var starling:Starling; - - + + public function StarlingTouchHitTester(starling:Starling) { if (!starling) { throw ArgumentError("Missing starling argument."); } - + this.starling = starling; } - - - public function hitTest(point:Point, nativeTarget:InteractiveObject):Object + + + public function hitTest(point:Point, possibleTarget:Object = null):Object { + if (possibleTarget && possibleTarget is DisplayObject) + { + return possibleTarget; + } + point = StarlingUtils.adjustGlobalPoint(starling, point); return starling.stage.hitTest(point, true); } From 75672ee10e71cde3196f609fb64204691d467d91 Mon Sep 17 00:00:00 2001 From: Pavel fljot Date: Mon, 17 Jun 2013 18:00:02 +0300 Subject: [PATCH 4/5] Maximum tap distance for multi-tap TapGesture Thanks to Ilya Shabanov for a issue report --- src/org/gestouch/gestures/TapGesture.as | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/org/gestouch/gestures/TapGesture.as b/src/org/gestouch/gestures/TapGesture.as index cac99c5..162d707 100644 --- a/src/org/gestouch/gestures/TapGesture.as +++ b/src/org/gestouch/gestures/TapGesture.as @@ -1,5 +1,6 @@ package org.gestouch.gestures { + import flash.geom.Point; import org.gestouch.core.gestouch_internal; import org.gestouch.core.GestureState; import org.gestouch.core.Touch; @@ -21,10 +22,12 @@ package org.gestouch.gestures public var slop:Number = Gesture.DEFAULT_SLOP << 2;//iOS has 45px for 132 dpi screen public var maxTapDelay:uint = 400; public var maxTapDuration:uint = 1500; + public var maxTapDistance:Number = Gesture.DEFAULT_SLOP << 2; protected var _timer:Timer; protected var _numTouchesRequiredReached:Boolean; protected var _tapCounter:uint = 0; + protected var _touchBeginLocations:Vector. = new Vector.(); public function TapGesture(target:Object = null) @@ -52,6 +55,7 @@ package org.gestouch.gestures _numTouchesRequiredReached = false; _tapCounter = 0; _timer.reset(); + _touchBeginLocations.length = 0; super.reset(); } @@ -100,6 +104,35 @@ package org.gestouch.gestures _timer.start(); } + if (numTapsRequired > 1) + { + if (_tapCounter == 0) + { + // Save touch begin locations to check + _touchBeginLocations.push(touch.location); + } + else + { + // Quite a dirty check, but should work in most cases + var found:Boolean = false; + for each (var loc:Point in _touchBeginLocations) + { + // current touch should be near any previous one + if (Point.distance(touch.location, loc) <= maxTapDistance) + { + found = true; + break; + } + } + + if (!found) + { + setState(GestureState.FAILED); + return; + } + } + } + if (touchesCount == numTouchesRequired) { _numTouchesRequiredReached = true; From 9a1f7e073dff3a673e84fe4251434c23b1de329a Mon Sep 17 00:00:00 2001 From: Pavel fljot Date: Wed, 26 Jun 2013 13:50:22 +0300 Subject: [PATCH 5/5] Bump version to 0.4.6 --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index f41c21e..922aa0b 100644 --- a/version.properties +++ b/version.properties @@ -1 +1 @@ -project.version = 0.4.5 \ No newline at end of file +project.version = 0.4.6 \ No newline at end of file