PageRenderTime 69ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/org/tuio/adapters/MouseTuioAdapter.as

http://tuio-as3.googlecode.com/
ActionScript | 823 lines | 437 code | 98 blank | 288 comment | 85 complexity | d5f882509eef6bb2d0dd1d05c3ab637a MD5 | raw file
  1. package org.tuio.adapters
  2. {
  3. import flash.display.DisplayObject;
  4. import flash.display.DisplayObjectContainer;
  5. import flash.display.InteractiveObject;
  6. import flash.display.NativeMenuItem;
  7. import flash.display.SpreadMethod;
  8. import flash.display.Sprite;
  9. import flash.display.Stage;
  10. import flash.events.ContextMenuEvent;
  11. import flash.events.Event;
  12. import flash.events.KeyboardEvent;
  13. import flash.events.MouseEvent;
  14. import flash.geom.Matrix;
  15. import flash.geom.Point;
  16. import flash.ui.ContextMenu;
  17. import flash.ui.ContextMenuItem;
  18. import flash.utils.Dictionary;
  19. import org.tuio.*;
  20. import org.tuio.debug.*;
  21. import org.tuio.util.DisplayListHelper;
  22. /**
  23. * Listens on MouseEvents, "translates" them to the analog TuioTouchEvents and TuioFiducialEvents and dispatches
  24. * them on <code>DisplayObject</code>s under the mouse pointer.
  25. *
  26. * Additionally, it provides means to simulate multi-touch input with a single mouse.
  27. * By pressing the 'Shift' key a touch can be added permanently. Pressing the 'Ctrl' key
  28. * in Windows or the 'Command' key in Mac OS X while clicking a touch, will add the touch to a group.
  29. * Furthermore, object interaction can be simulated by choosing a fiducial id from the context menu and
  30. * manipulating the debug representation of the fiducial subsequently. It can be dragged around
  31. * or if 'r' is pressed it can be rotated. If 'Shift' is pressed a fiducial will be removed.
  32. *
  33. * A group of touches will be moved around together. To rotate a group of touches, hold
  34. * the 'r' key, while dragging. To move the touches apart from or towards each other (e.g., to perform pinch/scale
  35. * gestures) hold the 's' key while dragging. To make a group disappear after dragging hold the 'Space'
  36. * key while dragging. The latter is handy if you want to test physical properties like inertia of a group of objects.
  37. *
  38. *
  39. * @author Johannes Luderschmidt
  40. *
  41. * @see org.tuio.TuioTouchEvent
  42. * @see org.tuio.TuioFiducialEvent
  43. *
  44. */
  45. public class MouseTuioAdapter extends AbstractTuioAdapter{
  46. private var _clampFiducialRotation:Boolean;
  47. private var stage:Stage;
  48. private var tuioSessionId:uint;
  49. private var touchMoveId:Number;
  50. private var touchMoveSrc:String;
  51. private var movedObject:ITuioDebugObject;
  52. private var shiftKey:Boolean;
  53. private var groups:Dictionary;
  54. private var frameId:uint = 0;
  55. private var lastSentFrameId:Number = 0;
  56. private var lastX:Number;
  57. private var lastY:Number;
  58. private var spaceKey:Boolean;
  59. private var rKey:Boolean;
  60. private var sKey:Boolean;
  61. private var centerOfGroupedTouchesX:Number;
  62. private var centerOfGroupedTouchesY:Number;
  63. private var fiducialX:Number;
  64. private var fiducialY:Number;
  65. private var fiducialContextMenu:ContextMenu;
  66. private const TWO_D_CUR:String = "2Dcur";
  67. private const TWO_D_OBJ:String = "2Dobj";
  68. private var src:String = "_mouse_tuio_adapter_";
  69. /**
  70. * initializes MouseToTouchDispatcher by adding appropriate event listeners to it. Basically, MouseToTouchDispatcher
  71. * listens on mouse events and translates them to touches. However, additionally keyboard listeners are being added
  72. * that listen on keyboard events to control certain actions like rotation of a touches group by holding 'r'.
  73. *
  74. * @param stage
  75. * @param useTuioManager call the add, move and remove functions of the TuioManager instead of simply dispatching TuioTouchEvents. You have to initialize TuioManager before.
  76. * @param useTuioDebug show the touches as debug cursors. You have to initialize TuioDebug before.
  77. *
  78. */
  79. public function MouseTuioAdapter(stage:Stage){
  80. super(this);
  81. this.stage = stage;
  82. enableAdapter();
  83. if (!this._tuioBlobs[this.src]){ this._tuioBlobs[this.src] = [];}
  84. if (!this._tuioCursors[this.src]){ this._tuioCursors[this.src] = [];}
  85. if (!this._tuioObjects[this.src]){ this._tuioObjects[this.src] = [];}
  86. tuioSessionId = 0;
  87. lastX = stage.mouseX;
  88. lastY = stage.mouseY;
  89. groups = new Dictionary(true);
  90. spaceKey = false;
  91. rKey = false;
  92. centerOfGroupedTouchesX = 0;
  93. centerOfGroupedTouchesY = 0;
  94. clampFiducialRotation = true;
  95. //Flash does not have MouseEvent.RIGHT_CLICK
  96. if(MouseEvent.RIGHT_CLICK){
  97. createContextMenu();
  98. }else{
  99. addFlashContextMenu();
  100. }
  101. }
  102. public function enableAdapter():void{
  103. stage.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
  104. stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
  105. stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);
  106. //Flash does not have MouseEvent.RIGHT_CLICK
  107. if(MouseEvent.RIGHT_CLICK){
  108. stage.addEventListener(MouseEvent.RIGHT_CLICK, contextMenuClick);
  109. }else{
  110. addFlashContextMenu();
  111. }
  112. stage.addEventListener(Event.EXIT_FRAME, sendFrameEvent);
  113. }
  114. public function disableAdapter():void{
  115. stage.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
  116. stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDown);
  117. stage.removeEventListener(KeyboardEvent.KEY_UP, keyUp);
  118. //Flash does not have MouseEvent.RIGHT_CLICK
  119. if(MouseEvent.RIGHT_CLICK){
  120. stage.removeEventListener(MouseEvent.RIGHT_CLICK, contextMenuClick);
  121. }else{
  122. removeFlashContextMenu();
  123. }
  124. stage.removeEventListener(Event.EXIT_FRAME, sendFrameEvent);
  125. }
  126. /**
  127. * Causes a Tuio update event to be sent. Is, e.g., used in gesture API.
  128. */
  129. private function sendFrameEvent(event:Event):void{
  130. if(this.frameId != this.lastSentFrameId){
  131. for each(var l:ITuioListener in this.listeners) {
  132. l.newFrame(this.frameId);
  133. }
  134. this.lastSentFrameId = this.frameId;
  135. }
  136. }
  137. /**
  138. * If there is no existing touch
  139. * under the mouse pointer, a new touch will be added. However, if there already is one it will be marked
  140. * for movement and no new touch is being added. Alternatively, if there is a fiducial underneath the mouse
  141. * pointer it will be selected for movement. If the 'Shift' key is pressed and there is an
  142. * existing touch beneath the mouse cursor this touch will be removed. Alternatively, If the 'Shift' key is pressed
  143. * and there is a fiducial underneath the mouse pointer, the fiducial will be removed.
  144. *
  145. * If the 'Ctrl/Command' key is pressed
  146. * the touch will be added to a group (marked by a dot in the center of a touch) if it does not belong to a
  147. * group already. If it does it will be removed from the group.
  148. *
  149. * NOTE: Adding touches permanently does only work if TuioDebug is being used and useTuioDebug is switched on.
  150. *
  151. * @param event
  152. *
  153. */
  154. private function handleMouseDown(event:MouseEvent):void{
  155. var cursorUnderPoint:ITuioDebugCursor = getCursorUnderPointer(event.stageX, event.stageY);
  156. var objectUnderPoint:ITuioDebugObject = getObjectUnderPointer(event.stageX, event.stageY);
  157. if(cursorUnderPoint != null){
  158. startMoveCursor(cursorUnderPoint, event);
  159. }else if(objectUnderPoint != null){
  160. startMoveObject(objectUnderPoint, event);
  161. }else{
  162. //add new mouse pointer
  163. var frameId:uint = this.frameId++;
  164. var tuioCursor:TuioCursor= createTuioCursor(event.stageX, event.stageY, 0, 0, this.tuioSessionId, frameId);
  165. _tuioCursors[this.src].push(tuioCursor);
  166. dispatchAddCursor(tuioCursor);
  167. this.touchMoveId = this.tuioSessionId;
  168. this.touchMoveSrc = this.src;
  169. stage.addEventListener(MouseEvent.MOUSE_MOVE, dispatchTouchMove);
  170. stage.addEventListener(MouseEvent.MOUSE_UP, dispatchTouchUp);
  171. //takes care that the cursor will not be removed on mouse up
  172. this.shiftKey = event.shiftKey;
  173. }
  174. }
  175. //========================================== CONTEXT MENU STUFF ==========================================
  176. /**
  177. *
  178. * creates a context menu with 100 context menu items that allows to choose
  179. * to add a debug fiducial with the fiducialId of the chosen menu item.
  180. */
  181. private function createContextMenu():void{
  182. fiducialContextMenu = new ContextMenu();
  183. for(var i:Number = 0; i < 100; i++){
  184. var item:NativeMenuItem = new NativeMenuItem("Add Fiducial "+i);
  185. fiducialContextMenu.addItem(item);
  186. item.addEventListener(Event.SELECT, contextMenuSelected);
  187. }
  188. }
  189. /**
  190. * shows the context menu
  191. *
  192. * @param event mouse event.
  193. *
  194. */
  195. private function contextMenuClick(event:MouseEvent):void{
  196. this.fiducialX = event.stageX;
  197. this.fiducialY = event.stageY;
  198. fiducialContextMenu.display(stage, this.fiducialX, this.fiducialY);
  199. }
  200. /**
  201. * adds a debug fiducial with the fiducialId of the chosen menu item to the stage.
  202. *
  203. * @param event
  204. *
  205. */
  206. private function contextMenuSelected(event:Event):void{
  207. var itemLabel:String = (event.target as NativeMenuItem).label;
  208. var fiducialId:Number = int(itemLabel.substring(itemLabel.lastIndexOf(" ")+1, itemLabel.length));
  209. dispatchAddFiducial(this.fiducialX, this.fiducialY, fiducialId);
  210. this.tuioSessionId = this.tuioSessionId+1;
  211. }
  212. /**
  213. *
  214. * @param stageX x position of mouse
  215. * @param stageY y position of mouse
  216. * @param fiducialId chosen fiducialId
  217. *
  218. */
  219. private function dispatchAddFiducial(stageX:Number, stageY:Number, fiducialId:uint):void{
  220. var frameId:uint = this.frameId++;
  221. var tuioObject:TuioObject = createTuioObject(fiducialId, stageX,stageY, this.tuioSessionId, 0, frameId);
  222. _tuioObjects[this.src].push(tuioObject);
  223. dispatchAddObject(tuioObject);
  224. }
  225. //========================================== TOUCH STUFF ==========================================
  226. /**
  227. * decides whether a TUIO debug cursor should be removed, added to a cursor group or it should be moved around.
  228. *
  229. * @param cursorUnderPoint TUIO debug cursor under the mouse pointer.
  230. * @param event
  231. *
  232. */
  233. private function startMoveCursor(cursorUnderPoint:ITuioDebugCursor, event:MouseEvent):void{
  234. //update or remove cursor under mouse pointer
  235. if(event.shiftKey){
  236. //remove cursor
  237. if(cursorUnderPoint.source == this.src){
  238. removeCursor(event, cursorUnderPoint.sessionId, cursorUnderPoint.source);
  239. deleteFromGroup(cursorUnderPoint);
  240. }else{
  241. trace("You can only remove touches that you created via mouse clicks.");
  242. }
  243. }else if(event.ctrlKey){
  244. var cursorObject:Object = this.groups[cursorUnderPoint.sessionId];
  245. //add cursor to group
  246. if(cursorObject == null){
  247. //add to group
  248. if(cursorUnderPoint.source == this.src){
  249. addToGroup(cursorUnderPoint);
  250. }else{
  251. trace("You can only add those touches to groups that have been created via mouse clicks.");
  252. }
  253. }else{
  254. //remove from group
  255. (cursorObject.cursor as DisplayObjectContainer).removeChild(cursorObject.markerSprite);
  256. deleteFromGroup(cursorUnderPoint);
  257. }
  258. }else{
  259. //take care that cursor is not removed after mouse up
  260. if(this.groups[this.touchMoveId] == null){
  261. this.shiftKey = true;
  262. }
  263. //move cursor
  264. this.touchMoveId = cursorUnderPoint.sessionId;
  265. this.touchMoveSrc = cursorUnderPoint.source;
  266. //take care that cursor is moved around the middle
  267. this.lastX = stage.mouseX;
  268. this.lastY = stage.mouseY;
  269. stage.addEventListener(MouseEvent.MOUSE_MOVE, dispatchTouchMove);
  270. stage.addEventListener(MouseEvent.MOUSE_UP, dispatchTouchUp);
  271. }
  272. }
  273. /**
  274. *adds a cursor to a group.
  275. *
  276. * @param cursorUnderPoint the cursor that should be added to the group.
  277. *
  278. */
  279. private function addToGroup(cursorUnderPoint:ITuioDebugCursor):void{
  280. var cursorObject:Object = this.groups[cursorUnderPoint.sessionId];
  281. cursorObject = new Object();
  282. cursorObject.cursor = cursorUnderPoint;
  283. var markerSprite:Sprite = new Sprite();
  284. markerSprite.graphics.beginFill(0xff0000);
  285. markerSprite.graphics.drawCircle(0,0,3);
  286. markerSprite.graphics.endFill();
  287. (cursorUnderPoint as DisplayObjectContainer).addChild(markerSprite);
  288. cursorObject.markerSprite = markerSprite;
  289. this.groups[cursorUnderPoint.sessionId] = cursorObject;
  290. }
  291. /**
  292. * deletes a cursor from the group dictionary.
  293. *
  294. * @param cursorUnderPoint the cursor that should be removed from the group.
  295. *
  296. */
  297. private function deleteFromGroup(cursorUnderPoint:ITuioDebugCursor):void{
  298. delete this.groups[cursorUnderPoint.sessionId];
  299. }
  300. /**
  301. * moves a touch or a group of touches (depending if dragged touch is member of a group).
  302. *
  303. * If the 'r' key is pressed and a touch that is member of a group is
  304. * moved around, the group will be rotated around its berycenter. To rotate the touches,
  305. * drag the mouse up and down while 'r' is pressed.
  306. *
  307. * If the 's' key is pressed and a touch that is member of a group is
  308. * moved around, the group will be rotated around its berycenter. To scale the touches,
  309. * drag the mouse left and right while 's' is pressed.
  310. *
  311. * 'r' and 's' can be used in combination.
  312. *
  313. * @param event
  314. *
  315. */
  316. private function dispatchTouchMove(event:MouseEvent):void{
  317. var xDiff:Number = stage.mouseX-this.lastX;
  318. var yDiff:Number = stage.mouseY-this.lastY;
  319. this.lastX = stage.mouseX;
  320. this.lastY = stage.mouseY;
  321. if(this.groups[this.touchMoveId] != null){
  322. var cursorObject:Object;
  323. var cursor:DisplayObjectContainer
  324. var xPos:Number;
  325. var yPos:Number;
  326. var cursorMatrix:Matrix;
  327. //simply move grouped touches if neither 'r' nor 's' key is pressed
  328. if(!this.rKey && !this.sKey){
  329. for each(cursorObject in this.groups){
  330. cursor = cursorObject.cursor as DisplayObjectContainer;
  331. xPos = cursor.x + xDiff;
  332. yPos = cursor.y + yDiff;
  333. moveCursor(xPos, yPos, xDiff, yDiff, cursorObject.cursor.sessionId,cursorObject.cursor.source);
  334. }
  335. }else{
  336. //rotate grouped touches if 'r' key is pressed
  337. for each(cursorObject in this.groups){
  338. cursor = cursorObject.cursor as DisplayObjectContainer;
  339. cursorMatrix = cursor.transform.matrix;
  340. cursorMatrix.translate(-this.centerOfGroupedTouchesX, -this.centerOfGroupedTouchesY);
  341. if(this.rKey){
  342. cursorMatrix.rotate(0.01 * yDiff);
  343. }
  344. if(this.sKey){
  345. var finalScaleFactor:Number = 1;
  346. var scaleFactor:Number = 1;
  347. var i:Number;
  348. var scaleTimes:Number = 0;
  349. if(xDiff > 0){
  350. scaleFactor = 1.01;
  351. scaleTimes = xDiff;
  352. }else if(xDiff < 0){
  353. scaleFactor = 0.99;
  354. scaleTimes = -xDiff;
  355. }
  356. //apply scaling as often as mouse have been moved in x direction since the last frame
  357. for(i = 0; i < scaleTimes; i++){
  358. finalScaleFactor = finalScaleFactor*scaleFactor;
  359. }
  360. cursorMatrix.scale(finalScaleFactor,finalScaleFactor);
  361. }
  362. cursorMatrix.translate(this.centerOfGroupedTouchesX, this.centerOfGroupedTouchesY);
  363. xPos = cursorMatrix.tx;
  364. yPos = cursorMatrix.ty;
  365. moveCursor(xPos, yPos, xDiff, yDiff, cursorObject.cursor.sessionId, cursorObject.cursor.source);
  366. }
  367. }
  368. }else{
  369. //if no touch from group has been selected, simply move single touch
  370. if(this.src == this.touchMoveSrc){
  371. moveCursor(stage.mouseX, stage.mouseY, xDiff, yDiff, this.touchMoveId, this.touchMoveSrc);
  372. }else{
  373. trace("You can only move touches that have been created via mouse clicks.");
  374. }
  375. }
  376. }
  377. /**
  378. * takes care of the touch movement by dispatching an appropriate TuioTouchEvent or using the TuioManager and
  379. * adjusts the display of the touch in TuioDebug.
  380. *
  381. * @param stageX the x coordinate of the touch
  382. * @param stageY the y coordinate of the touch
  383. * @param sessionId the session id of the touch
  384. *
  385. */
  386. private function moveCursor(stageX:Number, stageY:Number, diffX:Number, diffY:Number, sessionId:uint, source:String):void{
  387. var frameId:uint = this.frameId++;
  388. updateTuioCursor(getTuioCursor(sessionId, source), stageX, stageY, diffX, diffY, sessionId, frameId);
  389. dispatchUpdateCursor(getTuioCursor(sessionId, source));
  390. }
  391. /**
  392. * removes the touch that is being dragged around from stage if no key has been pressed.
  393. *
  394. * If the 'Shift' key has been pressed the touch will remain on the stage.
  395. *
  396. * If the 'Ctrl/Command' key has been pressed the touch will remain on stage and will be
  397. * added to a group.
  398. *
  399. * If the 'Space' key is being pressed and a group of touches is being moved around the
  400. * whole group of touches will be removed.
  401. *
  402. * @param event
  403. *
  404. */
  405. private function dispatchTouchUp(event:MouseEvent):void{
  406. if(this.groups[this.touchMoveId] == null){
  407. //keep touch if shift key has been pressed
  408. if(!this.shiftKey && !event.ctrlKey){
  409. removeCursor(event, tuioSessionId, this.src);
  410. }else if(event.ctrlKey){
  411. var cursorUnderPoint:ITuioDebugCursor = getCursorUnderPointer(event.stageX, event.stageY);
  412. addToGroup(cursorUnderPoint);
  413. }
  414. }else{
  415. if(this.spaceKey){
  416. //remove all touches from group if space key is pressed
  417. for each(var cursorObject:Object in this.groups){
  418. var cursor:DisplayObjectContainer = cursorObject.cursor as DisplayObjectContainer;
  419. removeCursor(event, cursorObject.cursor.sessionId,cursorObject.cursor.source);
  420. deleteFromGroup(cursorObject.cursor);
  421. }
  422. }
  423. }
  424. tuioSessionId = tuioSessionId+1;
  425. touchMoveId = tuioSessionId;
  426. lastX = 0;
  427. lastY = 0;
  428. stage.removeEventListener(MouseEvent.MOUSE_MOVE, dispatchTouchMove);
  429. stage.removeEventListener(MouseEvent.MOUSE_UP, dispatchTouchUp);
  430. }
  431. private function deleteTuioCursorFromGlobalList(cursorID:Number):void{
  432. var i:Number = 0;
  433. for each(var tuioCursor:TuioCursor in _tuioCursors[this.src]){
  434. if(tuioCursor.sessionID == cursorID){
  435. _tuioCursors[this.src].splice(i, 1);
  436. }
  437. i = i+1;
  438. }
  439. }
  440. /**
  441. * removes a touch from stage by dispatching an appropriate TuioTouchEvent or using the TuioManager and
  442. * removes the display of the touch in TuioDebug.
  443. *
  444. * @param event
  445. * @param sessionId session id of touch
  446. *
  447. */
  448. private function removeCursor(event:MouseEvent, sessionId:uint, source:String):void{
  449. var frameId:uint = this.frameId++;
  450. dispatchRemoveCursor(getTuioCursor(sessionId,source));
  451. deleteTuioCursorFromGlobalList(sessionId);
  452. }
  453. /**
  454. * returns the touch under the mouse pointer if there is one. Otherwise null will be returned.
  455. * If the mouse pointer is above the red dot of a touch that beloings to a group still the
  456. * touch will be returned.
  457. *
  458. * @param stageX
  459. * @param stageY
  460. * @return the touch under the mouse pointer if there is one. Otherwise null will be returned.
  461. *
  462. */
  463. private function getCursorUnderPointer(stageX:Number, stageY:Number):ITuioDebugCursor{
  464. var cursorUnderPointer:ITuioDebugCursor = null;
  465. var objectsUnderPoint:Array = stage.getObjectsUnderPoint(new Point(stageX, stageY));
  466. if(objectsUnderPoint[objectsUnderPoint.length-1] is ITuioDebugCursor){
  467. cursorUnderPointer = objectsUnderPoint[objectsUnderPoint.length-1];
  468. }else if(objectsUnderPoint.length > 1 && objectsUnderPoint[objectsUnderPoint.length-2] is ITuioDebugCursor){
  469. //if mouse pointer is above marker sprite, return ITuioDebugCursor beneath marker sprite
  470. cursorUnderPointer = objectsUnderPoint[objectsUnderPoint.length-2];
  471. }
  472. return cursorUnderPointer;
  473. }
  474. /**
  475. *
  476. * @param stageX
  477. * @param stageY
  478. * @return
  479. *
  480. */
  481. private function getObjectUnderPointer(stageX:Number, stageY:Number):ITuioDebugObject{
  482. var objectUnderPointer:ITuioDebugObject = null;
  483. var objectsUnderPoint:Array = stage.getObjectsUnderPoint(new Point(stageX, stageY));
  484. if(objectsUnderPoint[objectsUnderPoint.length-1] is ITuioDebugObject){
  485. objectUnderPointer = objectsUnderPoint[objectsUnderPoint.length-1];
  486. }else if(objectsUnderPoint.length > 1 && objectsUnderPoint[objectsUnderPoint.length-2] is ITuioDebugObject){
  487. //if mouse pointer is above marker sprite, return ITuioDebugCursor beneath marker sprite
  488. objectUnderPointer = objectsUnderPoint[objectsUnderPoint.length-2];
  489. }
  490. return objectUnderPointer;
  491. }
  492. /**
  493. * created a TuioCursor instance from the submitted parameters.
  494. *
  495. * @param stageX an x coordinate in global coordinates.
  496. * @param stageY a y coordinate in global coordinates.
  497. * @param touchId the session id of a touch.
  498. *
  499. * @return the TuioCursor.
  500. *
  501. */
  502. private function createTuioCursor(stageX:Number, stageY:Number, diffX:Number, diffY:Number, sessionId:uint, frameId:uint):TuioCursor {
  503. return new TuioCursor(TWO_D_CUR,sessionId,stageX/stage.stageWidth, stageY/stage.stageHeight,0,diffX/stage.stageWidth,diffY/stage.stageHeight,0,0,frameId,this.src);
  504. }
  505. /**
  506. * created a TuioContainer instance from the submitted parameters.
  507. *
  508. * @param stageX an x coordinate in global coordinates.
  509. * @param stageY a y coordinate in global coordinates.
  510. * @param touchId the session id of a touch.
  511. *
  512. * @return the TuioContainer.
  513. *
  514. */
  515. /*private function createTuioContainer(type:String, stageX:Number, stageY:Number, sessionId:uint, frameId:uint):TuioContainer{
  516. return new TuioContainer(type,sessionId,stageX/stage.stageWidth, stageY/stage.stageHeight,0,0,0,0,0,frameId);
  517. }*/
  518. private function updateTuioCursor(tuioCursor:TuioCursor, stageX:Number, stageY:Number, diffX:Number, diffY:Number, sessionId:uint, frameId:uint):void {
  519. tuioCursor.update(stageX/stage.stageWidth, stageY/stage.stageHeight,0,diffX/stage.stageWidth,diffY/stage.stageHeight,0,0,frameId);
  520. }
  521. //========================================== FIDUCIAL STUFF ==========================================
  522. /**
  523. * decides whether a TUIO debug object should be removed or moved around.
  524. *
  525. * @param cursorUnderPoint TUIO debug object under the mouse pointer.
  526. * @param event
  527. *
  528. */
  529. private function startMoveObject(objectUnderPoint:ITuioDebugObject, event:MouseEvent):void{
  530. //update or remove cursor under mouse pointer
  531. if(event.shiftKey){
  532. this.movedObject = objectUnderPoint;
  533. //remove cursor
  534. removeObject(event);
  535. }else{
  536. //move cursor
  537. this.movedObject = objectUnderPoint;
  538. //store start position in order to move object around the point where it has been clicked
  539. this.lastX = stage.mouseX;
  540. this.lastY = stage.mouseY;
  541. stage.addEventListener(MouseEvent.MOUSE_MOVE, dispatchObjectMove);
  542. stage.addEventListener(MouseEvent.MOUSE_UP, dispatchObjectUp);
  543. }
  544. }
  545. /**
  546. * moves a fiducial.
  547. *
  548. * If the 'r' key is being pressed the TUIO object will be rotated.
  549. *
  550. * @param event
  551. *
  552. */
  553. private function dispatchObjectMove(event:MouseEvent):void{
  554. var stageX:Number = (this.movedObject as DisplayObjectContainer).x + stage.mouseX - this.lastX;
  555. var stageY:Number = (this.movedObject as DisplayObjectContainer).y + stage.mouseY - this.lastY;
  556. if(!this.rKey){
  557. if(this.movedObject.source == this.src){
  558. moveObject(stageX, stageY, this.movedObject.sessionId, this.movedObject.fiducialId, this.movedObject.objectRotation);
  559. }else{
  560. trace("You can only move objects that have been created via mouse clicks.");
  561. }
  562. }else{
  563. var rotationVal:Number = this.movedObject.objectRotation + (0.01 * (stage.mouseY-this.lastY));
  564. if(this.clampFiducialRotation){
  565. rotationVal = rotationVal%(2*Math.PI);
  566. }
  567. if(this.movedObject.source == this.src){
  568. moveObject((this.movedObject as DisplayObjectContainer).x,(this.movedObject as DisplayObjectContainer).y, this.movedObject.sessionId, this.movedObject.fiducialId, rotationVal);
  569. }else{
  570. trace("You can only rotate objects that have been created via mouse clicks.");
  571. }
  572. }
  573. this.lastX = stage.mouseX;
  574. this.lastY = stage.mouseY;
  575. }
  576. /**
  577. * takes care of the fiducial movement by dispatching an appropriate FiducialEvent or using the TuioManager and
  578. * the TuioFiducialDispatcher to adjust the display of the fiducial in TuioDebug.
  579. *
  580. * @param stageX the x coordinate of the mouse pointer
  581. * @param stageY the y coordinate of the mouse pointer
  582. * @param sessionId the session id of the fiducial
  583. *
  584. */
  585. private function moveObject(stageX:Number, stageY:Number, sessionId:uint, fiducialId:uint, rotation:Number):void{
  586. var frameId:uint = this.frameId++;
  587. var updateTuioObject:TuioObject = getTuioObject(sessionId, this.src);
  588. updateTuioObject.update(stageX/stage.stageWidth, stageY/stage.stageHeight,0,rotation,0,0,0,0,0,0,0,0,0,0,frameId);
  589. dispatchUpdateObject(updateTuioObject);
  590. }
  591. /**
  592. * Removes the move and up listener for fiducial movement.
  593. *
  594. * @param event
  595. *
  596. */
  597. private function dispatchObjectUp(event:MouseEvent):void{
  598. stage.removeEventListener(MouseEvent.MOUSE_MOVE, dispatchObjectMove);
  599. stage.removeEventListener(MouseEvent.MOUSE_UP, dispatchObjectUp);
  600. }
  601. /**
  602. * removes a fiducial from stage by dispatching an appropriate FiducialEvent and
  603. * removes the display of the fiducial in TuioDebug.
  604. *
  605. * @param event
  606. *
  607. */
  608. private function removeObject(event:MouseEvent):void{
  609. var frameId:uint = this.frameId++;
  610. if(this.movedObject.source == this.src){
  611. dispatchRemoveObject(getTuioObject(this.movedObject.sessionId, this.movedObject.source));
  612. }else{
  613. trace("You can only remove objects that have been created via mouse clicks.");
  614. }
  615. }
  616. private function createTuioObject(fiducialId:Number, stageX:Number, stageY:Number, sessionId:uint, rotation:Number, frameId:uint):TuioObject{
  617. return new TuioObject(TWO_D_OBJ,sessionId,fiducialId, stageX/stage.stageWidth, stageY/stage.stageHeight,0,rotation,0,0,0,0,0,0,0,0,0,0,frameId,this.src);
  618. }
  619. //========================================== KEYBOARD STUFF ==========================================
  620. /**
  621. * if the 'Space' key is being pressed spaceKey is set to true in this instance.
  622. *
  623. * If the 'r' key is being pressed rKey is set to true in this instance and the
  624. * barycentric coordinates of the touch group is being calculated.
  625. *
  626. * @param event
  627. *
  628. */
  629. private function keyDown(event:KeyboardEvent):void{
  630. //if space has been pressed, all touches will be released
  631. if(event.keyCode == 32){//space
  632. this.spaceKey = true;
  633. }
  634. //if 's' or 'r' has been pressed while a grouped touch has been
  635. //clicked, touches will be 's'caled or 'r'otated
  636. if(event.keyCode == 82 || event.keyCode == 83){
  637. if(event.keyCode == 82){//r
  638. //caused by some very odd bug, an error appears when applying the rotation
  639. //if this.rKey is set to true again if it has been already set to true (remove
  640. //if statement and try it out to see what i mean)
  641. if(!this.rKey){
  642. this.rKey = true;
  643. }
  644. }
  645. if(event.keyCode == 83){//s
  646. //the same mentioned above applies to this statement
  647. if(!this.sKey){
  648. this.sKey = true;
  649. }
  650. }
  651. var cursorUnderPoint:ITuioDebugCursor = getCursorUnderPointer(stage.mouseX, stage.mouseY);
  652. if(cursorUnderPoint != null && this.groups[cursorUnderPoint.sessionId] != null){
  653. //rotate around barycenter of touches
  654. var xPos:Number;
  655. var yPos:Number;
  656. var xPositions:Array = [];
  657. var yPositions:Array = [];
  658. var calcCenterPoint:Point = new Point();
  659. var touchAmount:Number = 0;
  660. calcCenterPoint.x = 0;
  661. calcCenterPoint.y = 0;
  662. for each(var cursorObject:Object in this.groups){
  663. var cursor:DisplayObjectContainer = cursorObject.cursor as DisplayObjectContainer;
  664. xPos = cursor.x;
  665. yPos = cursor.y;
  666. xPositions.push(xPos);
  667. yPositions.push(yPos);
  668. calcCenterPoint.x = calcCenterPoint.x + xPos;
  669. calcCenterPoint.y = calcCenterPoint.y + yPos;
  670. touchAmount = touchAmount+1;
  671. }
  672. this.centerOfGroupedTouchesX = calcCenterPoint.x/touchAmount;
  673. this.centerOfGroupedTouchesY = calcCenterPoint.y/touchAmount;
  674. }
  675. }
  676. }
  677. /**
  678. * sets keyboard variables to false.
  679. *
  680. * @param event
  681. *
  682. */
  683. private function keyUp(event:KeyboardEvent):void{
  684. if(event.keyCode == 32){//space
  685. this.spaceKey = false;
  686. }
  687. if(event.keyCode == 82){//r
  688. this.rKey = false;
  689. this.centerOfGroupedTouchesX = 0;
  690. this.centerOfGroupedTouchesY = 0;
  691. }
  692. if(event.keyCode == 83){//s
  693. this.sKey = false;
  694. }
  695. }
  696. //========================================== FLASH CONTEXT MENU STUFF ==========================================
  697. private function addFlashContextMenu():void{
  698. //flash provides a ContextMenu class in flash.ui that enables to use
  699. //the context menu in an swf. however, ContextMenu is not provided
  700. //in the flex sdk and thus not supported by TUIO AS3. so go ahead
  701. //if you want to use flash and implement it yourself like this:
  702. //http://www.republicofcode.com/tutorials/flash/as3contextmenu/
  703. }
  704. private function removeFlashContextMenu():void{
  705. //flash provides a ContextMenu class in flash.ui that enables to use
  706. //the context menu in an swf. however, ContextMenu is not provided
  707. //in the flex sdk and thus not supported by TUIO AS3. so go ahead
  708. //if you want to use flash and implement it yourself like this:
  709. //http://www.republicofcode.com/tutorials/flash/as3contextmenu/
  710. }
  711. public function get clampFiducialRotation():Boolean
  712. {
  713. return _clampFiducialRotation;
  714. }
  715. /**
  716. * clamps the fiducial's rotation value to 360 degrees.
  717. * @param value
  718. *
  719. */
  720. public function set clampFiducialRotation(value:Boolean):void
  721. {
  722. _clampFiducialRotation = value;
  723. }
  724. }
  725. }