Squashed commit of the following:

commit e15c7e7318
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 14 18:36:05 2012 +0200

    Bumped version to 0.3.1

    Releasing bunch of fixes

commit ffb8ce1ec3
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 14 18:00:38 2012 +0200

    Proper state changing on calling Gesture#reset()

commit 13231a4708
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 14 17:49:49 2012 +0200

    Fix for LongPressGesture to work correctly with minPressDuration of zero (and the new IDLE state)

commit a449965e39
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 14 17:34:24 2012 +0200

    Fix to output GestureStateEvent#toString() propely

commit bcb3dfb61f
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 14 16:58:39 2012 +0200

    Removed some redundant code

commit 82742a8465
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 14 15:32:51 2012 +0200

    Made Gesture weak-referencing target

commit e14bbd11bb
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Thu Mar 8 13:40:04 2012 +0200

    Input adapters fix to catch events on empty stage

commit 97486ba2fe
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 7 01:12:50 2012 +0200

    Bumped version to 0.3

commit 764ca1522f
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Mar 7 01:05:04 2012 +0200

    Readme updates

commit 2efa95b85c
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 23:28:12 2012 +0200

    Experimental requireGestureToFail API implemented

commit 4e02d4ae63
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 23:27:39 2012 +0200

    Reformat condition

commit 7cdec34be4
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 23:17:23 2012 +0200

    Swipe gesture algorithm rewritten for better recognition and failing

commit 9edcd04878
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 12:00:38 2012 +0200

    Tiny cleanup

commit b922057845
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 01:22:42 2012 +0200

    New gesture for free transformation

    more precise and performant then combination of 3

commit 5f28227c75
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 01:12:46 2012 +0200

    Using custom GestureEvent and TransformGestureEvent from now on

commit 06df91ce04
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 00:52:50 2012 +0200

    Custom GestureEvent and TransformGestureEvent

    because native one have useless phase and stupid constants

commit 398e41f610
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 00:51:25 2012 +0200

    TouchesManager should not clone touches

    because they must persist during touch session. also good for performance.

commit 49b1139b4f
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Mar 6 00:50:34 2012 +0200

    Touch properties update

commit 242966790a
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Sat Mar 3 17:41:29 2012 +0200

    New gesture state

commit 4d5bef0252
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Fri Mar 2 20:33:16 2012 +0200

    Touch properties updates (and corresponding gestures fixes)

commit b56107e059
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Thu Mar 1 23:56:45 2012 +0200

    Minor cleanup for Gesture class

commit 51e8435b2d
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Thu Mar 1 18:12:35 2012 +0200

    Input adapters initialization and disposing

commit 895e662bd5
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Feb 29 22:20:09 2012 +0200

    Minor performance fix for SwipeGesture

commit 3dcc78c267
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Wed Feb 29 13:54:59 2012 +0200

    Added direction for PanGesture

commit 09dc1ddfc4
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Feb 21 20:14:13 2012 +0200

    Touch#time fix (affects SwipeGesture)

commit 0532f4bfbb
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Mon Feb 20 17:43:43 2012 +0200

    Moved some IGesturesManager methods under gestouch_internal namespace

commit 3ba8a3df86
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Fri Feb 17 17:53:15 2012 +0200

    Put back automatic input adapter initialization

commit 6d8b733d51
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Fri Feb 3 15:57:11 2012 +0200

    Moved input logic out to separate classes

commit ad767a4937
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Thu Feb 2 16:57:16 2012 +0200

    Bugfix for mouse/finger release out of stage

commit 47f2f848e4
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Fri Dec 30 18:26:16 2011 +0200

    Optimized event dispatching

commit 3e1b5948b2
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Fri Dec 30 16:47:52 2011 +0200

    Small optimization for PanGesture

commit d950550d16
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Fri Dec 30 03:19:56 2011 +0200

    Catch all the Touch/Mouse events in capture phase

    GesturesManager now captures TOUCH_BEGIN or MOUSE_DOWN from the stage in capture phase to be able to prevent their propagation at the target without affecting the gesture regoznition.

commit 9d9fcd20ba
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Nov 22 10:40:42 2011 +0200

    Fix central point calculation for more precise transformations

commit a036db1aef
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Nov 22 02:54:11 2011 +0200

    Initial commit for the new architecture

commit 9144538e46
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Nov 1 14:10:05 2011 +0200

    Added Gesture#enabled property

commit d3ddb825b5
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Oct 25 15:19:05 2011 +0300

    Fix condition for dispatching GestureTrackingEvent.GESTURE_TRACKING_END

commit fbc4ab7422
Merge: dc489ba e508862
Author: Pavel fljot <pavel.fljot@gmail.com>
Date:   Tue Oct 25 13:47:51 2011 +0300

    Merge branch 'refs/heads/master' into develop
This commit is contained in:
Pavel fljot 2012-03-14 18:39:53 +02:00
parent 99278b8ae0
commit 07d82c206c
8 changed files with 117 additions and 58 deletions

View file

@ -26,7 +26,7 @@ package org.gestouch.core
protected const _frameTickerShape:Shape = new Shape();
protected var _inputAdapters:Vector.<IInputAdapter> = new Vector.<IInputAdapter>();
protected var _stage:Stage;
protected var _gestures:Vector.<Gesture> = new Vector.<Gesture>();
protected var _gesturesMap:Dictionary = new Dictionary(true);
protected var _gesturesForTouchMap:Array = [];
protected var _gesturesForTargetMap:Dictionary = new Dictionary(true);
protected var _dirtyGestures:Vector.<Gesture> = new Vector.<Gesture>();
@ -157,19 +157,20 @@ package org.gestouch.core
{
throw new ArgumentError("Argument 'gesture' must be not null.");
}
if (_gestures.indexOf(gesture) > -1)
if (_gesturesMap[gesture])
{
throw new Error("This gesture is already registered.. something wrong.");
}
var targetGestures:Vector.<Gesture> = _gesturesForTargetMap[gesture.target] as Vector.<Gesture>;
var target:Object = gesture.target;
var targetGestures:Vector.<Gesture> = _gesturesForTargetMap[target] as Vector.<Gesture>;
if (!targetGestures)
{
targetGestures = _gesturesForTargetMap[gesture.target] = new Vector.<Gesture>();
}
targetGestures.push(gesture);
_gestures.push(gesture);
_gesturesMap[gesture] = true;
if (GesturesManager.initDefaultInputAdapter)
{
@ -195,19 +196,17 @@ package org.gestouch.core
var target:InteractiveObject = gesture.target;
var targetGestures:Vector.<Gesture> = _gesturesForTargetMap[target] as Vector.<Gesture>;
targetGestures.splice(targetGestures.indexOf(gesture), 1);
if (targetGestures.length == 0)
if (targetGestures.length > 1)
{
targetGestures.splice(targetGestures.indexOf(gesture), 1);
}
else
{
delete _gesturesForTargetMap[target];
target.removeEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
}
var index:int = _gestures.indexOf(gesture);
if (index > -1)
{
_gestures.splice(index, 1);
}
delete _gesturesMap[gesture];
//TODO: decide about gesture state and _dirtyGestures
}
@ -226,24 +225,30 @@ package org.gestouch.core
gestouch_internal function onGestureRecognized(gesture:Gesture):void
{
for each (var otherGesture:Gesture in _gestures)
for (var key:Object in _gesturesMap)
{
var otherGesture:Gesture = key as Gesture;
var target:DisplayObject = gesture.target;
var otherTarget:DisplayObject = otherGesture.target;
// conditions for otherGesture "own properties"
if (otherGesture != gesture &&
target && otherTarget &&//in case GC worked half way through
otherGesture.enabled &&
otherGesture.state == GestureState.POSSIBLE)
{
// conditions for otherGesture target
if (otherGesture.target == gesture.target ||
(gesture.target is DisplayObjectContainer && (gesture.target as DisplayObjectContainer).contains(otherGesture.target)) ||
(otherGesture.target is DisplayObjectContainer && (otherGesture.target as DisplayObjectContainer).contains(gesture.target))
)
if (otherTarget == target ||
(target is DisplayObjectContainer && (target as DisplayObjectContainer).contains(otherTarget)) ||
(otherTarget is DisplayObjectContainer && (otherTarget as DisplayObjectContainer).contains(target)))
{
var gestureDelegate:IGestureDelegate = gesture.delegate;
var otherGestureDelegate:IGestureDelegate = otherGesture.delegate;
// conditions for gestures relations
if (gesture.canPreventGesture(otherGesture) &&
otherGesture.canBePreventedByGesture(gesture) &&
(!gesture.delegate || !gesture.delegate.gesturesShouldRecognizeSimultaneously(gesture, otherGesture)) &&
(!otherGesture.delegate || !otherGesture.delegate.gesturesShouldRecognizeSimultaneously(otherGesture, gesture)))
(!gestureDelegate || !gestureDelegate.gesturesShouldRecognizeSimultaneously(gesture, otherGesture)) &&
(!otherGestureDelegate || !otherGestureDelegate.gesturesShouldRecognizeSimultaneously(otherGesture, gesture)))
{
otherGesture.gestouch_internal::setState_internal(GestureState.FAILED);
}

View file

@ -1,7 +1,5 @@
package org.gestouch.core
{
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
/**
* @author Pavel fljot
*/
@ -12,10 +10,6 @@ package org.gestouch.core
protected var _touchesMap:Object = {};
{
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
}
public function TouchesManager()
{

View file

@ -31,7 +31,7 @@ package org.gestouch.events
override public function toString():String
{
return formatToString("GestureStateEvent", newState, oldState);
return formatToString("GestureStateEvent", "type", "oldState", "newState");
}
}
}

View file

@ -4,9 +4,7 @@ package org.gestouch.gestures
import org.gestouch.core.GesturesManager;
import org.gestouch.core.IGestureDelegate;
import org.gestouch.core.IGesturesManager;
import org.gestouch.core.ITouchesManager;
import org.gestouch.core.Touch;
import org.gestouch.core.TouchesManager;
import org.gestouch.core.gestouch_internal;
import org.gestouch.events.GestureStateEvent;
@ -37,9 +35,6 @@ package org.gestouch.gestures
public static const DEFAULT_SLOP:uint = Math.round(20 / 252 * flash.system.Capabilities.screenDPI);
public var delegate:IGestureDelegate;
protected const _touchesManager:ITouchesManager = TouchesManager.getInstance();
protected const _gesturesManager:IGesturesManager = GesturesManager.getInstance();
/**
* Map (generic object) of tracking touch points, where keys are touch points IDs.
@ -66,7 +61,7 @@ package org.gestouch.gestures
/** @private */
protected var _target:InteractiveObject;
private var _targetWeekStorage:Dictionary;
/**
* InteractiveObject (DisplayObject) which this gesture is tracking the actual gesture motion on.
@ -81,16 +76,28 @@ package org.gestouch.gestures
*/
public function get target():InteractiveObject
{
return _target;
for (var key:Object in _targetWeekStorage)
{
return key as InteractiveObject;
}
return null;
}
public function set target(value:InteractiveObject):void
{
if (_target == value)
var target:InteractiveObject = this.target;
if (target == value)
return;
uninstallTarget(target);
_target = value;
installTarget(target);
for (var key:Object in _targetWeekStorage)
{
delete _targetWeekStorage[key];
}
if (value)
{
(_targetWeekStorage ||= new Dictionary(true))[value] = true;
}
installTarget(value);
}
@ -119,6 +126,28 @@ package org.gestouch.gestures
}
private var _delegateWeekStorage:Dictionary;
public function get delegate():IGestureDelegate
{
for (var key:Object in _delegateWeekStorage)
{
return key as IGestureDelegate;
}
return null;
}
public function set delegate(value:IGestureDelegate):void
{
for (var key:Object in _delegateWeekStorage)
{
delete _delegateWeekStorage[key];
}
if (value)
{
(_delegateWeekStorage ||= new Dictionary(true))[value] = true;
}
}
protected var _state:uint = GestureState.IDLE;
public function get state():uint
{
@ -184,7 +213,11 @@ package org.gestouch.gestures
*/
public function reset():void
{
//FIXME: proper state change?
var state:uint = this.state;//caching getter
if (state == GestureState.IDLE)
return;// Do nothing as we're in IDLE and nothing to reset
_location.x = 0;
_location.y = 0;
_touchesMap = {};
@ -197,7 +230,25 @@ package org.gestouch.gestures
}
_pendingRecognizedState = 0;
setState(GestureState.IDLE);
if (state == GestureState.POSSIBLE)
{
// manual reset() call. Set to FAILED to keep our State Machine clean and stable
setState(GestureState.FAILED);
}
else if (state == GestureState.BEGAN || state == GestureState.RECOGNIZED)
{
// manual reset() call. Set to CANCELLED to keep our State Machine clean and stable
setState(GestureState.CANCELLED);
}
else
{
// reset from GesturesManager after reaching one of the 4 final states:
// (state == GestureState.RECOGNIZED ||
// state == GestureState.ENDED ||
// state == GestureState.FAILED ||
// state == GestureState.CANCELLED)
setState(GestureState.IDLE);
}
}
@ -211,6 +262,7 @@ package org.gestouch.gestures
//TODO
reset();
target = null;
delegate = null;
_gesturesToFail = null;
}

View file

@ -95,15 +95,8 @@ package org.gestouch.gestures
{
_numTouchesRequiredReached = true;
_timer.reset();
_timer.delay = minPressDuration;
if (minPressDuration > 0)
{
_timer.start();
}
else
{
timer_timerCompleteHandler();
}
_timer.delay = minPressDuration || 1;
_timer.start();
}
}

View file

@ -31,20 +31,20 @@ package org.gestouch.input
}
_stage = stage;
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, true);
}
override public function init():void
{
_stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, true);
_stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);// to catch with EventPhase.AT_TARGET
}
override public function dispose():void
{
_stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, true);
_stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
uninstallStageListeners();
}
@ -53,8 +53,8 @@ package org.gestouch.input
{
// Maximum priority to prevent event hijacking
_stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true, int.MAX_VALUE);
_stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, false, int.MAX_VALUE);
_stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true, int.MAX_VALUE);
// To catch event out of stage
_stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false, int.MAX_VALUE);
}
@ -62,6 +62,7 @@ package org.gestouch.input
protected function uninstallStageListeners():void
{
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true);
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
@ -69,6 +70,8 @@ package org.gestouch.input
protected function mouseDownHandler(event:MouseEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;//we listen in capture or at_target (to catch on empty stage)
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (_touchesManager.hasTouch(PRIMARY_TOUCH_POINT_ID))
@ -77,8 +80,8 @@ package org.gestouch.input
installStageListeners();
var touch:Touch = _touchesManager.createTouch();
touch.id = 0;
touch.target = event.target as InteractiveObject;
touch.id = PRIMARY_TOUCH_POINT_ID;
touch.gestouch_internal::setLocation(new Point(event.stageX, event.stageY));
touch.gestouch_internal::setTime(getTimer());
touch.gestouch_internal::setBeginTime(getTimer());
@ -91,6 +94,8 @@ package org.gestouch.input
protected function mouseMoveHandler(event:MouseEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;//we listen in capture or at_target (to catch on empty stage)
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (!_touchesManager.hasTouch(PRIMARY_TOUCH_POINT_ID))
@ -106,10 +111,8 @@ package org.gestouch.input
protected function mouseUpHandler(event:MouseEvent):void
{
// If event happens outside of stage it will be with AT_TARGET phase
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;
return;//we listen in capture or at_target (to catch on empty stage)
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.

View file

@ -8,6 +8,8 @@ package org.gestouch.input
import flash.events.EventPhase;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
import flash.utils.getTimer;
@ -25,6 +27,10 @@ package org.gestouch.input
*/
protected var _touchesMap:Object = {};
{
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
}
public function TouchInputAdapter(stage:Stage)
{
@ -42,12 +48,14 @@ package org.gestouch.input
override public function init():void
{
_stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler, true);
_stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler);// to catch with EventPhase.AT_TARGET
}
override public function dispose():void
{
_stage.removeEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler, true);
_stage.removeEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler);
uninstallStageListeners();
}
@ -56,8 +64,8 @@ package org.gestouch.input
{
// Maximum priority to prevent event hijacking
_stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true, int.MAX_VALUE);
_stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, false, int.MAX_VALUE);
_stage.addEventListener(TouchEvent.TOUCH_END, touchEndHandler, true, int.MAX_VALUE);
// To catch event out of stage
_stage.addEventListener(TouchEvent.TOUCH_END, touchEndHandler, false, int.MAX_VALUE);
}
@ -65,6 +73,7 @@ package org.gestouch.input
protected function uninstallStageListeners():void
{
_stage.removeEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true);
_stage.removeEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler);
_stage.removeEventListener(TouchEvent.TOUCH_END, touchEndHandler, true);
_stage.removeEventListener(TouchEvent.TOUCH_END, touchEndHandler);
}
@ -72,6 +81,8 @@ package org.gestouch.input
protected function touchBeginHandler(event:TouchEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;//we listen in capture or at_target (to catch on empty stage)
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (_touchesManager.hasTouch(event.touchPointID))
@ -107,6 +118,8 @@ package org.gestouch.input
protected function touchMoveHandler(event:TouchEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;//we listen in capture or at_target (to catch on empty stage)
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (!_touchesManager.hasTouch(event.touchPointID) || !_touchesMap.hasOwnProperty(event.touchPointID))
@ -133,9 +146,8 @@ package org.gestouch.input
protected function touchEndHandler(event:TouchEvent):void
{
// If event happens outside of stage it will be with AT_TARGET phase
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;
return;//we listen in capture or at_target (to catch on empty stage)
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.

View file

@ -1 +1 @@
project.version = 0.3
project.version = 0.3.1