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); }