Moved input logic out to separate classes

This commit is contained in:
Pavel fljot 2012-02-03 15:57:11 +02:00
parent ad767a4937
commit 6d8b733d51
17 changed files with 468 additions and 420 deletions

View file

@ -1,18 +1,13 @@
package org.gestouch.core package org.gestouch.core
{ {
import flash.events.EventPhase;
import org.gestouch.events.MouseTouchEvent;
import org.gestouch.gestures.Gesture; import org.gestouch.gestures.Gesture;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer; import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject; import flash.display.InteractiveObject;
import flash.display.Stage; import flash.display.Shape;
import flash.events.Event; import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TouchEvent;
import flash.ui.Multitouch;
import flash.utils.Dictionary; import flash.utils.Dictionary;
/** /**
* @author Pavel fljot * @author Pavel fljot
*/ */
@ -22,7 +17,8 @@ package org.gestouch.core
private static var _allowInstantiation:Boolean; private static var _allowInstantiation:Boolean;
protected const _touchesManager:ITouchesManager = TouchesManager.getInstance(); protected const _touchesManager:ITouchesManager = TouchesManager.getInstance();
protected var _stage:Stage; protected const _frameTickerShape:Shape = new Shape();
protected var _inputAdapters:Vector.<IInputAdapter> = new Vector.<IInputAdapter>();
protected var _gestures:Vector.<Gesture> = new Vector.<Gesture>(); protected var _gestures:Vector.<Gesture> = new Vector.<Gesture>();
protected var _gesturesForTouchMap:Array = []; protected var _gesturesForTouchMap:Array = [];
protected var _gesturesForTargetMap:Dictionary = new Dictionary(true); protected var _gesturesForTargetMap:Dictionary = new Dictionary(true);
@ -40,6 +36,12 @@ package org.gestouch.core
} }
public function get inputAdapters():Vector.<IInputAdapter>
{
return _inputAdapters.concat();
}
public static function setImplementation(value:IGesturesManager):void public static function setImplementation(value:IGesturesManager):void
{ {
if (!value) if (!value)
@ -88,15 +90,6 @@ package org.gestouch.core
targetGestures.push(gesture); targetGestures.push(gesture);
_gestures.push(gesture); _gestures.push(gesture);
if (!_stage && gesture.target.stage)
{
installStage(gesture.target.stage);
}
else
{
gesture.target.addEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
}
} }
@ -115,7 +108,6 @@ package org.gestouch.core
if (targetGestures.length == 0) if (targetGestures.length == 0)
{ {
delete _gesturesForTargetMap[target]; delete _gesturesForTargetMap[target];
gesture.target.removeEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
} }
var index:int = _gestures.indexOf(gesture); var index:int = _gestures.indexOf(gesture);
@ -134,7 +126,7 @@ package org.gestouch.core
{ {
_dirtyGestures.push(gesture); _dirtyGestures.push(gesture);
_dirtyGesturesLength++; _dirtyGesturesLength++;
_stage.addEventListener(Event.ENTER_FRAME, stage_enterFrameHandler); _frameTickerShape.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
} }
} }
@ -168,6 +160,38 @@ package org.gestouch.core
} }
public function addInputAdapter(inputAdapter:IInputAdapter):void
{
if (!inputAdapter)
{
throw new Error("Input adapter must be non null.");
}
if (_inputAdapters.indexOf(inputAdapter) > -1)
return;//TODO: throw Error or ignore?
_inputAdapters.push(inputAdapter);
inputAdapter.touchesManager = _touchesManager;
inputAdapter.gesturesManager = this;
}
public function removeInputAdapter(inputAdapter:IInputAdapter):void
{
if (!inputAdapter)
{
throw new Error("Input adapter must be non null.");
}
var index:int = _inputAdapters.indexOf(inputAdapter);
if (index == -1)
{
throw new Error("This input manager is not registered.");
}
_inputAdapters.splice(index, 1);
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -176,55 +200,6 @@ package org.gestouch.core
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
protected function installStage(stage:Stage):void
{
_touchesManager.init(stage);
_stage = stage;
if (Multitouch.supportsTouchEvents)
{
stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler, true);
}
else
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, true);
}
}
protected function installStageListeners():void
{
//TODO: maximum priority to prevent event hijacking?
if (Multitouch.supportsTouchEvents)
{
_stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true);
_stage.addEventListener(TouchEvent.TOUCH_END, touchEndHandler, true);
_stage.addEventListener(TouchEvent.TOUCH_END, touchEndHandler);//to catch event out of stage
}
else
{
_stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true);
_stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
_stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);//to catch event out of stage
}
}
protected function uninstallStageListeners():void
{
if (Multitouch.supportsTouchEvents)
{
_stage.removeEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true);
_stage.removeEventListener(TouchEvent.TOUCH_END, touchEndHandler, true);
}
else
{
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true);
_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
}
}
protected function resetDirtyGestures():void protected function resetDirtyGestures():void
{ {
for each (var gesture:Gesture in _dirtyGestures) for each (var gesture:Gesture in _dirtyGestures)
@ -234,45 +209,17 @@ package org.gestouch.core
_dirtyGestures.length = 0; _dirtyGestures.length = 0;
_dirtyGesturesLength = 0; _dirtyGesturesLength = 0;
_dirtyGesturesMap = new Dictionary(true); _dirtyGesturesMap = new Dictionary(true);
_stage.removeEventListener(Event.ENTER_FRAME, stage_enterFrameHandler); _frameTickerShape.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
} }
gestouch_internal function onTouchBegin(touch:Touch):void
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
protected function gestureTarget_addedToStageHandler(event:Event):void
{
var target:DisplayObject = event.target as DisplayObject;
target.removeEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
if (!_stage)
{
installStage(target.stage);
}
var depth:uint = 1;//NB! not using 0-based for sorting function
var targetParent:DisplayObjectContainer = target.parent;
while (targetParent)
{
depth++;
targetParent = targetParent.parent;
}
}
protected function touchBeginHandler(event:TouchEvent):void
{ {
if (_dirtyGesturesLength > 0) if (_dirtyGesturesLength > 0)
{ {
resetDirtyGestures(); resetDirtyGestures();
} }
var touch:Touch = _touchesManager.getTouch(event.touchPointID);
var gesture:Gesture; var gesture:Gesture;
var i:uint; var i:uint;
@ -323,33 +270,23 @@ package org.gestouch.core
// Check for state because previous (i+1) gesture may already abort current (i) one // Check for state because previous (i+1) gesture may already abort current (i) one
if (gesture.state != GestureState.FAILED) if (gesture.state != GestureState.FAILED)
{ {
gesture.gestouch_internal::touchBeginHandler(touch, event); gesture.gestouch_internal::touchBeginHandler(touch);
} }
else else
{ {
gesturesForTouch.splice(i, 1); gesturesForTouch.splice(i, 1);
} }
} }
installStageListeners();
} }
protected function mouseDownHandler(event:MouseEvent):void gestouch_internal function onTouchMove(touch:Touch):void
{
touchBeginHandler(MouseTouchEvent.createMouseTouchEvent(event));
}
protected function touchMoveHandler(event:TouchEvent):void
{ {
if (_dirtyGesturesLength > 0) if (_dirtyGesturesLength > 0)
{ {
resetDirtyGestures(); resetDirtyGestures();
} }
var touch:Touch = _touchesManager.getTouch(event.touchPointID);
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch.id] as Vector.<Gesture>; var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch.id] as Vector.<Gesture>;
var gesture:Gesture; var gesture:Gesture;
var i:int = gesturesForTouch.length; var i:int = gesturesForTouch.length;
@ -359,7 +296,7 @@ package org.gestouch.core
if (gesture.state != GestureState.FAILED && gesture.isTrackingTouch(touch.id)) if (gesture.state != GestureState.FAILED && gesture.isTrackingTouch(touch.id))
{ {
gesture.gestouch_internal::touchMoveHandler(touch, event); gesture.gestouch_internal::touchMoveHandler(touch);
} }
else else
{ {
@ -370,26 +307,13 @@ package org.gestouch.core
} }
protected function mouseMoveHandler(event:MouseEvent):void gestouch_internal function onTouchEnd(touch:Touch):void
{ {
//TODO: copy code from touchMoveHandler: save 1 function call?
touchMoveHandler(MouseTouchEvent.createMouseTouchEvent(event));
}
protected function touchEndHandler(event:TouchEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;
if (_dirtyGesturesLength > 0) if (_dirtyGesturesLength > 0)
{ {
resetDirtyGestures(); resetDirtyGestures();
} }
var touch:Touch = _touchesManager.getTouch(event.touchPointID);
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch.id] as Vector.<Gesture>; var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch.id] as Vector.<Gesture>;
var gesture:Gesture; var gesture:Gesture;
var i:int = gesturesForTouch.length; var i:int = gesturesForTouch.length;
@ -397,29 +321,29 @@ package org.gestouch.core
{ {
gesture = gesturesForTouch[i] as Gesture; gesture = gesturesForTouch[i] as Gesture;
// TODO: handle cancelled touch:
// if (event.hasOwnProperty("isTouchPointCanceled") && event["isTouchPointCanceled"] && ...
if (gesture.state != GestureState.FAILED && gesture.isTrackingTouch(touch.id)) if (gesture.state != GestureState.FAILED && gesture.isTrackingTouch(touch.id))
{ {
gesture.gestouch_internal::touchEndHandler(touch, event); gesture.gestouch_internal::touchEndHandler(touch);
} }
} }
if (_touchesManager.activeTouchesCount == 0)
{
uninstallStageListeners();
}
} }
protected function mouseUpHandler(event:MouseEvent):void gestouch_internal function onTouchCancel(touch:Touch):void
{ {
touchEndHandler(MouseTouchEvent.createMouseTouchEvent(event)); //TODO
} }
private function stage_enterFrameHandler(event:Event):void
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
private function enterFrameHandler(event:Event):void
{ {
resetDirtyGestures(); resetDirtyGestures();
} }

View file

@ -6,6 +6,9 @@ package org.gestouch.core
*/ */
public interface IGesturesManager public interface IGesturesManager
{ {
function addInputAdapter(inputAdapter:IInputAdapter):void;
function removeInputAdapter(inputAdapter:IInputAdapter):void;
function addGesture(gesture:Gesture):void; function addGesture(gesture:Gesture):void;
function removeGesture(gesture:Gesture):void; function removeGesture(gesture:Gesture):void;

View file

@ -0,0 +1,11 @@
package org.gestouch.core
{
/**
* @author Pavel fljot
*/
public interface IInputAdapter
{
function set touchesManager(value:ITouchesManager):void;
function set gesturesManager(value:IGesturesManager):void;
}
}

View file

@ -1,6 +1,5 @@
package org.gestouch.core package org.gestouch.core
{ {
import flash.display.Stage;
/** /**
* @author Pavel fljot * @author Pavel fljot
*/ */
@ -8,7 +7,10 @@ package org.gestouch.core
{ {
function get activeTouchesCount():uint; function get activeTouchesCount():uint;
function init(stage:Stage):void; function createTouch():Touch;
function addTouch(touch:Touch):Touch;
function removeTouch(touch:Touch):Touch;
function getTouch(touchPointID:int):Touch; function getTouch(touchPointID:int):Touch;
function hasTouch(touchPointID:int):Boolean;
} }
} }

View file

@ -1,13 +1,7 @@
package org.gestouch.core package org.gestouch.core
{ {
import flash.events.EventPhase;
import flash.display.InteractiveObject;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.events.TouchEvent;
import flash.ui.Multitouch; import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode; import flash.ui.MultitouchInputMode;
import flash.utils.getTimer;
/** /**
* @author Pavel fljot * @author Pavel fljot
*/ */
@ -16,7 +10,6 @@ package org.gestouch.core
private static var _instance:ITouchesManager; private static var _instance:ITouchesManager;
private static var _allowInstantiation:Boolean; private static var _allowInstantiation:Boolean;
protected var _stage:Stage;
protected var _touchesMap:Object = {}; protected var _touchesMap:Object = {};
{ {
@ -67,25 +60,44 @@ package org.gestouch.core
} }
public function init(stage:Stage):void public function createTouch():Touch
{ {
_stage = stage; //TODO: pool
if (Multitouch.supportsTouchEvents) return new Touch();
}
public function addTouch(touch:Touch):Touch
{
if (_touchesMap.hasOwnProperty(touch.id))
{ {
stage.addEventListener(TouchEvent.TOUCH_BEGIN, stage_touchBeginHandler, true, int.MAX_VALUE); throw new Error("Touch with id " + touch.id + " is already registered.");
stage.addEventListener(TouchEvent.TOUCH_MOVE, stage_touchMoveHandler, true, int.MAX_VALUE);
stage.addEventListener(TouchEvent.TOUCH_END, stage_touchEndHandler, true, int.MAX_VALUE);
// if mouse/finger leaves the stage we will get only AT_TARGET phase
stage.addEventListener(TouchEvent.TOUCH_END, stage_touchEndHandler, false, int.MAX_VALUE);
} }
else
_touchesMap[touch.id] = touch;
_activeTouchesCount++;
return touch;
}
public function removeTouch(touch:Touch):Touch
{
if (!_touchesMap.hasOwnProperty(touch.id))
{ {
stage.addEventListener(MouseEvent.MOUSE_DOWN, stage_mouseDownHandler, true, int.MAX_VALUE); throw new Error("Touch with id " + touch.id + " is not registered.");
stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler, true, int.MAX_VALUE);
stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler, true, int.MAX_VALUE);
// if mouse/finger leaves the stage we will get only AT_TARGET phase
stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler, false, int.MAX_VALUE);
} }
delete _touchesMap[touch.id];
_activeTouchesCount--;
return touch;
}
public function hasTouch(touchPointID:int):Boolean
{
return _touchesMap.hasOwnProperty(touchPointID);
} }
@ -94,119 +106,5 @@ package org.gestouch.core
var touch:Touch = _touchesMap[touchPointID] as Touch; var touch:Touch = _touchesMap[touchPointID] as Touch;
return touch ? touch.clone() : null; return touch ? touch.clone() : null;
} }
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
protected function stage_touchBeginHandler(event:TouchEvent):void
{
var touch:Touch = new Touch(event.touchPointID);
_touchesMap[event.touchPointID] = touch;
touch.target = event.target as InteractiveObject;
touch.x = event.stageX;
touch.y = event.stageY;
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
touch.time = getTimer();//TODO: conditional compilation + event.timestamp
_activeTouchesCount++;
}
protected function stage_mouseDownHandler(event:MouseEvent):void
{
var touch:Touch = new Touch(0);
_touchesMap[0] = touch;
touch.target = event.target as InteractiveObject;
touch.x = event.stageX;
touch.y = event.stageY;
touch.sizeX = NaN;
touch.sizeY = NaN;
touch.pressure = NaN;
touch.time = getTimer();//TODO: conditional compilation + event.timestamp
_activeTouchesCount++;
}
protected function stage_touchMoveHandler(event:TouchEvent):void
{
var touch:Touch = _touchesMap[event.touchPointID] as Touch;
if (!touch)
{
// some fake event?
return;
}
touch.x = event.stageX;
touch.y = event.stageY;
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
touch.time = getTimer();//TODO: conditional compilation + event.timestamp
}
protected function stage_mouseMoveHandler(event:MouseEvent):void
{
var touch:Touch = _touchesMap[0] as Touch;
if (!touch)
{
// some fake event?
return;
}
touch.x = event.stageX;
touch.y = event.stageY;
touch.time = getTimer();//TODO: conditional compilation + event.timestamp
}
protected function stage_touchEndHandler(event:TouchEvent):void
{
var touch:Touch = _touchesMap[event.touchPointID] as Touch;
if (!touch)
{
// some fake event?
return;
}
touch.x = event.stageX;
touch.y = event.stageY;
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
touch.time = getTimer();//TODO: conditional compilation + event.timestamp
_activeTouchesCount--;
}
protected function stage_mouseUpHandler(event:MouseEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;
var touch:Touch = _touchesMap[0] as Touch;
if (!touch)
{
// some fake event?
return;
}
touch.x = event.stageX;
touch.y = event.stageY;
touch.time = getTimer();//TODO: conditional compilation + event.timestamp
_activeTouchesCount--;
}
} }
} }

View file

@ -1,99 +0,0 @@
package org.gestouch.events
{
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TouchEvent;
/**
* @author Pavel fljot
*/
public class MouseTouchEvent extends TouchEvent
{
private static const typeMap:Object = {};
protected var _mouseEvent:MouseEvent;
{
MouseTouchEvent.typeMap[MouseEvent.MOUSE_DOWN] = TouchEvent.TOUCH_BEGIN;
MouseTouchEvent.typeMap[MouseEvent.MOUSE_MOVE] = TouchEvent.TOUCH_MOVE;
MouseTouchEvent.typeMap[MouseEvent.MOUSE_UP] = TouchEvent.TOUCH_END;
}
public function MouseTouchEvent(type:String, event:MouseEvent)
{
super(type, event.bubbles, event.cancelable, 0, true, event.localX, event.localY, NaN, NaN, NaN, event.relatedObject, event.ctrlKey, event.altKey, event.shiftKey);
_mouseEvent = event;
}
public static function createMouseTouchEvent(event:MouseEvent):MouseTouchEvent
{
var type:String = MouseTouchEvent.typeMap[event.type];
if (!type)
{
throw new Error("No match found for MouseEvent of type \"" + event.type + "\"");
}
return new MouseTouchEvent(type, event);
}
override public function get target():Object
{
return _mouseEvent.target;
}
override public function get currentTarget():Object
{
return _mouseEvent.currentTarget;
}
override public function get eventPhase():uint
{
return _mouseEvent.eventPhase;
}
override public function get stageX():Number
{
return _mouseEvent.stageX;
}
override public function get stageY():Number
{
return _mouseEvent.stageY;
}
override public function stopPropagation():void
{
super.stopPropagation();
_mouseEvent.stopPropagation();
}
override public function stopImmediatePropagation():void
{
super.stopImmediatePropagation();
_mouseEvent.stopImmediatePropagation();
}
override public function clone():Event
{
return super.clone();
}
override public function toString():String
{
return super.toString() + " *faked";
}
}
}

View file

@ -273,7 +273,7 @@ package org.gestouch.gestures
/** /**
* TODO: clarify usage. For now it's supported to call this method in onTouchBegin with return. * TODO: clarify usage. For now it's supported to call this method in onTouchBegin with return.
*/ */
protected function ignoreTouch(touch:Touch, event:TouchEvent):void protected function ignoreTouch(touch:Touch):void
{ {
if (_touchesMap.hasOwnProperty(touch.id)) if (_touchesMap.hasOwnProperty(touch.id))
{ {
@ -285,33 +285,27 @@ package org.gestouch.gestures
[Abstract] [Abstract]
/** /**
* Internal method, used by GesturesManager.
*
* <p><b>NB!</b> This is abstract method and must be overridden.</p> * <p><b>NB!</b> This is abstract method and must be overridden.</p>
*/ */
protected function onTouchBegin(touch:Touch, event:TouchEvent):void protected function onTouchBegin(touch:Touch):void
{ {
} }
[Abstract] [Abstract]
/** /**
* Internal method, used by GesturesManager.
*
* <p><b>NB!</b> This is abstract method and must be overridden.</p> * <p><b>NB!</b> This is abstract method and must be overridden.</p>
*/ */
protected function onTouchMove(touch:Touch, event:TouchEvent):void protected function onTouchMove(touch:Touch):void
{ {
} }
[Abstract] [Abstract]
/** /**
* Internal method, used by GesturesManager.
*
* <p><b>NB!</b> This is abstract method and must be overridden.</p> * <p><b>NB!</b> This is abstract method and must be overridden.</p>
*/ */
protected function onTouchEnd(touch:Touch, event:TouchEvent):void protected function onTouchEnd(touch:Touch):void
{ {
} }
@ -401,28 +395,28 @@ package org.gestouch.gestures
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
gestouch_internal function touchBeginHandler(touch:Touch, event:TouchEvent):void gestouch_internal function touchBeginHandler(touch:Touch):void
{ {
_touchesMap[touch.id] = touch; _touchesMap[touch.id] = touch;
_touchesCount++; _touchesCount++;
onTouchBegin(touch, event); onTouchBegin(touch);
} }
gestouch_internal function touchMoveHandler(touch:Touch, event:TouchEvent):void gestouch_internal function touchMoveHandler(touch:Touch):void
{ {
_touchesMap[touch.id] = touch; _touchesMap[touch.id] = touch;
onTouchMove(touch, event); onTouchMove(touch);
} }
gestouch_internal function touchEndHandler(touch:Touch, event:TouchEvent):void gestouch_internal function touchEndHandler(touch:Touch):void
{ {
delete _touchesMap[touch.id]; delete _touchesMap[touch.id];
_touchesCount--; _touchesCount--;
onTouchEnd(touch, event); onTouchEnd(touch);
} }
} }
} }

View file

@ -7,7 +7,6 @@ package org.gestouch.gestures
import flash.display.InteractiveObject; import flash.display.InteractiveObject;
import flash.events.GesturePhase; import flash.events.GesturePhase;
import flash.events.TimerEvent; import flash.events.TimerEvent;
import flash.events.TouchEvent;
import flash.utils.Timer; import flash.utils.Timer;
@ -82,13 +81,13 @@ package org.gestouch.gestures
} }
override protected function onTouchBegin(touch:Touch, event:TouchEvent):void override protected function onTouchBegin(touch:Touch):void
{ {
if (touchesCount > numTouchesRequired) if (touchesCount > numTouchesRequired)
{ {
if (state == GestureState.BEGAN || state == GestureState.CHANGED) if (state == GestureState.BEGAN || state == GestureState.CHANGED)
{ {
ignoreTouch(touch, event); ignoreTouch(touch);
} }
else else
{ {
@ -117,7 +116,7 @@ package org.gestouch.gestures
} }
override protected function onTouchMove(touch:Touch, event:TouchEvent):void override protected function onTouchMove(touch:Touch):void
{ {
if (state == GestureState.POSSIBLE && slop > 0) if (state == GestureState.POSSIBLE && slop > 0)
{ {
@ -141,7 +140,7 @@ package org.gestouch.gestures
} }
override protected function onTouchEnd(touch:Touch, event:TouchEvent):void override protected function onTouchEnd(touch:Touch):void
{ {
//TODO: check proper condition (behavior) on iOS native //TODO: check proper condition (behavior) on iOS native
if (_numTouchesRequiredReached) if (_numTouchesRequiredReached)

View file

@ -1,13 +1,11 @@
package org.gestouch.gestures package org.gestouch.gestures
{ {
import org.gestouch.events.PanGestureEvent;
import org.gestouch.core.GestureState; import org.gestouch.core.GestureState;
import org.gestouch.core.Touch; import org.gestouch.core.Touch;
import org.gestouch.events.ZoomGestureEvent; import org.gestouch.events.PanGestureEvent;
import flash.display.InteractiveObject; import flash.display.InteractiveObject;
import flash.events.GesturePhase; import flash.events.GesturePhase;
import flash.events.TouchEvent;
import flash.geom.Point; import flash.geom.Point;
[Event(name="gesturePan", type="org.gestouch.events.PanGestureEvent")] [Event(name="gesturePan", type="org.gestouch.events.PanGestureEvent")]
@ -107,12 +105,12 @@ package org.gestouch.gestures
// //
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
override protected function onTouchBegin(touch:Touch, event:TouchEvent):void override protected function onTouchBegin(touch:Touch):void
{ {
if (touchesCount > maxNumTouchesRequired) if (touchesCount > maxNumTouchesRequired)
{ {
//TODO //TODO
ignoreTouch(touch, event); ignoreTouch(touch);
return; return;
} }
@ -126,7 +124,7 @@ package org.gestouch.gestures
} }
override protected function onTouchMove(touch:Touch, event:TouchEvent):void override protected function onTouchMove(touch:Touch):void
{ {
if (touchesCount < minNumTouchesRequired) if (touchesCount < minNumTouchesRequired)
return; return;
@ -180,7 +178,7 @@ package org.gestouch.gestures
} }
override protected function onTouchEnd(touch:Touch, event:TouchEvent):void override protected function onTouchEnd(touch:Touch):void
{ {
if (touchesCount < minNumTouchesRequired) if (touchesCount < minNumTouchesRequired)
{ {

View file

@ -7,7 +7,6 @@ package org.gestouch.gestures
import flash.display.InteractiveObject; import flash.display.InteractiveObject;
import flash.events.GesturePhase; import flash.events.GesturePhase;
import flash.events.TouchEvent;
import flash.geom.Point; import flash.geom.Point;
[Event(name="gestureRotate", type="org.gestouch.events.RotateGestureEvent")] [Event(name="gestureRotate", type="org.gestouch.events.RotateGestureEvent")]
@ -66,12 +65,12 @@ package org.gestouch.gestures
// //
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
override protected function onTouchBegin(touch:Touch, event:TouchEvent):void override protected function onTouchBegin(touch:Touch):void
{ {
if (touchesCount > 2) if (touchesCount > 2)
{ {
//TODO //TODO
ignoreTouch(touch, event); ignoreTouch(touch);
return; return;
} }
@ -94,7 +93,7 @@ package org.gestouch.gestures
} }
override protected function onTouchMove(touch:Touch, event:TouchEvent):void override protected function onTouchMove(touch:Touch):void
{ {
if (touch.id == _firstTouch.id) if (touch.id == _firstTouch.id)
{ {
@ -155,7 +154,7 @@ package org.gestouch.gestures
} }
override protected function onTouchEnd(touch:Touch, event:TouchEvent):void override protected function onTouchEnd(touch:Touch):void
{ {
if (touchesCount == 0) if (touchesCount == 0)
{ {

View file

@ -6,7 +6,6 @@ package org.gestouch.gestures
import flash.display.InteractiveObject; import flash.display.InteractiveObject;
import flash.events.GesturePhase; import flash.events.GesturePhase;
import flash.events.TouchEvent;
import flash.geom.Point; import flash.geom.Point;
import flash.system.Capabilities; import flash.system.Capabilities;
@ -69,7 +68,7 @@ package org.gestouch.gestures
// //
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
override protected function onTouchBegin(touch:Touch, event:TouchEvent):void override protected function onTouchBegin(touch:Touch):void
{ {
if (touchesCount > numTouchesRequired) if (touchesCount > numTouchesRequired)
{ {
@ -88,7 +87,7 @@ package org.gestouch.gestures
} }
override protected function onTouchMove(touch:Touch, event:TouchEvent):void override protected function onTouchMove(touch:Touch):void
{ {
if (touchesCount < numTouchesRequired) if (touchesCount < numTouchesRequired)
return; return;
@ -185,7 +184,7 @@ package org.gestouch.gestures
} }
override protected function onTouchEnd(touch:Touch, event:TouchEvent):void override protected function onTouchEnd(touch:Touch):void
{ {
setState(GestureState.FAILED); setState(GestureState.FAILED);
} }

View file

@ -7,7 +7,6 @@ package org.gestouch.gestures
import flash.display.InteractiveObject; import flash.display.InteractiveObject;
import flash.events.GesturePhase; import flash.events.GesturePhase;
import flash.events.TimerEvent; import flash.events.TimerEvent;
import flash.events.TouchEvent;
import flash.utils.Timer; import flash.utils.Timer;
@ -91,7 +90,7 @@ package org.gestouch.gestures
} }
override protected function onTouchBegin(touch:Touch, event:TouchEvent):void override protected function onTouchBegin(touch:Touch):void
{ {
if (touchesCount > numTouchesRequired) if (touchesCount > numTouchesRequired)
{ {
@ -118,7 +117,7 @@ package org.gestouch.gestures
} }
override protected function onTouchMove(touch:Touch, event:TouchEvent):void override protected function onTouchMove(touch:Touch):void
{ {
if (slop >= 0) if (slop >= 0)
{ {
@ -133,7 +132,7 @@ package org.gestouch.gestures
} }
override protected function onTouchEnd(touch:Touch, event:TouchEvent):void override protected function onTouchEnd(touch:Touch):void
{ {
if (!_numTouchesRequiredReached) if (!_numTouchesRequiredReached)
{ {

View file

@ -6,7 +6,6 @@ package org.gestouch.gestures
import flash.display.InteractiveObject; import flash.display.InteractiveObject;
import flash.events.GesturePhase; import flash.events.GesturePhase;
import flash.events.TouchEvent;
import flash.geom.Point; import flash.geom.Point;
[Event(name="gestureZoom", type="org.gestouch.events.ZoomGestureEvent")] [Event(name="gestureZoom", type="org.gestouch.events.ZoomGestureEvent")]
@ -66,12 +65,12 @@ package org.gestouch.gestures
// //
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
override protected function onTouchBegin(touch:Touch, event:TouchEvent):void override protected function onTouchBegin(touch:Touch):void
{ {
if (touchesCount > 2) if (touchesCount > 2)
{ {
//TODO //TODO
ignoreTouch(touch, event); ignoreTouch(touch);
return; return;
} }
@ -94,7 +93,7 @@ package org.gestouch.gestures
} }
override protected function onTouchMove(touch:Touch, event:TouchEvent):void override protected function onTouchMove(touch:Touch):void
{ {
if (touch.id == _firstTouch.id) if (touch.id == _firstTouch.id)
{ {
@ -165,7 +164,7 @@ package org.gestouch.gestures
} }
override protected function onTouchEnd(touch:Touch, event:TouchEvent):void override protected function onTouchEnd(touch:Touch):void
{ {
if (touchesCount == 0) if (touchesCount == 0)
{ {

View file

@ -0,0 +1,37 @@
package org.gestouch.input
{
import org.gestouch.core.IGesturesManager;
import org.gestouch.core.IInputAdapter;
import org.gestouch.core.ITouchesManager;
/**
* @author Pavel fljot
*/
public class AbstractInputAdapter implements IInputAdapter
{
protected var _touchesManager:ITouchesManager;
protected var _gesturesManager:IGesturesManager;
public function AbstractInputAdapter()
{
if (Object(this).constructor == AbstractInputAdapter)
{
throw new Error("This is abstract class and should not be directly instantiated.");
}
}
public function set touchesManager(value:ITouchesManager):void
{
_touchesManager = value;
}
public function set gesturesManager(value:IGesturesManager):void
{
_gesturesManager = value;
}
}
}

View file

@ -0,0 +1,121 @@
package org.gestouch.input
{
import org.gestouch.core.Touch;
import org.gestouch.core.gestouch_internal;
import flash.display.InteractiveObject;
import flash.display.Stage;
import flash.events.EventPhase;
import flash.events.MouseEvent;
import flash.utils.getTimer;
/**
* @author Pavel fljot
*/
public class MouseInputAdapter extends AbstractInputAdapter
{
private static const PRIMARY_TOUCH_POINT_ID:uint = 0;
protected var _stage:Stage;
public function MouseInputAdapter(stage:Stage)
{
super();
if (!stage)
{
throw new Error("Stage must be not null.");
}
_stage = stage;
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, true);
}
protected function installStageListeners():void
{
// Maximum priority to prevent event hijacking
_stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true, 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);
}
protected function uninstallStageListeners():void
{
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true);
_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
protected function mouseDownHandler(event:MouseEvent):void
{
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (_touchesManager.hasTouch(PRIMARY_TOUCH_POINT_ID))
return;
installStageListeners();
var touch:Touch = _touchesManager.createTouch();
touch.id = 0;
touch.target = event.target as InteractiveObject;
touch.x = event.stageX;
touch.y = event.stageY;
touch.time = getTimer();
_touchesManager.addTouch(touch);
_gesturesManager.gestouch_internal::onTouchBegin(touch);
}
protected function mouseMoveHandler(event:MouseEvent):void
{
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (!_touchesManager.hasTouch(PRIMARY_TOUCH_POINT_ID))
return;
var touch:Touch = _touchesManager.getTouch(PRIMARY_TOUCH_POINT_ID);
touch.x = event.stageX;
touch.y = event.stageY;
//TODO: time update vs begin time
_gesturesManager.gestouch_internal::onTouchMove(touch);
}
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;
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (!_touchesManager.hasTouch(PRIMARY_TOUCH_POINT_ID))
return;
var touch:Touch = _touchesManager.getTouch(PRIMARY_TOUCH_POINT_ID);
touch.x = event.stageX;
touch.y = event.stageY;
//TODO: time update vs begin time
_gesturesManager.gestouch_internal::onTouchEnd(touch);
_touchesManager.removeTouch(touch);
if (_touchesManager.activeTouchesCount == 0)
{
uninstallStageListeners();
}
}
}
}

View file

@ -0,0 +1,17 @@
package org.gestouch.input
{
import org.gestouch.input.AbstractInputAdapter;
/**
* @author Pavel fljot
*/
public class TUIOInputAdapter extends AbstractInputAdapter
{
public function TUIOInputAdapter()
{
super();
//TODO
}
}
}

View file

@ -0,0 +1,147 @@
package org.gestouch.input
{
import org.gestouch.core.Touch;
import org.gestouch.core.gestouch_internal;
import flash.display.InteractiveObject;
import flash.display.Stage;
import flash.events.EventPhase;
import flash.events.TouchEvent;
import flash.utils.getTimer;
/**
* @author Pavel fljot
*/
public class TouchInputAdapter extends AbstractInputAdapter
{
protected var _stage:Stage;
/**
* The hash map of touches instantiated via TouchEvent.
* Used to avoid collisions (double processing) with MouseInputAdapter.
*
* TODO: any better way?
*/
protected var _touchesMap:Object = {};
public function TouchInputAdapter(stage:Stage)
{
super();
if (!stage)
{
throw new Error("Stage must be not null.");
}
_stage = stage;
stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler, true);
}
protected function installStageListeners():void
{
// Maximum priority to prevent event hijacking
_stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true, 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);
}
protected function uninstallStageListeners():void
{
_stage.removeEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true);
_stage.removeEventListener(TouchEvent.TOUCH_END, touchEndHandler, true);
_stage.removeEventListener(TouchEvent.TOUCH_END, touchEndHandler);
}
protected function touchBeginHandler(event:TouchEvent):void
{
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (_touchesManager.hasTouch(event.touchPointID))
return;
installStageListeners();
var touch:Touch = _touchesManager.createTouch();
touch.id = event.touchPointID;
touch.target = event.target as InteractiveObject;
touch.x = event.stageX;
touch.y = event.stageY;
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
//TODO: conditional compilation?
if (event.hasOwnProperty("timestamp"))
{
touch.time = event["timestamp"];
}
else
{
touch.time = getTimer();
}
_touchesManager.addTouch(touch);
_touchesMap[touch.id] = true;
_gesturesManager.gestouch_internal::onTouchBegin(touch);
}
protected function touchMoveHandler(event:TouchEvent):void
{
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (!_touchesManager.hasTouch(event.touchPointID) || !_touchesMap.hasOwnProperty(event.touchPointID))
return;
var touch:Touch = _touchesManager.getTouch(event.touchPointID);
touch.x = event.stageX;
touch.y = event.stageY;
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
//TODO: time update vs begin time
_gesturesManager.gestouch_internal::onTouchMove(touch);
}
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;
// Way to prevent MouseEvent/TouchEvent collisions.
// Also helps to ignore possible fake events.
if (!_touchesManager.hasTouch(event.touchPointID))
return;
var touch:Touch = _touchesManager.getTouch(event.touchPointID);
touch.x = event.stageX;
touch.y = event.stageY;
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
//TODO: time update vs begin time
_gesturesManager.gestouch_internal::onTouchEnd(touch);
_touchesManager.removeTouch(touch);
delete _touchesMap[touch.id];
if (_touchesManager.activeTouchesCount == 0)
{
uninstallStageListeners();
}
// TODO: handle cancelled touch:
// if (event.hasOwnProperty("isTouchPointCanceled") && event["isTouchPointCanceled"] && ...
}
}
}