mirror of
https://github.com/scratchfoundation/Gestouch.git
synced 2024-11-27 01:35:40 -05:00
Experimental requireGestureToFail API implemented
This commit is contained in:
parent
4e02d4ae63
commit
2efa95b85c
5 changed files with 163 additions and 13 deletions
|
@ -14,6 +14,7 @@ package org.gestouch.gestures
|
|||
import flash.events.EventDispatcher;
|
||||
import flash.geom.Point;
|
||||
import flash.system.Capabilities;
|
||||
import flash.utils.Dictionary;
|
||||
|
||||
|
||||
[Event(name="stateChange", type="org.gestouch.events.GestureStateEvent")]
|
||||
|
@ -46,6 +47,12 @@ package org.gestouch.gestures
|
|||
protected var _touchesMap:Object = {};
|
||||
protected var _centralPoint:Point = new Point();
|
||||
protected var _localLocation:Point;
|
||||
/**
|
||||
* List of gesture we require to fail.
|
||||
* @see requireGestureToFail()
|
||||
*/
|
||||
protected var _gesturesToFail:Dictionary = new Dictionary(true);
|
||||
protected var _pendingRecognizedState:uint;
|
||||
|
||||
|
||||
public function Gesture(target:InteractiveObject = null)
|
||||
|
@ -177,12 +184,19 @@ package org.gestouch.gestures
|
|||
*/
|
||||
public function reset():void
|
||||
{
|
||||
//TODO
|
||||
//FIXME: proper state change?
|
||||
_location.x = 0;
|
||||
_location.y = 0;
|
||||
_touchesMap = {};
|
||||
_touchesCount = 0;
|
||||
|
||||
for (var key:* in _gesturesToFail)
|
||||
{
|
||||
var gestureToFail:Gesture = key as Gesture;
|
||||
gestureToFail.removeEventListener(GestureStateEvent.STATE_CHANGE, gestureToFail_stateChangeHandler);
|
||||
}
|
||||
_pendingRecognizedState = 0;
|
||||
|
||||
setState(GestureState.IDLE);
|
||||
}
|
||||
|
||||
|
@ -197,6 +211,7 @@ package org.gestouch.gestures
|
|||
//TODO
|
||||
reset();
|
||||
target = null;
|
||||
_gesturesToFail = null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -212,9 +227,13 @@ package org.gestouch.gestures
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* <b>NB! Current implementation is highly experimental!</b> See examples for more info.
|
||||
*/
|
||||
public function requireGestureToFail(gesture:Gesture):void
|
||||
{
|
||||
//TODO
|
||||
_gesturesToFail[gesture] = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -319,6 +338,39 @@ package org.gestouch.gestures
|
|||
|
||||
if (newState == GestureState.BEGAN || newState == GestureState.RECOGNIZED)
|
||||
{
|
||||
var gestureToFail:Gesture;
|
||||
// first we check if other required-to-fail gestures recognized
|
||||
// TODO: is this really necessary? using "requireGestureToFail" API assume that
|
||||
// required-to-fail gesture always recognizes AFTER this one.
|
||||
for (var key:* in _gesturesToFail)
|
||||
{
|
||||
gestureToFail = key as Gesture;
|
||||
if (gestureToFail.state != GestureState.IDLE && gestureToFail.state != GestureState.POSSIBLE
|
||||
&& gestureToFail.state != GestureState.FAILED)
|
||||
{
|
||||
// Looks like other gesture won't fail,
|
||||
// which means the required condition will not happen, so we must fail
|
||||
setState(GestureState.FAILED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// then we check of other required-to-fail gestures are actually tracked (not IDLE)
|
||||
// and not still not recognized (e.g. POSSIBLE state)
|
||||
for (key in _gesturesToFail)
|
||||
{
|
||||
gestureToFail = key as Gesture;
|
||||
if (gestureToFail.state == GestureState.POSSIBLE)
|
||||
{
|
||||
// Other gesture might fail soon, so we postpone state change
|
||||
_pendingRecognizedState = newState;
|
||||
return false;
|
||||
}
|
||||
// else if gesture is in IDLE state it means it doesn't track anything,
|
||||
// so we simply ignore it as it doesn't seem like conflict from this perspective
|
||||
// (perspective of using "requireGestureToFail" API)
|
||||
}
|
||||
|
||||
|
||||
if (delegate && !delegate.gestureShouldBegin(this))
|
||||
{
|
||||
setState(GestureState.FAILED);
|
||||
|
@ -381,6 +433,17 @@ package org.gestouch.gestures
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executed once requiredToFail gestures have been failed and
|
||||
* pending (delayed) recognized state has been entered.
|
||||
* You must dispatch gesture event here.
|
||||
*/
|
||||
protected function onDelayedRecognize():void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
@ -398,6 +461,12 @@ package org.gestouch.gestures
|
|||
|
||||
if (_touchesCount == 1 && state == GestureState.IDLE)
|
||||
{
|
||||
for (var key:* in _gesturesToFail)
|
||||
{
|
||||
var gestureToFail:Gesture = key as Gesture;
|
||||
gestureToFail.addEventListener(GestureStateEvent.STATE_CHANGE, gestureToFail_stateChangeHandler, false, 0, true);
|
||||
}
|
||||
|
||||
setState(GestureState.POSSIBLE);
|
||||
}
|
||||
}
|
||||
|
@ -417,5 +486,37 @@ package org.gestouch.gestures
|
|||
|
||||
onTouchEnd(touch);
|
||||
}
|
||||
|
||||
|
||||
protected function gestureToFail_stateChangeHandler(event:GestureStateEvent):void
|
||||
{
|
||||
if (state != GestureState.POSSIBLE)
|
||||
return;//just in case..FIXME?
|
||||
|
||||
if (!_pendingRecognizedState)
|
||||
return;
|
||||
|
||||
if (event.newState == GestureState.FAILED)
|
||||
{
|
||||
for (var key:* in _gesturesToFail)
|
||||
{
|
||||
var gestureToFail:Gesture = key as Gesture;
|
||||
if (gestureToFail.state == GestureState.POSSIBLE)
|
||||
{
|
||||
// we're still waiting for some gesture to fail
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (setState(_pendingRecognizedState))
|
||||
{
|
||||
onDelayedRecognize();
|
||||
}
|
||||
}
|
||||
else if (event.newState != GestureState.POSSIBLE)
|
||||
{
|
||||
setState(GestureState.FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -151,6 +151,16 @@ package org.gestouch.gestures
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
override protected function onDelayedRecognize():void
|
||||
{
|
||||
if (hasEventListener(LongPressGestureEvent.GESTURE_LONG_PRESS))
|
||||
{
|
||||
dispatchEvent(new LongPressGestureEvent(LongPressGestureEvent.GESTURE_LONG_PRESS, false, false, GestureState.BEGAN,
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ package org.gestouch.gestures
|
|||
*/
|
||||
public var direction:uint = PanGestureDirection.NO_DIRECTION;
|
||||
|
||||
protected var _gestureBeginOffsetX:Number;
|
||||
protected var _gestureBeginOffsetY:Number;
|
||||
|
||||
|
||||
public function PanGesture(target:InteractiveObject = null)
|
||||
{
|
||||
|
@ -87,6 +90,15 @@ package org.gestouch.gestures
|
|||
return PanGesture;
|
||||
}
|
||||
|
||||
|
||||
override public function reset():void
|
||||
{
|
||||
_gestureBeginOffsetX = NaN;
|
||||
_gestureBeginOffsetY = NaN;
|
||||
|
||||
super.reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -142,20 +154,14 @@ package org.gestouch.gestures
|
|||
updateLocation();
|
||||
offsetX = _location.x - prevLocationX;
|
||||
offsetY = _location.y - prevLocationY;
|
||||
// Unfortunately we create several new point instances here,
|
||||
// but thats not a big deal since this code executed only once per recognition session
|
||||
var offset:Point = new Point(offsetX, offsetY);
|
||||
if (offset.length > slop)
|
||||
{
|
||||
var slopVector:Point = offset.clone();
|
||||
slopVector.normalize(slop);
|
||||
offset = offset.subtract(slopVector);
|
||||
}
|
||||
// acummulate begin offsets for the case when this gesture recognition is delayed by requireGestureToFail
|
||||
_gestureBeginOffsetX = (_gestureBeginOffsetX != _gestureBeginOffsetX) ? offsetX : _gestureBeginOffsetX + offsetX;
|
||||
_gestureBeginOffsetY = (_gestureBeginOffsetY != _gestureBeginOffsetY) ? offsetY : _gestureBeginOffsetY + offsetY;
|
||||
|
||||
if (setState(GestureState.BEGAN) && hasEventListener(PanGestureEvent.GESTURE_PAN))
|
||||
{
|
||||
dispatchEvent(new PanGestureEvent(PanGestureEvent.GESTURE_PAN, false, false, GestureState.BEGAN,
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, offset.x, offset.y));
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, offsetX, offsetY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,5 +204,15 @@ package org.gestouch.gestures
|
|||
updateLocation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override protected function onDelayedRecognize():void
|
||||
{
|
||||
if (hasEventListener(PanGestureEvent.GESTURE_PAN))
|
||||
{
|
||||
dispatchEvent(new PanGestureEvent(PanGestureEvent.GESTURE_PAN, false, false, GestureState.BEGAN,
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, _gestureBeginOffsetX, _gestureBeginOffsetY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -176,11 +176,12 @@ package org.gestouch.gestures
|
|||
}
|
||||
else if (absVelX >= minVelocity && (minOffset != minOffset || absOffsetX >= minOffset))
|
||||
{
|
||||
_offset.y = 0;
|
||||
if (setState(GestureState.RECOGNIZED) && hasEventListener(SwipeGestureEvent.GESTURE_SWIPE))
|
||||
{
|
||||
_localLocation = target.globalToLocal(_location);//refresh local location in case target moved
|
||||
dispatchEvent(new SwipeGestureEvent(SwipeGestureEvent.GESTURE_SWIPE, false, false, GestureState.RECOGNIZED,
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, _offset.x, 0));
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, _offset.x, _offset.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,11 +204,12 @@ package org.gestouch.gestures
|
|||
}
|
||||
else if (absVelY >= minVelocity && (minOffset != minOffset || absOffsetY >= minOffset))
|
||||
{
|
||||
_offset.x = 0;
|
||||
if (setState(GestureState.RECOGNIZED) && hasEventListener(SwipeGestureEvent.GESTURE_SWIPE))
|
||||
{
|
||||
_localLocation = target.globalToLocal(_location);//refresh local location in case target moved
|
||||
dispatchEvent(new SwipeGestureEvent(SwipeGestureEvent.GESTURE_SWIPE, false, false, GestureState.RECOGNIZED,
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, 0, _offset.y));
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, _offset.x, _offset.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,5 +228,16 @@ package org.gestouch.gestures
|
|||
setState(GestureState.FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override protected function onDelayedRecognize():void
|
||||
{
|
||||
if (hasEventListener(SwipeGestureEvent.GESTURE_SWIPE))
|
||||
{
|
||||
_localLocation = target.globalToLocal(_location);//refresh local location in case target moved
|
||||
dispatchEvent(new SwipeGestureEvent(SwipeGestureEvent.GESTURE_SWIPE, false, false, GestureState.RECOGNIZED,
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y, _offset.x, _offset.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -151,6 +151,16 @@ package org.gestouch.gestures
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
override protected function onDelayedRecognize():void
|
||||
{
|
||||
if (hasEventListener(TapGestureEvent.GESTURE_TAP))
|
||||
{
|
||||
dispatchEvent(new TapGestureEvent(TapGestureEvent.GESTURE_TAP, false, false, GestureState.RECOGNIZED,
|
||||
_location.x, _location.y, _localLocation.x, _localLocation.y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue