starling initial commit

This commit is contained in:
Pavel fljot 2012-03-13 14:05:50 +02:00
parent e15c7e7318
commit 13dbd61014
28 changed files with 617 additions and 254 deletions

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<AS3Classpath>
<AS3LibraryFolder>libs</AS3LibraryFolder>
<AS3Classpath generateProblems="true" sdkBased="false" type="source" useAsSharedCode="false">src</AS3Classpath>
<AS3Classpath generateProblems="false" sdkBased="true" type="lib" useAsSharedCode="false">frameworks/libs/air/airglobal.swc</AS3Classpath>
<AS3Classpath generateProblems="false" sdkBased="true" type="lib" useAsSharedCode="false">frameworks/libs/mobile/mobilecomponents.swc</AS3Classpath>
@ -10,4 +11,5 @@
<AS3Classpath generateProblems="false" sdkBased="true" type="lib" useAsSharedCode="false">frameworks/libs/air/servicemonitor.swc</AS3Classpath>
<AS3Classpath generateProblems="false" sdkBased="true" type="lib" useAsSharedCode="false">frameworks/themes/Mobile/mobile.swc</AS3Classpath>
<AS3Classpath generateProblems="false" sdkBased="true" type="lib" useAsSharedCode="false">frameworks/libs/mx/mx.swc</AS3Classpath>
<AS3Classpath generateProblems="false" sdkBased="false" type="lib" useAsSharedCode="false">libs/starling.swc</AS3Classpath>
</AS3Classpath>

View file

@ -21,6 +21,8 @@
<arg value="-include-sources=${src.dir}"/>
<!-- Exclude Flex Framework classes (some mx events comes from binding). -->
<arg value="-external-library-path+=${flexSDK.dir}/frameworks/libs"/>
<!-- Exclude any external classes (such as Starling framework classes) -->
<arg value="-external-library-path+=${libs.dir}"/>
<!-- Keep the metatags (Apparat?). -->
<arg value="-keep-as3-metadata+=Abstract"/>
<!-- Boolean mosh pit! -->
@ -44,6 +46,7 @@
</delete>
<java jar="${FLEX_HOME}/lib/asdoc.jar" dir="${FLEX_HOME}/frameworks" fork="true" failonerror="true">
<arg line="-source-path ${src.dir}"/>
<arg line="-external-library-path+=${libs.dir}"/>
<arg line="-doc-sources ${src.dir}"/>
<arg line="-output ${asdoc.dir}"/>
<arg value="-keep-xml=true"/>

BIN
libs/starling.swc Normal file

Binary file not shown.

View file

@ -0,0 +1,27 @@
package org.gestouch.core
{
import flash.display.DisplayObject;
import org.gestouch.core.IDisplayListAdapter;
/**
* @author Pavel fljot
*/
public class DisplayListAdapter implements IDisplayListAdapter
{
public function getHierarchy(genericTarget:Object):Vector.<Object>
{
var list:Vector.<Object> = new Vector.<Object>();
var i:uint = 0;
var target:DisplayObject = genericTarget as DisplayObject;
while (target)
{
list[i] = target;
target = target.parent;
i++;
}
return list;
}
}
}

View file

@ -0,0 +1,46 @@
package org.gestouch.core
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.geom.Point;
import flash.utils.Dictionary;
/**
* @author Pavel fljot
*/
final public class DisplayObjectAdapter implements IGestureTargetAdapter
{
private var _targetWeekStorage:Dictionary = new Dictionary(true);
public function DisplayObjectAdapter(target:DisplayObject)
{
_targetWeekStorage[target] = true;
}
public function get target():Object
{
for (var key:Object in _targetWeekStorage)
{
return key;
}
return null;
}
public function globalToLocal(point:Point):Point
{
return (target as DisplayObject).globalToLocal(point);
}
public function contains(target:Object):Boolean
{
const targetAsDOC:DisplayObjectContainer = this.target as DisplayObjectContainer;
return (targetAsDOC && targetAsDOC.contains(target as DisplayObject));
}
}
}

View file

@ -5,11 +5,10 @@ package org.gestouch.core
import org.gestouch.input.TouchInputAdapter;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.display.Shape;
import flash.display.Stage;
import flash.events.Event;
import flash.events.IEventDispatcher;
import flash.ui.Multitouch;
import flash.utils.Dictionary;
@ -25,9 +24,10 @@ package org.gestouch.core
protected const _touchesManager:ITouchesManager = TouchesManager.getInstance();
protected const _frameTickerShape:Shape = new Shape();
protected var _inputAdapters:Vector.<IInputAdapter> = new Vector.<IInputAdapter>();
protected var _displayListAdaptersMap:Dictionary = new Dictionary();
protected var _stage:Stage;
protected var _gesturesMap:Dictionary = new Dictionary(true);
protected var _gesturesForTouchMap:Array = [];
protected var _gesturesForTouchMap:Dictionary = new Dictionary();
protected var _gesturesForTargetMap:Dictionary = new Dictionary(true);
protected var _dirtyGestures:Vector.<Gesture> = new Vector.<Gesture>();
protected var _dirtyGesturesLength:uint = 0;
@ -40,6 +40,9 @@ package org.gestouch.core
{
throw new Error("Do not instantiate GesturesManager directly.");
}
_touchesManager.gesturesManager = this;
_displayListAdaptersMap[DisplayObject] = new DisplayListAdapter();
}
@ -90,7 +93,6 @@ package org.gestouch.core
_inputAdapters.push(inputAdapter);
inputAdapter.touchesManager = _touchesManager;
inputAdapter.gesturesManager = this;
inputAdapter.init();
}
@ -115,6 +117,16 @@ package org.gestouch.core
}
public function addDisplayListAdapter(targetClass:Class, adapter:IDisplayListAdapter):void
{
if (!targetClass || !adapter)
{
throw new Error("Argument error: both arguments required.");
}
_displayListAdaptersMap[targetClass] = adapter;
}
//--------------------------------------------------------------------------
@ -166,7 +178,7 @@ package org.gestouch.core
var targetGestures:Vector.<Gesture> = _gesturesForTargetMap[target] as Vector.<Gesture>;
if (!targetGestures)
{
targetGestures = _gesturesForTargetMap[gesture.target] = new Vector.<Gesture>();
targetGestures = _gesturesForTargetMap[target] = new Vector.<Gesture>();
}
targetGestures.push(gesture);
@ -174,13 +186,17 @@ package org.gestouch.core
if (GesturesManager.initDefaultInputAdapter)
{
if (!_stage && gesture.target.stage)
var targetAsDO:DisplayObject = target as DisplayObject;
if (targetAsDO)
{
installStage(gesture.target.stage);
}
else
{
gesture.target.addEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
if (!_stage && targetAsDO.stage)
{
installStage(targetAsDO.stage);
}
else
{
targetAsDO.addEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
}
}
}
}
@ -194,7 +210,7 @@ package org.gestouch.core
}
var target:InteractiveObject = gesture.target;
var target:Object = gesture.target;
var targetGestures:Vector.<Gesture> = _gesturesForTargetMap[target] as Vector.<Gesture>;
if (targetGestures.length > 1)
{
@ -203,7 +219,10 @@ package org.gestouch.core
else
{
delete _gesturesForTargetMap[target];
target.removeEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
if (target is IEventDispatcher)
{
(target as IEventDispatcher).removeEventListener(Event.ADDED_TO_STAGE, gestureTarget_addedToStageHandler);
}
}
delete _gesturesMap[gesture];
@ -228,8 +247,8 @@ package org.gestouch.core
for (var key:Object in _gesturesMap)
{
var otherGesture:Gesture = key as Gesture;
var target:DisplayObject = gesture.target;
var otherTarget:DisplayObject = otherGesture.target;
var target:Object = gesture.target;
var otherTarget:Object = otherGesture.target;
// conditions for otherGesture "own properties"
if (otherGesture != gesture &&
@ -237,10 +256,10 @@ package org.gestouch.core
otherGesture.enabled &&
otherGesture.state == GestureState.POSSIBLE)
{
// conditions for otherGesture target
if (otherTarget == target ||
(target is DisplayObjectContainer && (target as DisplayObjectContainer).contains(otherTarget)) ||
(otherTarget is DisplayObjectContainer && (otherTarget as DisplayObjectContainer).contains(target)))
gesture.targetAdapter.contains(otherTarget) ||
otherGesture.targetAdapter.contains(target)
)
{
var gestureDelegate:IGestureDelegate = gesture.delegate;
var otherGestureDelegate:IGestureDelegate = otherGesture.delegate;
@ -268,24 +287,37 @@ package org.gestouch.core
var gesture:Gesture;
var i:uint;
// This vector will contain active gestures for specific touch (ID) during all touch session.
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch.id] as Vector.<Gesture>;
// This vector will contain active gestures for specific touch during all touch session.
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch] as Vector.<Gesture>;
if (!gesturesForTouch)
{
gesturesForTouch = new Vector.<Gesture>();
_gesturesForTouchMap[touch.id] = gesturesForTouch;
gesturesForTouch = _gesturesForTouchMap[touch] = new Vector.<Gesture>();
}
else
{
gesturesForTouch.length = 0;
}
}
var target:Object = touch.target;
var hierarchy:Vector.<Object>;
for (var key:* in _displayListAdaptersMap)
{
var targetClass:Class = key as Class;
if (target is targetClass)
{
hierarchy = (_displayListAdaptersMap[key] as IDisplayListAdapter).getHierarchy(target);
break;
}
}
if (!hierarchy)
{
throw new Error("Display list adapter not found for target of type '" + targetClass + "'.");
}
// Create a sorted(!) list of gestures which are interested in this touch.
// Sorting priority: deeper target has higher priority, recently added gesture has higher priority.
var target:InteractiveObject = touch.target;
var gesturesForTarget:Vector.<Gesture>;
while (target)
for each (target in hierarchy)
{
gesturesForTarget = _gesturesForTargetMap[target] as Vector.<Gesture>;
if (gesturesForTarget)
@ -302,8 +334,6 @@ package org.gestouch.core
}
}
}
target = target.parent;
}
// Then we populate them with this touch and event.
@ -332,7 +362,7 @@ package org.gestouch.core
resetDirtyGestures();
}
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch.id] as Vector.<Gesture>;
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch] as Vector.<Gesture>;
var gesture:Gesture;
var i:int = gesturesForTouch.length;
while (i-- > 0)
@ -359,7 +389,7 @@ package org.gestouch.core
resetDirtyGestures();
}
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch.id] as Vector.<Gesture>;
var gesturesForTouch:Vector.<Gesture> = _gesturesForTouchMap[touch] as Vector.<Gesture>;
var gesture:Gesture;
var i:int = gesturesForTouch.length;
while (i-- > 0)
@ -371,6 +401,8 @@ package org.gestouch.core
gesture.gestouch_internal::touchEndHandler(touch);
}
}
gesturesForTouch.length = 0;// release for GC
}

View file

@ -0,0 +1,10 @@
package org.gestouch.core
{
/**
* @author Pavel fljot
*/
public interface IDisplayListAdapter
{
function getHierarchy(target:Object):Vector.<Object>;
}
}

View file

@ -0,0 +1,15 @@
package org.gestouch.core
{
import flash.geom.Point;
/**
* @author Pavel fljot
*/
public interface IGestureTargetAdapter
{
function get target():Object;
function globalToLocal(point:Point):Point;
function contains(target:Object):Boolean;
}
}

View file

@ -13,5 +13,7 @@ package org.gestouch.core
{
function addInputAdapter(inputAdapter:IInputAdapter):void;
function removeInputAdapter(inputAdapter:IInputAdapter, dispose:Boolean = true):void;
function addDisplayListAdapter(targetClass:Class, adapter:IDisplayListAdapter):void;
}
}

View file

@ -6,7 +6,6 @@ package org.gestouch.core
public interface IInputAdapter
{
function set touchesManager(value:ITouchesManager):void;
function set gesturesManager(value:IGesturesManager):void;
function init():void;
function dispose():void;

View file

@ -5,12 +5,14 @@ package org.gestouch.core
*/
public interface ITouchesManager
{
function set gesturesManager(value:IGesturesManager):void;
function get activeTouchesCount():uint;
function createTouch():Touch;
function addTouch(touch:Touch):Touch;
function removeTouch(touch:Touch):Touch;
function getTouch(touchPointID:int):Touch;
function hasTouch(touchPointID:int):Boolean;
function onTouchBegin(inputAdapter:IInputAdapter, touchID:uint, x:Number, y:Number, target:Object):void;
function onTouchMove(inputAdapter:IInputAdapter, touchID:uint, x:Number, y:Number):void;
function onTouchEnd(inputAdapter:IInputAdapter, touchID:uint, x:Number, y:Number):void;
function onInputAdapterDispose(inputAdapter:IInputAdapter):void;
}
}

View file

@ -1,6 +1,5 @@
package org.gestouch.core
{
import flash.display.InteractiveObject;
import flash.geom.Point;
@ -19,7 +18,7 @@ package org.gestouch.core
/**
* The original event target for this touch (touch began with).
*/
public var target:InteractiveObject;
public var target:Object;
public var sizeX:Number;
public var sizeY:Number;
@ -39,13 +38,16 @@ package org.gestouch.core
{
return _location.clone();
}
gestouch_internal function setLocation(value:Point):void
gestouch_internal function setLocation(value:Point, time:uint):void
{
_location = value;
_beginLocation = _location.clone();
_previousLocation = _location.clone();
_time = time;
_beginTime = time;
}
gestouch_internal function updateLocation(x:Number, y:Number):void
gestouch_internal function updateLocation(x:Number, y:Number, time:uint):void
{
if (_location)
{
@ -53,10 +55,11 @@ package org.gestouch.core
_previousLocation.y = _location.y;
_location.x = x;
_location.y = y;
_time = time;
}
else
{
gestouch_internal::setLocation(new Point(x, y));
gestouch_internal::setLocation(new Point(x, y), time);
}
}

View file

@ -1,5 +1,8 @@
package org.gestouch.core
{
import flash.geom.Point;
import flash.utils.Dictionary;
import flash.utils.getTimer;
/**
* @author Pavel fljot
*/
@ -20,6 +23,13 @@ package org.gestouch.core
}
protected var _gesturesManager:IGesturesManager;
public function set gesturesManager(value:IGesturesManager):void
{
_gesturesManager = value;
}
protected var _activeTouchesCount:uint;
public function get activeTouchesCount():uint
{
@ -54,50 +64,112 @@ package org.gestouch.core
}
public function createTouch():Touch
public function onTouchBegin(inputAdapter:IInputAdapter, touchID:uint, x:Number, y:Number, target:Object):void
{
var overlappingTouches:Dictionary = _touchesMap[touchID] as Dictionary;
if (overlappingTouches)
{
// In case we listen to both TouchEvents and MouseEvents, one of them will come first
// (right now looks like MouseEvent dispatches first, but who know what Adobe will
// do tomorrow). This check is to filter out the one comes second.
for each (var registeredTouch:Touch in overlappingTouches)
{
if (registeredTouch.target == target)
return;
}
}
else
{
overlappingTouches = _touchesMap[touchID] = new Dictionary();
_activeTouchesCount++;
}
var touch:Touch = createTouch();
touch.id = touchID;
touch.target = target;
touch.gestouch_internal::setLocation(new Point(x, y), getTimer());
overlappingTouches[inputAdapter] = touch;
_gesturesManager.gestouch_internal::onTouchBegin(touch);
}
public function onTouchMove(inputAdapter:IInputAdapter, touchID:uint, x:Number, y:Number):void
{
var overlappingTouches:Dictionary = _touchesMap[touchID] as Dictionary;
if (!overlappingTouches)
return;//this touch isn't properly registered.. some fake
var touch:Touch = overlappingTouches[inputAdapter] as Touch;
if (!touch)
return;//touch with this ID from this inputAdapter is not registered. see workaround reason above
touch.gestouch_internal::updateLocation(x, y, getTimer());
_gesturesManager.gestouch_internal::onTouchMove(touch);
}
public function onTouchEnd(inputAdapter:IInputAdapter, touchID:uint, x:Number, y:Number):void
{
var overlappingTouches:Dictionary = _touchesMap[touchID] as Dictionary;
if (!overlappingTouches)
return;//this touch isn't properly registered.. some fake
var touch:Touch = overlappingTouches[inputAdapter] as Touch;
if (!touch)
return;//touch with this ID from this inputAdapter is not registered. see workaround reason above
touch.gestouch_internal::updateLocation(x, y, getTimer());
delete overlappingTouches[inputAdapter];
var empty:Boolean = true;
for (var key:Object in overlappingTouches)
{
empty = false;
break;
}
if (empty)
{
delete _touchesMap[touchID];
_activeTouchesCount--;
}
_gesturesManager.gestouch_internal::onTouchEnd(touch);
}
/**
* Must be called by IInputAdapter#dispose() to remove all the touches invoked by it.
*/
public function onInputAdapterDispose(inputAdapter:IInputAdapter):void
{
for (var touchID:Object in _touchesMap)
{
var overlappingTouches:Dictionary = _touchesMap[touchID] as Dictionary;
if (overlappingTouches[inputAdapter])
{
delete overlappingTouches[inputAdapter];
var empty:Boolean = true;
for (var key:Object in overlappingTouches)
{
empty = false;
break;
}
if (empty)
{
delete _touchesMap[touchID];
_activeTouchesCount--;
}
}
}
}
protected function createTouch():Touch
{
//TODO: pool
return new Touch();
}
public function addTouch(touch:Touch):Touch
{
if (_touchesMap.hasOwnProperty(touch.id))
{
throw new Error("Touch with id " + touch.id + " is already registered.");
}
_touchesMap[touch.id] = touch;
_activeTouchesCount++;
return touch;
}
public function removeTouch(touch:Touch):Touch
{
if (!_touchesMap.hasOwnProperty(touch.id))
{
throw new Error("Touch with id " + touch.id + " is not registered.");
}
delete _touchesMap[touch.id];
_activeTouchesCount--;
return touch;
}
public function hasTouch(touchPointID:int):Boolean
{
return _touchesMap.hasOwnProperty(touchPointID);
}
public function getTouch(touchPointID:int):Touch
{
return _touchesMap[touchPointID] as Touch;
}
}
}

View file

@ -0,0 +1,27 @@
package org.gestouch.extensions.starling
{
import starling.display.DisplayObject;
import org.gestouch.core.IDisplayListAdapter;
/**
* @author Pavel fljot
*/
public class StarlingDisplayListAdapter implements IDisplayListAdapter
{
public function getHierarchy(genericTarget:Object):Vector.<Object>
{
var list:Vector.<Object> = new Vector.<Object>();
var i:uint = 0;
var target:DisplayObject = genericTarget as DisplayObject;
while (target)
{
list[i] = target;
target = target.parent;
i++;
}
return list;
}
}
}

View file

@ -0,0 +1,47 @@
package org.gestouch.extensions.starling
{
import org.gestouch.core.IGestureTargetAdapter;
import starling.display.DisplayObject;
import starling.display.DisplayObjectContainer;
import flash.geom.Point;
import flash.utils.Dictionary;
/**
* @author Pavel fljot
*/
final public class StarlingDisplayObjectAdapter implements IGestureTargetAdapter
{
private var _targetWeekStorage:Dictionary = new Dictionary(true);
public function StarlingDisplayObjectAdapter(target:DisplayObject)
{
_targetWeekStorage[target] = true;
}
public function get target():Object
{
for (var key:Object in _targetWeekStorage)
{
return key;
}
return null;
}
public function globalToLocal(point:Point):Point
{
return (target as DisplayObject).globalToLocal(point);
}
public function contains(target:Object):Boolean
{
const targetAsDOC:DisplayObjectContainer = this.target as DisplayObjectContainer;
return (targetAsDOC && targetAsDOC.contains(target as DisplayObject));
}
}
}

View file

@ -0,0 +1,185 @@
package org.gestouch.extensions.starling
{
import flash.events.EventPhase;
import flash.events.MouseEvent;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.ui.Mouse;
import org.gestouch.input.AbstractInputAdapter;
import starling.core.Starling;
/**
* @author Pavel fljot
*/
public class StarlingInputAdapter extends AbstractInputAdapter
{
private static const PRIMARY_TOUCH_POINT_ID:uint = 0;
protected var _starling:Starling;
public function StarlingInputAdapter(starling:Starling)
{
super();
if (!starling)
{
throw new Error("Argument error.");
}
_starling = starling;
}
protected function get supportsTouchEvents():Boolean
{
// just like in Starling (starling.core::Starling)
return !(Mouse.supportsCursor || !Starling.multitouchEnabled);
}
override public function init():void
{
// We want to begin tracking only those touches that happen on Stage3D layer,
// e.g. event.target == nativeStage. That's we don't listen for touch begin
// in capture phase (as we do for native display list).
if (supportsTouchEvents)
{
_starling.nativeStage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler);
}
else
{
_starling.nativeStage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
}
override public function dispose():void
{
_starling.nativeStage.removeEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler);
_starling.nativeStage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
uninstallStageListeners();
_starling = null;
_touchesManager.onInputAdapterDispose(this);
_touchesManager = null;
}
protected function installStageListeners():void
{
// Maximum priority to prevent event hijacking
if (supportsTouchEvents)
{
_starling.nativeStage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true, int.MAX_VALUE);
_starling.nativeStage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, false, int.MAX_VALUE);
_starling.nativeStage.addEventListener(TouchEvent.TOUCH_END, touchEndHandler, true, int.MAX_VALUE);
_starling.nativeStage.addEventListener(TouchEvent.TOUCH_END, touchEndHandler, false, int.MAX_VALUE);
}
else
{
_starling.nativeStage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true, int.MAX_VALUE);
_starling.nativeStage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, false, int.MAX_VALUE);
_starling.nativeStage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true, int.MAX_VALUE);
_starling.nativeStage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false, int.MAX_VALUE);
}
}
protected function uninstallStageListeners():void
{
_starling.nativeStage.removeEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, true);
_starling.nativeStage.removeEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler, false);
_starling.nativeStage.removeEventListener(TouchEvent.TOUCH_END, touchEndHandler, true);
_starling.nativeStage.removeEventListener(TouchEvent.TOUCH_END, touchEndHandler, false);
_starling.nativeStage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, true);
_starling.nativeStage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, false);
_starling.nativeStage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
_starling.nativeStage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false);
}
protected function mouseDownHandler(event:MouseEvent):void
{
// We ignore event with bubbling phase because it happened on some native InteractiveObject,
// which basically hovers Stage3D layer. So we treat it as if Starling wouldn't recieve any input.
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;
var target:Object = _starling.stage.hitTest(new Point(event.stageX, event.stageY), true);
_touchesManager.onTouchBegin(this, PRIMARY_TOUCH_POINT_ID, event.stageX, event.stageY, target);
if (_touchesManager.activeTouchesCount > 0)
{
installStageListeners();
}
}
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)
_touchesManager.onTouchMove(this, PRIMARY_TOUCH_POINT_ID, event.stageX, event.stageY);
}
protected function mouseUpHandler(event:MouseEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;//we listen in capture or at_target (to catch on empty stage)
_touchesManager.onTouchEnd(this, PRIMARY_TOUCH_POINT_ID, event.stageX, event.stageY);
if (_touchesManager.activeTouchesCount == 0)
{
uninstallStageListeners();
}
}
protected function touchBeginHandler(event:TouchEvent):void
{
// We ignore event with bubbling phase because it happened on some native InteractiveObject,
// which basically hovers Stage3D layer. So we treat it as if Starling wouldn't recieve any input.
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;
var target:Object = _starling.stage.hitTest(new Point(event.stageX, event.stageY), true);
_touchesManager.onTouchBegin(this, event.touchPointID, event.stageX, event.stageY, target);
if (_touchesManager.activeTouchesCount > 0)
{
installStageListeners();
}
}
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)
_touchesManager.onTouchMove(this, event.touchPointID, event.stageX, event.stageY);
}
protected function touchEndHandler(event:TouchEvent):void
{
if (event.eventPhase == EventPhase.BUBBLING_PHASE)
return;//we listen in capture or at_target (to catch on empty stage)
_touchesManager.onTouchEnd(this, event.touchPointID, event.stageX, event.stageY);
if (_touchesManager.activeTouchesCount == 0)
{
uninstallStageListeners();
}
// TODO: handle cancelled touch:
// if (event.hasOwnProperty("isTouchPointCanceled") && event["isTouchPointCanceled"] && ...
}
}
}

View file

@ -3,12 +3,12 @@ package org.gestouch.gestures
import org.gestouch.core.GestureState;
import org.gestouch.core.GesturesManager;
import org.gestouch.core.IGestureDelegate;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.IGesturesManager;
import org.gestouch.core.Touch;
import org.gestouch.core.gestouch_internal;
import org.gestouch.events.GestureStateEvent;
import flash.display.InteractiveObject;
import flash.events.EventDispatcher;
import flash.geom.Point;
import flash.system.Capabilities;
@ -50,20 +50,29 @@ package org.gestouch.gestures
protected var _pendingRecognizedState:uint;
public function Gesture(target:InteractiveObject = null)
public function Gesture(targetAdapter:IGestureTargetAdapter = null)
{
super();
preinit();
this.target = target;
setTarget(targetAdapter);
}
/** @private */
private var _targetWeekStorage:Dictionary;
protected var _targetAdapter:IGestureTargetAdapter;
/**
*
*/
public function get targetAdapter():IGestureTargetAdapter
{
return _targetAdapter;
}
/**
* FIXME
* InteractiveObject (DisplayObject) which this gesture is tracking the actual gesture motion on.
*
* <p>Could be some image, component (like map) or the larger view like Stage.</p>
@ -74,30 +83,9 @@ package org.gestouch.gestures
*
* @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html
*/
public function get target():InteractiveObject
public function get target():Object
{
for (var key:Object in _targetWeekStorage)
{
return key as InteractiveObject;
}
return null;
}
public function set target(value:InteractiveObject):void
{
var target:InteractiveObject = this.target;
if (target == value)
return;
uninstallTarget(target);
for (var key:Object in _targetWeekStorage)
{
delete _targetWeekStorage[key];
}
if (value)
{
(_targetWeekStorage ||= new Dictionary(true))[value] = true;
}
installTarget(value);
return _targetAdapter ? _targetAdapter.target : null;
}
@ -185,6 +173,17 @@ package org.gestouch.gestures
// Public methods
//
//--------------------------------------------------------------------------
public function setTarget(targetAdapter:IGestureTargetAdapter):void
{
if (_targetAdapter == targetAdapter)
return;
uninstallTarget(this.targetAdapter);
_targetAdapter = targetAdapter;
installTarget(this.targetAdapter);
}
[Abstract]
/**
@ -261,7 +260,7 @@ package org.gestouch.gestures
{
//TODO
reset();
target = null;
setTarget(null);
delegate = null;
_gesturesToFail = null;
}
@ -310,9 +309,9 @@ package org.gestouch.gestures
*
* @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html
*/
protected function installTarget(target:InteractiveObject):void
protected function installTarget(targetAdapter:IGestureTargetAdapter):void
{
if (target)
if (targetAdapter)
{
_gesturesManager.gestouch_internal::addGesture(this);
}
@ -326,9 +325,9 @@ package org.gestouch.gestures
*
* @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html
*/
protected function uninstallTarget(target:InteractiveObject):void
protected function uninstallTarget(targetAdapter:IGestureTargetAdapter):void
{
if (target)
if (targetAdapter)
{
_gesturesManager.gestouch_internal::removeGesture(this);
}

View file

@ -1,10 +1,10 @@
package org.gestouch.gestures
{
import org.gestouch.core.GestureState;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.Touch;
import org.gestouch.events.LongPressGestureEvent;
import flash.display.InteractiveObject;
import flash.events.TimerEvent;
import flash.utils.Timer;
@ -30,7 +30,7 @@ package org.gestouch.gestures
protected var _numTouchesRequiredReached:Boolean;
public function LongPressGesture(target:InteractiveObject = null)
public function LongPressGesture(target:IGestureTargetAdapter = null)
{
super(target);
}

View file

@ -1,10 +1,10 @@
package org.gestouch.gestures
{
import org.gestouch.core.GestureState;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.Touch;
import org.gestouch.events.PanGestureEvent;
import flash.display.InteractiveObject;
import flash.geom.Point;
[Event(name="gesturePan", type="org.gestouch.events.PanGestureEvent")]
@ -27,7 +27,7 @@ package org.gestouch.gestures
protected var _gestureBeginOffsetY:Number;
public function PanGesture(target:InteractiveObject = null)
public function PanGesture(target:IGestureTargetAdapter = null)
{
super(target);
}

View file

@ -1,11 +1,11 @@
package org.gestouch.gestures
{
import org.gestouch.core.GestureState;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.Touch;
import org.gestouch.events.RotateGestureEvent;
import org.gestouch.utils.GestureUtils;
import flash.display.InteractiveObject;
import flash.geom.Point;
[Event(name="gestureRotate", type="org.gestouch.events.RotateGestureEvent")]
@ -24,7 +24,7 @@ package org.gestouch.gestures
protected var _transformVector:Point;
public function RotateGesture(target:InteractiveObject = null)
public function RotateGesture(target:IGestureTargetAdapter = null)
{
super(target);
}

View file

@ -1,10 +1,10 @@
package org.gestouch.gestures
{
import org.gestouch.core.GestureState;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.Touch;
import org.gestouch.events.SwipeGestureEvent;
import flash.display.InteractiveObject;
import flash.geom.Point;
[Event(name="gestureSwipe", type="org.gestouch.events.SwipeGestureEvent")]
@ -31,7 +31,7 @@ package org.gestouch.gestures
protected var _decelerationCounter:uint = 0;
public function SwipeGesture(target:InteractiveObject = null)
public function SwipeGesture(target:IGestureTargetAdapter = null)
{
super(target);
}

View file

@ -1,10 +1,10 @@
package org.gestouch.gestures
{
import org.gestouch.core.GestureState;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.Touch;
import org.gestouch.events.TapGestureEvent;
import flash.display.InteractiveObject;
import flash.events.TimerEvent;
import flash.utils.Timer;
@ -28,7 +28,7 @@ package org.gestouch.gestures
protected var _tapCounter:uint = 0;
public function TapGesture(target:InteractiveObject = null)
public function TapGesture(target:IGestureTargetAdapter = null)
{
super(target);
}

View file

@ -1,11 +1,11 @@
package org.gestouch.gestures
{
import org.gestouch.core.GestureState;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.Touch;
import org.gestouch.events.TransformGestureEvent;
import org.gestouch.utils.GestureUtils;
import flash.display.InteractiveObject;
import flash.geom.Point;
@ -22,7 +22,7 @@ package org.gestouch.gestures
protected var _transformVector:Point;
public function TransformGesture(target:InteractiveObject = null)
public function TransformGesture(target:IGestureTargetAdapter = null)
{
super(target);
}

View file

@ -1,10 +1,10 @@
package org.gestouch.gestures
{
import org.gestouch.core.GestureState;
import org.gestouch.core.IGestureTargetAdapter;
import org.gestouch.core.Touch;
import org.gestouch.events.ZoomGestureEvent;
import flash.display.InteractiveObject;
import flash.geom.Point;
[Event(name="gestureZoom", type="org.gestouch.events.ZoomGestureEvent")]
@ -24,7 +24,7 @@ package org.gestouch.gestures
protected var _transformVector:Point;
public function ZoomGesture(target:InteractiveObject = null)
public function ZoomGesture(target:IGestureTargetAdapter = null)
{
super(target);
}

View file

@ -1,6 +1,5 @@
package org.gestouch.input
{
import org.gestouch.core.IGesturesManager;
import org.gestouch.core.IInputAdapter;
import org.gestouch.core.ITouchesManager;
@ -11,7 +10,6 @@ package org.gestouch.input
public class AbstractInputAdapter implements IInputAdapter
{
protected var _touchesManager:ITouchesManager;
protected var _gesturesManager:IGesturesManager;
public function AbstractInputAdapter()
@ -29,12 +27,6 @@ package org.gestouch.input
}
public function set gesturesManager(value:IGesturesManager):void
{
_gesturesManager = value;
}
[Abstract]
public function init():void
{

View file

@ -1,14 +1,8 @@
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.geom.Point;
import flash.utils.getTimer;
/**
@ -46,6 +40,8 @@ package org.gestouch.input
_stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, true);
_stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
uninstallStageListeners();
_touchesManager.onInputAdapterDispose(this);
_touchesManager = null;
}
@ -72,23 +68,13 @@ package org.gestouch.input
{
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))
return;
installStageListeners();
_touchesManager.onTouchBegin(this, PRIMARY_TOUCH_POINT_ID, event.stageX, event.stageY, event.target);
var touch:Touch = _touchesManager.createTouch();
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());
_touchesManager.addTouch(touch);
_gesturesManager.gestouch_internal::onTouchBegin(touch);
if (_touchesManager.activeTouchesCount > 0)
{
installStageListeners();
}
}
@ -96,16 +82,8 @@ package org.gestouch.input
{
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))
return;
var touch:Touch = _touchesManager.getTouch(PRIMARY_TOUCH_POINT_ID);
touch.gestouch_internal::updateLocation(event.stageX, event.stageY);
touch.gestouch_internal::setTime(getTimer());
_gesturesManager.gestouch_internal::onTouchMove(touch);
_touchesManager.onTouchMove(this, PRIMARY_TOUCH_POINT_ID, event.stageX, event.stageY);
}
@ -114,18 +92,7 @@ package org.gestouch.input
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))
return;
var touch:Touch = _touchesManager.getTouch(PRIMARY_TOUCH_POINT_ID);
touch.gestouch_internal::updateLocation(event.stageX, event.stageY);
touch.gestouch_internal::setTime(getTimer());
_gesturesManager.gestouch_internal::onTouchEnd(touch);
_touchesManager.removeTouch(touch);
_touchesManager.onTouchEnd(this, PRIMARY_TOUCH_POINT_ID, event.stageX, event.stageY);
if (_touchesManager.activeTouchesCount == 0)
{

View file

@ -1,16 +1,10 @@
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.geom.Point;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
import flash.utils.getTimer;
/**
@ -57,6 +51,8 @@ package org.gestouch.input
_stage.removeEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler, true);
_stage.removeEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler);
uninstallStageListeners();
_touchesManager.onInputAdapterDispose(this);
_touchesManager = null;
}
@ -83,36 +79,13 @@ package org.gestouch.input
{
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))
return;
_touchesManager.onTouchBegin(this, event.touchPointID, event.stageX, event.stageY, event.target);
installStageListeners();
var touch:Touch = _touchesManager.createTouch();
touch.id = event.touchPointID;
touch.target = event.target as InteractiveObject;
touch.gestouch_internal::setLocation(new Point(event.stageX, event.stageY));
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
//TODO: conditional compilation?
if (event.hasOwnProperty("timestamp"))
if (_touchesManager.activeTouchesCount > 0)
{
touch.gestouch_internal::setTime(event["timestamp"]);
touch.gestouch_internal::setBeginTime(event["timestamp"]);
installStageListeners();
}
else
{
touch.gestouch_internal::setTime(getTimer());
touch.gestouch_internal::setBeginTime(getTimer());
}
_touchesManager.addTouch(touch);
_touchesMap[touch.id] = true;
_gesturesManager.gestouch_internal::onTouchBegin(touch);
}
@ -120,27 +93,8 @@ package org.gestouch.input
{
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))
return;
var touch:Touch = _touchesManager.getTouch(event.touchPointID);
touch.gestouch_internal::updateLocation(event.stageX, event.stageY);
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
//TODO: conditional compilation?
if (event.hasOwnProperty("timestamp"))
{
touch.gestouch_internal::setTime(event["timestamp"]);
}
else
{
touch.gestouch_internal::setTime(getTimer());
}
_gesturesManager.gestouch_internal::onTouchMove(touch);
_touchesManager.onTouchMove(this, event.touchPointID, event.stageX, event.stageY);
}
@ -149,30 +103,7 @@ package org.gestouch.input
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))
return;
var touch:Touch = _touchesManager.getTouch(event.touchPointID);
touch.gestouch_internal::updateLocation(event.stageX, event.stageY);
touch.sizeX = event.sizeX;
touch.sizeY = event.sizeY;
touch.pressure = event.pressure;
//TODO: conditional compilation?
if (event.hasOwnProperty("timestamp"))
{
touch.gestouch_internal::setTime(event["timestamp"]);
}
else
{
touch.gestouch_internal::setTime(getTimer());
}
_gesturesManager.gestouch_internal::onTouchEnd(touch);
_touchesManager.removeTouch(touch);
delete _touchesMap[touch.id];
_touchesManager.onTouchEnd(this, event.touchPointID, event.stageX, event.stageY);
if (_touchesManager.activeTouchesCount == 0)
{

View file

@ -1,5 +1,6 @@
package org.gestouch.utils
{
import flash.geom.Point;
import flash.system.Capabilities;
/**
* Set of constants.
@ -24,5 +25,6 @@ package org.gestouch.utils
* Precalculated coefficient Math.PI * 2
*/
public static const PI_DOUBLE:Number = Math.PI * 2;
public static const GLOBAL_ZERO:Point = new Point();
}
}