Merge branch 'refs/heads/develop'

This commit is contained in:
Pavel fljot 2013-06-26 13:50:51 +03:00
commit 89e3acf473
11 changed files with 201 additions and 45 deletions

8
.gitignore vendored
View file

@ -8,4 +8,10 @@ wiki/
Thumbs.db Thumbs.db
.DS_Store .DS_Store
build.properties build.properties
# Intellij project files
*.iml
*.ipr
*.iws
.idea/

View file

@ -1,12 +1,11 @@
package org.gestouch.core package org.gestouch.core
{ {
import org.gestouch.extensions.native.NativeDisplayListAdapter;
import org.gestouch.extensions.native.NativeTouchHitTester;
import flash.display.DisplayObject; import flash.display.DisplayObject;
import flash.utils.Dictionary; import flash.utils.Dictionary;
import flash.utils.getQualifiedClassName; import flash.utils.getQualifiedClassName;
import org.gestouch.extensions.native.NativeDisplayListAdapter;
/** /**
* @author Pavel fljot * @author Pavel fljot
@ -15,10 +14,6 @@ package org.gestouch.core
{ {
private static const _displayListAdaptersMap:Dictionary = new Dictionary(); private static const _displayListAdaptersMap:Dictionary = new Dictionary();
{
initClass();
}
/** @private */ /** @private */
private static var _inputAdapter:IInputAdapter; private static var _inputAdapter:IInputAdapter;
@ -91,7 +86,15 @@ package org.gestouch.core
gestouch_internal static function createGestureTargetAdapter(target:Object):IDisplayListAdapter 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) if (adapter)
{ {
return new (adapter.reflect())(target); return new (adapter.reflect())(target);
@ -114,12 +117,5 @@ package org.gestouch.core
return null; return null;
} }
private static function initClass():void
{
addTouchHitTester(new NativeTouchHitTester());
addDisplayListAdapter(DisplayObject, new NativeDisplayListAdapter());
}
} }
} }

View file

@ -1,17 +1,19 @@
package org.gestouch.core 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.DisplayObject;
import flash.display.Shape; import flash.display.Shape;
import flash.display.Stage; import flash.display.Stage;
import flash.errors.IllegalOperationError;
import flash.events.Event; import flash.events.Event;
import flash.events.IEventDispatcher; import flash.events.IEventDispatcher;
import flash.utils.Dictionary; import flash.utils.Dictionary;
import flash.utils.getQualifiedClassName; import flash.utils.getQualifiedClassName;
import org.gestouch.extensions.native.NativeTouchHitTester;
import org.gestouch.gestures.Gesture;
import org.gestouch.input.NativeInputAdapter;
/** /**
* @author Pavel fljot * @author Pavel fljot
*/ */
@ -48,6 +50,7 @@ package org.gestouch.core
_stage = stage; _stage = stage;
Gestouch.inputAdapter ||= new NativeInputAdapter(stage); Gestouch.inputAdapter ||= new NativeInputAdapter(stage);
Gestouch.addTouchHitTester(new NativeTouchHitTester(stage));
} }
@ -104,7 +107,7 @@ package org.gestouch.core
} }
else else
{ {
targetAsDO.addEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler); targetAsDO.addEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler, false,0, true);
} }
} }
} }

View file

@ -1,6 +1,5 @@
package org.gestouch.core package org.gestouch.core
{ {
import flash.display.InteractiveObject;
import flash.geom.Point; import flash.geom.Point;
@ -9,6 +8,6 @@ package org.gestouch.core
*/ */
public interface ITouchHitTester public interface ITouchHitTester
{ {
function hitTest(point:Point, nativeTarget:InteractiveObject):Object; function hitTest(point:Point, possibleTarget:Object = null):Object;
} }
} }

View file

@ -1,6 +1,5 @@
package org.gestouch.core package org.gestouch.core
{ {
import flash.display.InteractiveObject;
import flash.display.Stage; import flash.display.Stage;
import flash.geom.Point; import flash.geom.Point;
import flash.utils.Dictionary; 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) if (touchID in _touchesMap)
return false;// touch with specified ID is already registered and being tracked return false;// touch with specified ID is already registered and being tracked
@ -119,7 +118,7 @@ package org.gestouch.core
var altTarget:Object; var altTarget:Object;
for each (var hitTester:ITouchHitTester in _hitTesters) for each (var hitTester:ITouchHitTester in _hitTesters)
{ {
target = hitTester.hitTest(location, nativeTarget); target = hitTester.hitTest(location, possibleTarget);
if (target) if (target)
{ {
if ((target is Stage)) if ((target is Stage))

View file

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

View file

@ -1,19 +1,40 @@
package org.gestouch.extensions.native package org.gestouch.extensions.native
{ {
import org.gestouch.core.ITouchHitTester; import flash.display.DisplayObject;
import flash.display.Stage;
import flash.display.InteractiveObject;
import flash.geom.Point; import flash.geom.Point;
import org.gestouch.core.ITouchHitTester;
/** /**
* @author Pavel fljot * @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);
} }
} }
} }

View file

@ -1,34 +1,39 @@
package org.gestouch.extensions.starling package org.gestouch.extensions.starling
{ {
import starling.core.Starling; import flash.geom.Point;
import org.gestouch.core.ITouchHitTester; import org.gestouch.core.ITouchHitTester;
import flash.display.InteractiveObject; import starling.core.Starling;
import flash.geom.Point; import starling.display.DisplayObject;
/** /**
* @author Pavel fljot * @author Pavel fljot
*/ */
final public class StarlingTouchHitTester implements ITouchHitTester public class StarlingTouchHitTester implements ITouchHitTester
{ {
private var starling:Starling; private var starling:Starling;
public function StarlingTouchHitTester(starling:Starling) public function StarlingTouchHitTester(starling:Starling)
{ {
if (!starling) if (!starling)
{ {
throw ArgumentError("Missing starling argument."); throw ArgumentError("Missing starling argument.");
} }
this.starling = starling; 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); point = StarlingUtils.adjustGlobalPoint(starling, point);
return starling.stage.hitTest(point, true); return starling.stage.hitTest(point, true);
} }

View file

@ -424,7 +424,7 @@ package org.gestouch.gestures
*/ */
protected function ignoreTouch(touch:Touch):void protected function ignoreTouch(touch:Touch):void
{ {
if (_touchesMap.hasOwnProperty(touch.id)) if (touch.id in _touchesMap)
{ {
delete _touchesMap[touch.id]; delete _touchesMap[touch.id];
_touchesCount--; _touchesCount--;

View file

@ -1,5 +1,6 @@
package org.gestouch.gestures package org.gestouch.gestures
{ {
import flash.geom.Point;
import org.gestouch.core.gestouch_internal; import org.gestouch.core.gestouch_internal;
import org.gestouch.core.GestureState; import org.gestouch.core.GestureState;
import org.gestouch.core.Touch; 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 slop:Number = Gesture.DEFAULT_SLOP << 2;//iOS has 45px for 132 dpi screen
public var maxTapDelay:uint = 400; public var maxTapDelay:uint = 400;
public var maxTapDuration:uint = 1500; public var maxTapDuration:uint = 1500;
public var maxTapDistance:Number = Gesture.DEFAULT_SLOP << 2;
protected var _timer:Timer; protected var _timer:Timer;
protected var _numTouchesRequiredReached:Boolean; protected var _numTouchesRequiredReached:Boolean;
protected var _tapCounter:uint = 0; protected var _tapCounter:uint = 0;
protected var _touchBeginLocations:Vector.<Point> = new Vector.<Point>();
public function TapGesture(target:Object = null) public function TapGesture(target:Object = null)
@ -52,6 +55,7 @@ package org.gestouch.gestures
_numTouchesRequiredReached = false; _numTouchesRequiredReached = false;
_tapCounter = 0; _tapCounter = 0;
_timer.reset(); _timer.reset();
_touchBeginLocations.length = 0;
super.reset(); super.reset();
} }
@ -100,6 +104,35 @@ package org.gestouch.gestures
_timer.start(); _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) if (touchesCount == numTouchesRequired)
{ {
_numTouchesRequiredReached = true; _numTouchesRequiredReached = true;

View file

@ -1 +1 @@
project.version = 0.4.5 project.version = 0.4.6