1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * @constant 29 * @type Number 30 */ 31 cc.TouchSelectorBeganBit = 1 << 0; 32 33 /** 34 * @constant 35 * @type Number 36 */ 37 cc.TouchSelectorMovedBit = 1 << 1; 38 39 /** 40 * @constant 41 * @type Number 42 */ 43 cc.TouchSelectorEndedBit = 1 << 2; 44 45 /** 46 * @constant 47 * @type Number 48 */ 49 cc.TouchSelectorCancelledBit = 1 << 3; 50 51 /** 52 * @constant 53 * @type Number 54 */ 55 cc.TouchSelectorAllBits = (cc.TouchSelectorBeganBit | cc.TouchSelectorMovedBit | cc.TouchSelectorEndedBit | cc.TouchSelectorCancelledBit); 56 57 /** 58 * @constant 59 * @type Number 60 */ 61 cc.TOUCH_BEGAN = 0; 62 63 /** 64 * @constant 65 * @type Number 66 */ 67 cc.TOUCH_MOVED = 1; 68 69 /** 70 * @constant 71 * @type Number 72 */ 73 cc.TOUCH_ENDED = 2; 74 75 /** 76 * @constant 77 * @type Number 78 */ 79 cc.TOUCH_CANCELLED = 3; 80 81 /** 82 * @constant 83 * @type Number 84 */ 85 cc.TouchMax = 4; 86 87 /** 88 * @function 89 * @param {cc.TouchHandler} p1 90 * @param {cc.TouchHandler} p2 91 * @return {Boolean} 92 */ 93 cc.less = function (p1, p2) { 94 return p1.getPriority() > p2.getPriority(); 95 }; 96 97 /** 98 * @param {Number} type 99 * Constructor 100 */ 101 cc.TouchHandlerHelperData = function (type) { 102 // we only use the type 103 this.type = type; 104 }; 105 106 /** 107 * cc.TouchDispatcher. 108 * Singleton that handles all the touch events. 109 * The dispatcher dispatches events to the registered TouchHandlers. 110 * There are 2 different type of touch handlers: 111 * - Standard Touch Handlers 112 * - Targeted Touch Handlers 113 * 114 * The Standard Touch Handlers work like the CocoaTouch touch handler: a set of touches is passed to the delegate. 115 * On the other hand, the Targeted Touch Handlers only receive 1 touch at the time, and they can "swallow" touches (avoid the propagation of the event). 116 * 117 * Firstly, the dispatcher sends the received touches to the targeted touches. 118 * These touches can be swallowed by the Targeted Touch Handlers. If there are still remaining touches, then the remaining touches will be sent 119 * to the Standard Touch Handlers. 120 * @class 121 * @extends cc.Class 122 */ 123 cc.TouchDispatcher = cc.Class.extend(/** @lends cc.TouchDispatcher# */ { 124 _mousePressed:false, 125 _targetedHandlers:null, 126 _standardHandlers:null, 127 _locked:false, 128 _toAdd:false, 129 _toRemove:false, 130 _handlersToAdd:null, 131 _handlersToRemove:null, 132 _toQuit:false, 133 _dispatchEvents:false, 134 _handlerHelperData:[new cc.TouchHandlerHelperData(cc.TOUCH_BEGAN), new cc.TouchHandlerHelperData(cc.TOUCH_MOVED), new cc.TouchHandlerHelperData(cc.TOUCH_ENDED), new cc.TouchHandlerHelperData(cc.TOUCH_CANCELLED)], 135 136 /** 137 * @return {Boolean} 138 */ 139 init:function () { 140 this._dispatchEvents = true; 141 this._targetedHandlers = []; 142 this._standardHandlers = []; 143 this._handlersToAdd = []; 144 this._handlersToRemove = []; 145 this._toRemove = false; 146 this._toAdd = false; 147 this._toQuit = false; 148 this._locked = false; 149 this._mousePressed = false; 150 cc.TouchDispatcher.registerHtmlElementEvent(cc.canvas); 151 return true; 152 }, 153 154 _setMousePressed:function (pressed) { 155 this._mousePressed = pressed; 156 }, 157 158 _getMousePressed:function () { 159 return this._mousePressed; 160 }, 161 162 /** 163 * Whether or not the events are going to be dispatched. Default: true 164 * @return {Boolean} 165 */ 166 isDispatchEvents:function () { 167 return this._dispatchEvents; 168 }, 169 170 /** 171 * @param {Boolean} dispatchEvents 172 */ 173 setDispatchEvents:function (dispatchEvents) { 174 this._dispatchEvents = dispatchEvents; 175 }, 176 177 /** 178 * Adds a standard touch delegate to the dispatcher's list. 179 * See StandardTouchDelegate description. 180 * IMPORTANT: The delegate will be retained. 181 * @param {Object} delegate 182 * @param {Number} [priority=0] 183 */ 184 _addStandardDelegate:function (delegate, priority) { 185 priority = priority || 0; 186 var handler = cc.StandardTouchHandler.create(delegate, priority); 187 188 if (!this._locked) { 189 this._standardHandlers = this.forceAddHandler(handler, this._standardHandlers); 190 } else { 191 /* If handler is contained in m_pHandlersToRemove, if so remove it from m_pHandlersToRemove and retrun. 192 * Refer issue #752(cocos2d-x) 193 */ 194 if (this._handlersToRemove.indexOf(delegate) != -1) { 195 cc.ArrayRemoveObject(this._handlersToRemove, delegate); 196 return; 197 } 198 199 this._handlersToAdd.push(handler); 200 this._toAdd = true; 201 } 202 }, 203 204 /** 205 * @param {Object} delegate 206 * @param {Number} priority 207 * @param {Boolean} swallowsTouches 208 */ 209 _addTargetedDelegate:function (delegate, priority, swallowsTouches) { 210 var handler = cc.TargetedTouchHandler.create(delegate, priority, swallowsTouches); 211 if (!this._locked) { 212 this._targetedHandlers = this.forceAddHandler(handler, this._targetedHandlers); 213 } else { 214 /* If handler is contained in m_pHandlersToRemove, if so remove it from m_pHandlersToRemove and retrun. 215 * Refer issue #752(cocos2d-x) 216 */ 217 if (this._handlersToRemove.indexOf(delegate) != -1) { 218 cc.ArrayRemoveObject(this._handlersToRemove, delegate); 219 return; 220 } 221 222 this._handlersToAdd.push(handler); 223 this._toAdd = true; 224 } 225 }, 226 227 /** 228 * Force add handler 229 * @param {cc.TouchHandler} handler 230 * @param {Array} array 231 * @return {Array} 232 */ 233 forceAddHandler:function (handler, array) { 234 var u = 0, h; 235 236 for (var i = 0; i < array.length; i++) { 237 h = array[i]; 238 if (h) { 239 if (h.getPriority() < handler.getPriority()) 240 ++u; 241 if (h.getDelegate() == handler.getDelegate()) { 242 cc.log("cc.TouchDispatcher.forceAddHandler(): The handler has been added."); 243 return array; 244 } 245 } 246 } 247 return cc.ArrayAppendObjectToIndex(array, handler, u); 248 }, 249 250 /** 251 * Force remove all delegates 252 */ 253 forceRemoveAllDelegates:function () { 254 this._standardHandlers.length = 0; 255 this._targetedHandlers.length = 0; 256 }, 257 258 /** 259 * Removes a touch delegate. 260 * The delegate will be released 261 * @param {cc.TouchDelegate} delegate 262 */ 263 _removeDelegate:function (delegate) { 264 if (delegate == null) { 265 return; 266 } 267 268 if (!this._locked) { 269 this.forceRemoveDelegate(delegate); 270 } else { 271 /* 272 * If handler is contained in m_pHandlersToAdd, if so remove it from m_pHandlersToAdd and return. 273 */ 274 var handler = this.findHandler(this._handlersToAdd, delegate); 275 if (handler) { 276 cc.ArrayRemoveObject(this._handlersToAdd, handler); 277 return; 278 } 279 280 this._handlersToRemove.push(delegate); 281 this._toRemove = true; 282 } 283 }, 284 285 /** 286 * Removes all touch delegates, releasing all the delegates 287 */ 288 removeAllDelegates:function () { 289 if (!this._locked) { 290 this.forceRemoveAllDelegates(); 291 } else { 292 this._toQuit = true; 293 } 294 }, 295 296 /** 297 * Changes the priority of a previously added delegate. The lower the number, the higher the priority 298 * @param {Number} priority 299 * @param {cc.TouchDelegate} delegate 300 */ 301 setPriority:function (priority, delegate) { 302 if(!delegate) 303 throw "cc.TouchDispatcher.setPriority(): delegate should be non-null."; 304 var handler = this.findHandler(delegate); 305 if(!handler){ 306 cc.log("cc.TouchDispatcher.setPriority(): Can't find TouchHandler."); 307 return; 308 } 309 310 if (handler.getPriority() != priority) { 311 handler.setPriority(priority); 312 this.rearrangeHandlers(this._targetedHandlers); 313 this.rearrangeHandlers(this._standardHandlers); 314 } 315 }, 316 317 /** 318 * @param {Array} touches 319 * @param {event} event 320 * @param {Number} index 321 */ 322 touches:function (touches, event, index) { 323 if(index< 0 || index >=4) 324 throw "cc.TouchDispatcher.touches(): invalid index"; 325 326 this._locked = true; 327 328 // optimization to prevent a mutable copy when it is not necessary 329 var targetedHandlersCount = this._targetedHandlers.length; 330 var standardHandlersCount = this._standardHandlers.length; 331 var needsMutableSet = (targetedHandlersCount && standardHandlersCount); 332 333 var mutableTouches = (needsMutableSet ? touches.slice() : touches); 334 var helper = this._handlerHelperData[index]; 335 // 336 // process the target handlers 1st 337 // 338 if (targetedHandlersCount > 0) { 339 var touch, handler, claimed; 340 for (var i = 0; i < touches.length; i++) { 341 touch = touches[i]; 342 343 for (var j = 0; j < this._targetedHandlers.length; j++) { 344 handler = this._targetedHandlers[j]; 345 346 if (!handler) { 347 break; 348 } 349 350 claimed = false; 351 if (index == cc.TOUCH_BEGAN) { 352 if (handler.getDelegate().onTouchBegan) { 353 claimed = handler.getDelegate().onTouchBegan(touch, event); 354 355 if (claimed) { 356 handler.getClaimedTouches().push(touch); 357 } 358 } 359 //} else if (handler.getClaimedTouches().indexOf(touch)> -1){ 360 } else if (handler.getClaimedTouches().length > 0) { 361 // moved ended cancelled 362 claimed = true; 363 switch (helper.type) { 364 case cc.TOUCH_MOVED: 365 if (cc.Browser.isMobile) { 366 if (handler.getDelegate().onTouchMoved) handler.getDelegate().onTouchMoved(touch, event); 367 } else { 368 if (this._mousePressed && handler.getDelegate().onTouchMoved) handler.getDelegate().onTouchMoved(touch, event); 369 } 370 break; 371 case cc.TOUCH_ENDED: 372 if (handler.getDelegate().onTouchEnded) handler.getDelegate().onTouchEnded(touch, event); 373 handler.getClaimedTouches().length = 0; 374 //cc.ArrayRemoveObject(handler.getClaimedTouches(),touch); 375 break; 376 case cc.TOUCH_CANCELLED: 377 if (handler.getDelegate().onTouchCancelled) handler.getDelegate().onTouchCancelled(touch, event); 378 handler.getClaimedTouches().length = 0; 379 //cc.ArrayRemoveObject(handler.getClaimedTouches(),touch); 380 break; 381 } 382 } 383 384 if (claimed && handler.isSwallowsTouches()) { 385 if (needsMutableSet) { 386 cc.ArrayRemoveObject(mutableTouches, touch); 387 } 388 break; 389 } 390 } 391 } 392 } 393 394 // 395 // process standard handlers 2nd 396 // 397 if (standardHandlersCount > 0) { 398 for (i = 0; i < this._standardHandlers.length; i++) { 399 handler = this._standardHandlers[i]; 400 401 if (!handler) { 402 break; 403 } 404 405 switch (helper.type) { 406 case cc.TOUCH_BEGAN: 407 if (mutableTouches.length > 0) { 408 if (handler.getDelegate().onTouchesBegan) handler.getDelegate().onTouchesBegan(mutableTouches, event); 409 } 410 break; 411 case cc.TOUCH_MOVED: 412 if (mutableTouches.length > 0) { 413 if (cc.Browser.isMobile) { 414 if (handler.getDelegate().onTouchesMoved) handler.getDelegate().onTouchesMoved(mutableTouches, event); 415 } else { 416 if (this._mousePressed && handler.getDelegate().onTouchesMoved) handler.getDelegate().onTouchesMoved(mutableTouches, event); 417 } 418 } 419 break; 420 case cc.TOUCH_ENDED: 421 if (handler.getDelegate().onTouchesEnded) handler.getDelegate().onTouchesEnded(mutableTouches, event); 422 break; 423 case cc.TOUCH_CANCELLED: 424 if (handler.getDelegate().onTouchesCancelled) handler.getDelegate().onTouchesCancelled(mutableTouches, event); 425 break; 426 } 427 } 428 } 429 430 if (needsMutableSet) { 431 mutableTouches = null; 432 } 433 434 // 435 // Optimization. To prevent a [handlers copy] which is expensive 436 // the add/removes/quit is done after the iterations 437 // 438 this._locked = false; 439 if (this._toRemove) { 440 this._toRemove = false; 441 for (i = 0; i < this._handlersToRemove.length; i++) { 442 this.forceRemoveDelegate(this._handlersToRemove[i]); 443 } 444 this._handlersToRemove.length = 0; 445 } 446 447 if (this._toAdd) { 448 this._toAdd = false; 449 450 for (i = 0; i < this._handlersToAdd.length; i++) { 451 handler = this._handlersToAdd[i]; 452 if (!handler) { 453 break; 454 } 455 456 if (handler instanceof cc.TargetedTouchHandler) { 457 this._targetedHandlers = this.forceAddHandler(handler, this._targetedHandlers); 458 } else { 459 this._standardHandlers = this.forceAddHandler(handler, this._standardHandlers); 460 } 461 } 462 this._handlersToAdd.length = 0; 463 } 464 465 if (this._toQuit) { 466 this._toQuit = false; 467 this.forceRemoveAllDelegates(); 468 } 469 }, 470 471 /** 472 * @param {Array} touches 473 * @param {event} event 474 */ 475 touchesBegan:function (touches, event) { 476 if (this._dispatchEvents) { 477 this.touches(touches, event, cc.TOUCH_BEGAN); 478 } 479 }, 480 481 /** 482 * @param {Array} touches 483 * @param {event} event 484 */ 485 touchesMoved:function (touches, event) { 486 if (this._dispatchEvents) { 487 this.touches(touches, event, cc.TOUCH_MOVED); 488 } 489 }, 490 491 /** 492 * @param {Array} touches 493 * @param {event} event 494 */ 495 touchesEnded:function (touches, event) { 496 if (this._dispatchEvents) { 497 this.touches(touches, event, cc.TOUCH_ENDED); 498 } 499 }, 500 501 /** 502 * @param {Array} touches 503 * @param {event} event 504 */ 505 touchesCancelled:function (touches, event) { 506 if (this._dispatchEvents) { 507 this.touches(touches, event, cc.TOUCH_CANCELLED); 508 } 509 }, 510 511 /** 512 * @param {Array||cc.TouchDelegate} array array or delegate 513 * @param {cc.TouchDelegate} delegate 514 * @return {cc.TargetedTouchHandler|cc.StandardTouchHandler|Null} 515 */ 516 findHandler:function (array, delegate) { 517 switch (arguments.length) { 518 case 1: 519 delegate = arguments[0]; 520 if(!delegate) 521 throw "cc.TouchDispatcher.findHandler(): delegate should be non-null."; 522 for (var i = 0; i < this._targetedHandlers.length; i++) { 523 if (this._targetedHandlers[i].getDelegate() == delegate) { 524 return this._targetedHandlers[i]; 525 } 526 } 527 for (i = 0; i < this._standardHandlers.length; i++) { 528 if (this._standardHandlers[i].getDelegate() == delegate) { 529 return this._standardHandlers[i]; 530 } 531 } 532 return null; 533 break; 534 case 2: 535 if(!array) 536 throw "cc.TouchDispatcher.findHandler(): array should be non-null."; 537 if(!delegate) 538 throw "cc.TouchDispatcher.findHandler(): delegate should be non-null."; 539 540 for (i = 0; i < array.length; i++) { 541 if (array[i].getDelegate() == delegate) { 542 return array[i]; 543 } 544 } 545 546 return null; 547 break; 548 default: 549 throw "Argument must be non-nil "; 550 break; 551 } 552 }, 553 554 /** 555 * @param {cc.TouchDelegate} delegate 556 */ 557 forceRemoveDelegate:function (delegate) { 558 var handler; 559 // XXX: remove it from both handlers ??? 560 // remove handler from m_pStandardHandlers 561 for (var i = 0; i < this._standardHandlers.length; i++) { 562 handler = this._standardHandlers[i]; 563 if (handler && handler.getDelegate() == delegate) { 564 cc.ArrayRemoveObject(this._standardHandlers, handler); 565 break; 566 } 567 } 568 569 for (i = 0; i < this._targetedHandlers.length; i++) { 570 handler = this._targetedHandlers[i]; 571 if (handler && handler.getDelegate() == delegate) { 572 cc.ArrayRemoveObject(this._targetedHandlers, handler); 573 break; 574 } 575 } 576 }, 577 578 /** 579 * @param {Array} array 580 */ 581 rearrangeHandlers:function (array) { 582 array.sort(cc.less); 583 } 584 }); 585 586 /** 587 * @type {cc.Point} 588 */ 589 cc.TouchDispatcher.preTouchPoint = cc.p(0, 0); 590 591 cc.TouchDispatcher.isRegisterEvent = false; 592 593 cc.getHTMLElementPosition = function (element) { 594 var docElem = document.documentElement; 595 var win = window; 596 var box = null; 597 if (typeof element.getBoundingClientRect === 'function') { 598 box = element.getBoundingClientRect(); 599 } else { 600 if (element instanceof HTMLCanvasElement) { 601 box = { 602 left:0, 603 top:0, 604 width:element.width, 605 height:element.height 606 }; 607 } else { 608 box = { 609 left:0, 610 top:0, 611 width:parseInt(element.style.width), 612 height:parseInt(element.style.height) 613 }; 614 } 615 } 616 return { 617 left:box.left + win.pageXOffset - docElem.clientLeft, 618 top:box.top + win.pageYOffset - docElem.clientTop, 619 width:box.width, 620 height:box.height 621 }; 622 }; 623 624 cc.ProcessMouseupEvent = function (element, event) { 625 var pos = cc.getHTMLElementPosition(element); 626 627 var tx, ty; 628 if (event.pageX != null) { //not avalable in <= IE8 629 tx = event.pageX; 630 ty = event.pageY; 631 } else { 632 pos.left -= document.body.scrollLeft; 633 pos.top -= document.body.scrollTop; 634 tx = event.clientX; 635 ty = event.clientY; 636 } 637 638 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 639 640 var touch = new cc.Touch(location.x, location.y); 641 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 642 cc.TouchDispatcher.preTouchPoint.x = location.x; 643 cc.TouchDispatcher.preTouchPoint.y = location.y; 644 645 var posArr = []; 646 posArr.push(touch); 647 //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null); 648 cc.EGLView.getInstance().touchesEnded(posArr, null); 649 }; 650 651 /** 652 * @param {HTMLCanvasElement|HTMLDivElement} element 653 */ 654 cc.TouchDispatcher.registerHtmlElementEvent = function (element) { 655 if (cc.TouchDispatcher.isRegisterEvent) return; 656 657 if (!cc.Browser.isMobile) { 658 window.addEventListener('mousedown', function (event) { 659 cc.Director.getInstance().getTouchDispatcher()._setMousePressed(true); 660 }); 661 662 window.addEventListener('mouseup', function (event) { 663 cc.Director.getInstance().getTouchDispatcher()._setMousePressed(false); 664 665 var pos = cc.getHTMLElementPosition(element); 666 667 var tx, ty; 668 if (event.pageX != null) { //not avalable in <= IE8 669 tx = event.pageX; 670 ty = event.pageY; 671 } else { 672 pos.left -= document.body.scrollLeft; 673 pos.top -= document.body.scrollTop; 674 tx = event.clientX; 675 ty = event.clientY; 676 } 677 678 if (!cc.rectContainsPoint(new cc.Rect(pos.left, pos.top, pos.width, pos.height), cc.p(tx, ty))) { 679 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 680 var touch = new cc.Touch(location.x, location.y); 681 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 682 cc.TouchDispatcher.preTouchPoint.x = location.x; 683 cc.TouchDispatcher.preTouchPoint.y = location.y; 684 685 var posArr = []; 686 posArr.push(touch); 687 //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null); 688 cc.EGLView.getInstance().touchesEnded(posArr, null); 689 } 690 }); 691 692 //register canvas mouse event 693 element.addEventListener("mousedown", function (event) { 694 var pos = cc.getHTMLElementPosition(element); 695 696 var tx, ty; 697 if (event.pageX != null) { //not avalable in <= IE8 698 tx = event.pageX; 699 ty = event.pageY; 700 } else { 701 pos.left -= document.body.scrollLeft; 702 pos.top -= document.body.scrollTop; 703 tx = event.clientX; 704 ty = event.clientY; 705 } 706 707 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 708 var touch = new cc.Touch(location.x, location.y); 709 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 710 cc.TouchDispatcher.preTouchPoint.x = location.x; 711 cc.TouchDispatcher.preTouchPoint.y = location.y; 712 713 var posArr = []; 714 posArr.push(touch); 715 //csx cc.Director.getInstance().getTouchDispatcher().touchesBegan(posArr, null); 716 cc.EGLView.getInstance().touchesBegan(posArr, null); 717 }); 718 719 element.addEventListener("mouseup", function (event) { 720 cc.ProcessMouseupEvent(element, event); 721 }); 722 723 element.addEventListener("mousemove", function (event) { 724 var pos = cc.getHTMLElementPosition(element); 725 726 var tx, ty; 727 if (event.pageX != null) { //not avalable in <= IE8 728 tx = event.pageX; 729 ty = event.pageY; 730 } else { 731 pos.left -= document.body.scrollLeft; 732 pos.top -= document.body.scrollTop; 733 tx = event.clientX; 734 ty = event.clientY; 735 } 736 737 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 738 var touch = new cc.Touch(location.x, location.y); 739 //TODO this feature only chrome support 740 //if((event.button == 0) && (event.which == 1)) 741 // touch._setPressed(true); 742 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 743 cc.TouchDispatcher.preTouchPoint.x = location.x; 744 cc.TouchDispatcher.preTouchPoint.y = location.y; 745 746 var posArr = []; 747 posArr.push(touch); 748 749 //csx cc.Director.getInstance().getTouchDispatcher().touchesMoved(posArr, null); 750 cc.EGLView.getInstance().touchesMoved(posArr, null); 751 }); 752 } 753 else if(window.navigator.msPointerEnabled){ 754 var _pointerEventsMap = { 755 "MSPointerDown" : "touchesBegan", 756 "MSPointerMove" : "touchesMoved", 757 "MSPointerUp" : "touchesEnded", 758 "MSPointerCancel" : "touchesCancelled" 759 }; 760 761 for(var i in _pointerEventsMap){ 762 (function(_pointerEvent, _touchEvent){ 763 element.addEventListener(_pointerEvent, function (event){ 764 var pos = cc.getHTMLElementPosition(element); 765 766 pos.left -= document.body.scrollLeft; 767 pos.top -= document.body.scrollTop; 768 769 var tx, ty, touch, preLocation; 770 tx = event.clientX; 771 ty = event.clientY; 772 773 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 774 var touch = new cc.Touch(location.x, location.y); 775 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 776 cc.TouchDispatcher.preTouchPoint.x = location.x; 777 cc.TouchDispatcher.preTouchPoint.y = location.y; 778 779 cc.Director.getInstance().getTouchDispatcher()[_touchEvent]([touch], null); 780 event.stopPropagation(); 781 event.preventDefault(); 782 }, false); 783 })(i, _pointerEventsMap[i]); 784 } 785 } 786 else { 787 788 //register canvas touch event 789 element.addEventListener("touchstart", function (event) { 790 if (!event.changedTouches) return; 791 792 var posArr = []; 793 var pos = cc.getHTMLElementPosition(element); 794 795 pos.left -= document.body.scrollLeft; 796 pos.top -= document.body.scrollTop; 797 798 var touch_event, tx, ty, touch, preLocation; 799 var length = event.changedTouches.length; 800 for (var i = 0; i < length; i++) { 801 touch_event = event.changedTouches[i]; 802 //tx = touch_event.pageX; 803 //ty = touch_event.pageY; 804 if (touch_event) { 805 tx = touch_event.clientX; 806 ty = touch_event.clientY; 807 808 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 809 touch = null; 810 if (touch_event.hasOwnProperty("identifier")) { 811 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 812 //use Touch Pool 813 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 814 touch._setPrevPoint(preLocation.x, preLocation.y); 815 cc.TouchDispatcher._setPreTouch(touch); 816 } else { 817 touch = new cc.Touch(location.x, location.y); 818 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 819 } 820 cc.TouchDispatcher.preTouchPoint.x = location.x; 821 cc.TouchDispatcher.preTouchPoint.y = location.y; 822 823 posArr.push(touch); 824 } 825 } 826 //csx cc.Director.getInstance().getTouchDispatcher().touchesBegan(posArr, null); 827 cc.EGLView.getInstance().touchesBegan(posArr, null); 828 event.stopPropagation(); 829 event.preventDefault(); 830 }, false); 831 832 element.addEventListener("touchmove", function (event) { 833 if (!event.changedTouches) return; 834 835 var posArr = []; 836 var pos = cc.getHTMLElementPosition(element); 837 838 pos.left -= document.body.scrollLeft; 839 pos.top -= document.body.scrollTop; 840 841 var touch_event, tx, ty, touch, preLocation; 842 var length = event.changedTouches.length; 843 for (var i = 0; i < length; i++) { 844 touch_event = event.changedTouches[i]; 845 //tx = touch_event.pageX; 846 //ty = touch_event.pageY; 847 if (touch_event) { 848 tx = touch_event.clientX; 849 ty = touch_event.clientY; 850 851 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 852 853 touch = null; 854 if (touch_event.hasOwnProperty("identifier")) { 855 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 856 //use Touch Pool 857 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 858 touch._setPrevPoint(preLocation.x, preLocation.y); 859 cc.TouchDispatcher._setPreTouch(touch); 860 } else { 861 touch = new cc.Touch(location.x, location.y); 862 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 863 } 864 cc.TouchDispatcher.preTouchPoint.x = location.x; 865 cc.TouchDispatcher.preTouchPoint.y = location.y; 866 867 posArr.push(touch); 868 } 869 } 870 //csx cc.Director.getInstance().getTouchDispatcher().touchesMoved(posArr, null); 871 cc.EGLView.getInstance().touchesMoved(posArr, null); 872 event.stopPropagation(); 873 event.preventDefault(); 874 }, false); 875 876 element.addEventListener("touchend", function (event) { 877 if (!event.changedTouches) return; 878 879 var posArr = []; 880 var pos = cc.getHTMLElementPosition(element); 881 882 pos.left -= document.body.scrollLeft; 883 pos.top -= document.body.scrollTop; 884 885 var touch_event, tx, ty, touch, preLocation; 886 var length = event.changedTouches.length; 887 for (var i = 0; i < length; i++) { 888 touch_event = event.changedTouches[i]; 889 //tx = touch_event.pageX; 890 //ty = touch_event.pageY; 891 if (touch_event) { 892 tx = touch_event.clientX; 893 ty = touch_event.clientY; 894 895 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 896 897 touch = null; 898 if (touch_event.hasOwnProperty("identifier")) { 899 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 900 //use Touch Pool 901 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 902 touch._setPrevPoint(preLocation.x, preLocation.y); 903 cc.TouchDispatcher._deletePreTouchWithSameId(touch); 904 } else { 905 touch = new cc.Touch(location.x, location.y); 906 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 907 } 908 cc.TouchDispatcher.preTouchPoint.x = location.x; 909 cc.TouchDispatcher.preTouchPoint.y = location.y; 910 911 posArr.push(touch); 912 } 913 } 914 //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null); 915 cc.EGLView.getInstance().touchesEnded(posArr, null); 916 event.stopPropagation(); 917 event.preventDefault(); 918 }, false); 919 920 element.addEventListener("touchcancel", function (event) { 921 if (!event.changedTouches) return; 922 923 var posArr = []; 924 var pos = cc.getHTMLElementPosition(element); 925 926 pos.left -= document.body.scrollLeft; 927 pos.top -= document.body.scrollTop; 928 929 var touch_event, tx, ty, touch, preLocation; 930 var length = event.changedTouches.length; 931 for (var i = 0; i < length; i++) { 932 touch_event = event.changedTouches[i]; 933 //tx = touch_event.pageX; 934 //ty = touch_event.pageY; 935 if (touch_event) { 936 tx = touch_event.clientX; 937 ty = touch_event.clientY; 938 939 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 940 941 touch = null; 942 if (touch_event.hasOwnProperty("identifier")) { 943 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 944 //use Touch Pool 945 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 946 touch._setPrevPoint(preLocation.x, preLocation.y); 947 cc.TouchDispatcher._deletePreTouchWithSameId(touch); 948 } else { 949 touch = new cc.Touch(location.x, location.y); 950 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 951 } 952 cc.TouchDispatcher.preTouchPoint.x = location.x; 953 cc.TouchDispatcher.preTouchPoint.y = location.y; 954 955 posArr.push(touch); 956 } 957 } 958 //csx cc.Director.getInstance().getTouchDispatcher().touchesCancelled(posArr, null); 959 cc.EGLView.getInstance().touchesCancelled(posArr, null); 960 event.stopPropagation(); 961 event.preventDefault(); 962 }, false); 963 } 964 965 cc.TouchDispatcher.isRegisterEvent = true; 966 }; 967 968 /** 969 * @param {cc.Touch} touch 970 * @return {cc.Touch} preTouch 971 */ 972 cc.TouchDispatcher._getPreTouch = function (touch) { 973 var preTouch = null; 974 var preTouchPool = cc.TouchDispatcher._preTouchPool; 975 var id = touch.getId(); 976 for (var i = preTouchPool.length - 1; i >= 0; i--) { 977 if (preTouchPool[i].getId() == id) { 978 preTouch = preTouchPool[i]; 979 break; 980 } 981 } 982 if (!preTouch) { 983 preTouch = touch; 984 } 985 return preTouch; 986 }; 987 988 /** 989 * @param {cc.Touch} touch 990 */ 991 cc.TouchDispatcher._setPreTouch = function (touch) { 992 var find = false; 993 var preTouchPool = cc.TouchDispatcher._preTouchPool; 994 var id = touch.getId(); 995 for (var i = preTouchPool.length - 1; i >= 0; i--) { 996 if (preTouchPool[i].getId() == id) { 997 preTouchPool[i] = touch; 998 find = true; 999 break; 1000 } 1001 } 1002 if (!find) { 1003 //debug touches{ 1004 //cc.log("Pool.length: " + preTouchPool.length); 1005 //} 1006 if (preTouchPool.length <= 50) { 1007 preTouchPool.push(touch); 1008 } else { 1009 preTouchPool[cc.TouchDispatcher._preTouchPoolPointer] = touch; 1010 cc.TouchDispatcher._preTouchPoolPointer = (cc.TouchDispatcher._preTouchPoolPointer + 1) % 50; 1011 } 1012 } 1013 }; 1014 1015 /** 1016 * @param {cc.Touch} touch 1017 */ 1018 cc.TouchDispatcher._deletePreTouchWithSameId = function (touch) { 1019 var changeTouch; 1020 var preTouchPool = cc.TouchDispatcher._preTouchPool; 1021 var id = touch.getId(); 1022 for (var i = preTouchPool.length - 1; i >= 0; i--) { 1023 if (preTouchPool[i].getId() == id) { 1024 changeTouch = preTouchPool.pop(); 1025 if (i != preTouchPool.length) { 1026 preTouchPool[i] = changeTouch; 1027 } 1028 break; 1029 } 1030 } 1031 }; 1032 1033 /** 1034 * @type {Array} 1035 */ 1036 cc.TouchDispatcher._preTouchPool = []; 1037 1038 /** 1039 * @type {Number} 1040 */ 1041 cc.TouchDispatcher._preTouchPoolPointer = 0; 1042 1043 /** 1044 * register a targeted touch delegate to the dispatcher's list. 1045 * @param {Number} priority 1046 * @param {Boolean} swallowsTouches 1047 * @param {Object} delegate 1048 */ 1049 cc.registerTargetedDelegate = function(priority, swallowsTouches, delegate){ 1050 cc.Director.getInstance().getTouchDispatcher()._addTargetedDelegate(delegate, priority, swallowsTouches); 1051 }; 1052 1053 /** 1054 * Adds a standard touch delegate to the dispatcher's list. 1055 * See StandardTouchDelegate description. 1056 * @param {Object} delegate 1057 * @param {Number} [priority=] 1058 */ 1059 cc.registerStandardDelegate = function(delegate, priority){ 1060 cc.Director.getInstance().getTouchDispatcher()._addStandardDelegate(delegate, priority); 1061 }; 1062 1063 /** 1064 * Removes a touch delegate. from TouchDispatcher 1065 * @param delegate 1066 */ 1067 cc.unregisterTouchDelegate = function(delegate){ 1068 cc.Director.getInstance().getTouchDispatcher()._removeDelegate(delegate); 1069 };