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.Assert(0, "TouchDispatcher.forceAddHandler()"); 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 cc.Assert(delegate != null, "TouchDispatcher.setPriority():Arguments is null"); 303 304 var handler = this.findHandler(delegate); 305 306 cc.Assert(handler != null, "TouchDispatcher.setPriority():Cant find TouchHandler"); 307 308 if (handler.getPriority() != priority) { 309 handler.setPriority(priority); 310 311 this.rearrangeHandlers(this._targetedHandlers); 312 this.rearrangeHandlers(this._standardHandlers); 313 } 314 }, 315 316 /** 317 * @param {Array} touches 318 * @param {event} event 319 * @param {Number} index 320 */ 321 touches:function (touches, event, index) { 322 cc.Assert(index >= 0 && index < 4, "TouchDispatcher.touches()"); 323 324 this._locked = true; 325 326 // optimization to prevent a mutable copy when it is not necessary 327 var targetedHandlersCount = this._targetedHandlers.length; 328 var standardHandlersCount = this._standardHandlers.length; 329 var needsMutableSet = (targetedHandlersCount && standardHandlersCount); 330 331 var mutableTouches = (needsMutableSet ? touches.slice() : touches); 332 var helper = this._handlerHelperData[index]; 333 // 334 // process the target handlers 1st 335 // 336 if (targetedHandlersCount > 0) { 337 var touch, handler, claimed; 338 for (var i = 0; i < touches.length; i++) { 339 touch = touches[i]; 340 341 for (var j = 0; j < this._targetedHandlers.length; j++) { 342 handler = this._targetedHandlers[j]; 343 344 if (!handler) { 345 break; 346 } 347 348 claimed = false; 349 if (index == cc.TOUCH_BEGAN) { 350 if (handler.getDelegate().onTouchBegan) { 351 claimed = handler.getDelegate().onTouchBegan(touch, event); 352 353 if (claimed) { 354 handler.getClaimedTouches().push(touch); 355 } 356 } 357 //} else if (handler.getClaimedTouches().indexOf(touch)> -1){ 358 } else if (handler.getClaimedTouches().length > 0) { 359 // moved ended cancelled 360 claimed = true; 361 switch (helper.type) { 362 case cc.TOUCH_MOVED: 363 if (cc.Browser.isMobile) { 364 if (handler.getDelegate().onTouchMoved) handler.getDelegate().onTouchMoved(touch, event); 365 } else { 366 if (this._mousePressed && handler.getDelegate().onTouchMoved) handler.getDelegate().onTouchMoved(touch, event); 367 } 368 break; 369 case cc.TOUCH_ENDED: 370 if (handler.getDelegate().onTouchEnded) handler.getDelegate().onTouchEnded(touch, event); 371 handler.getClaimedTouches().length = 0; 372 //cc.ArrayRemoveObject(handler.getClaimedTouches(),touch); 373 break; 374 case cc.TOUCH_CANCELLED: 375 if (handler.getDelegate().onTouchCancelled) handler.getDelegate().onTouchCancelled(touch, event); 376 handler.getClaimedTouches().length = 0; 377 //cc.ArrayRemoveObject(handler.getClaimedTouches(),touch); 378 break; 379 } 380 } 381 382 if (claimed && handler.isSwallowsTouches()) { 383 if (needsMutableSet) { 384 cc.ArrayRemoveObject(mutableTouches, touch); 385 } 386 break; 387 } 388 } 389 } 390 } 391 392 // 393 // process standard handlers 2nd 394 // 395 if (standardHandlersCount > 0) { 396 for (i = 0; i < this._standardHandlers.length; i++) { 397 handler = this._standardHandlers[i]; 398 399 if (!handler) { 400 break; 401 } 402 403 switch (helper.type) { 404 case cc.TOUCH_BEGAN: 405 if (mutableTouches.length > 0) { 406 if (handler.getDelegate().onTouchesBegan) handler.getDelegate().onTouchesBegan(mutableTouches, event); 407 } 408 break; 409 case cc.TOUCH_MOVED: 410 if (mutableTouches.length > 0) { 411 if (cc.Browser.isMobile) { 412 if (handler.getDelegate().onTouchesMoved) handler.getDelegate().onTouchesMoved(mutableTouches, event); 413 } else { 414 if (this._mousePressed && handler.getDelegate().onTouchesMoved) handler.getDelegate().onTouchesMoved(mutableTouches, event); 415 } 416 } 417 break; 418 case cc.TOUCH_ENDED: 419 if (handler.getDelegate().onTouchesEnded) handler.getDelegate().onTouchesEnded(mutableTouches, event); 420 break; 421 case cc.TOUCH_CANCELLED: 422 if (handler.getDelegate().onTouchesCancelled) handler.getDelegate().onTouchesCancelled(mutableTouches, event); 423 break; 424 } 425 } 426 } 427 428 if (needsMutableSet) { 429 mutableTouches = null; 430 } 431 432 // 433 // Optimization. To prevent a [handlers copy] which is expensive 434 // the add/removes/quit is done after the iterations 435 // 436 this._locked = false; 437 if (this._toRemove) { 438 this._toRemove = false; 439 for (i = 0; i < this._handlersToRemove.length; i++) { 440 this.forceRemoveDelegate(this._handlersToRemove[i]); 441 } 442 this._handlersToRemove.length = 0; 443 } 444 445 if (this._toAdd) { 446 this._toAdd = false; 447 448 for (i = 0; i < this._handlersToAdd.length; i++) { 449 handler = this._handlersToAdd[i]; 450 if (!handler) { 451 break; 452 } 453 454 if (handler instanceof cc.TargetedTouchHandler) { 455 this._targetedHandlers = this.forceAddHandler(handler, this._targetedHandlers); 456 } else { 457 this._standardHandlers = this.forceAddHandler(handler, this._standardHandlers); 458 } 459 } 460 this._handlersToAdd.length = 0; 461 } 462 463 if (this._toQuit) { 464 this._toQuit = false; 465 this.forceRemoveAllDelegates(); 466 } 467 }, 468 469 /** 470 * @param {Array} touches 471 * @param {event} event 472 */ 473 touchesBegan:function (touches, event) { 474 if (this._dispatchEvents) { 475 this.touches(touches, event, cc.TOUCH_BEGAN); 476 } 477 }, 478 479 /** 480 * @param {Array} touches 481 * @param {event} event 482 */ 483 touchesMoved:function (touches, event) { 484 if (this._dispatchEvents) { 485 this.touches(touches, event, cc.TOUCH_MOVED); 486 } 487 }, 488 489 /** 490 * @param {Array} touches 491 * @param {event} event 492 */ 493 touchesEnded:function (touches, event) { 494 if (this._dispatchEvents) { 495 this.touches(touches, event, cc.TOUCH_ENDED); 496 } 497 }, 498 499 /** 500 * @param {Array} touches 501 * @param {event} event 502 */ 503 touchesCancelled:function (touches, event) { 504 if (this._dispatchEvents) { 505 this.touches(touches, event, cc.TOUCH_CANCELLED); 506 } 507 }, 508 509 /** 510 * @param {Array||cc.TouchDelegate} array array or delegate 511 * @param {cc.TouchDelegate} delegate 512 * @return {cc.TargetedTouchHandler|cc.StandardTouchHandler|Null} 513 */ 514 findHandler:function (array, delegate) { 515 switch (arguments.length) { 516 case 1: 517 delegate = arguments[0]; 518 for (var i = 0; i < this._targetedHandlers.length; i++) { 519 if (this._targetedHandlers[i].getDelegate() == delegate) { 520 return this._targetedHandlers[i]; 521 } 522 } 523 for (i = 0; i < this._standardHandlers.length; i++) { 524 if (this._standardHandlers[i].getDelegate() == delegate) { 525 return this._standardHandlers[i]; 526 } 527 } 528 return null; 529 break; 530 case 2: 531 cc.Assert(array != null && delegate != null, "TouchDispatcher.findHandler():Arguments is null"); 532 533 for (i = 0; i < array.length; i++) { 534 if (array[i].getDelegate() == delegate) { 535 return array[i]; 536 } 537 } 538 539 return null; 540 break; 541 default: 542 throw "Argument must be non-nil "; 543 break; 544 } 545 }, 546 547 /** 548 * @param {cc.TouchDelegate} delegate 549 */ 550 forceRemoveDelegate:function (delegate) { 551 var handler; 552 // XXX: remove it from both handlers ??? 553 // remove handler from m_pStandardHandlers 554 for (var i = 0; i < this._standardHandlers.length; i++) { 555 handler = this._standardHandlers[i]; 556 if (handler && handler.getDelegate() == delegate) { 557 cc.ArrayRemoveObject(this._standardHandlers, handler); 558 break; 559 } 560 } 561 562 for (i = 0; i < this._targetedHandlers.length; i++) { 563 handler = this._targetedHandlers[i]; 564 if (handler && handler.getDelegate() == delegate) { 565 cc.ArrayRemoveObject(this._targetedHandlers, handler); 566 break; 567 } 568 } 569 }, 570 571 /** 572 * @param {Array} array 573 */ 574 rearrangeHandlers:function (array) { 575 array.sort(cc.less); 576 } 577 }); 578 579 /** 580 * @type {cc.Point} 581 */ 582 cc.TouchDispatcher.preTouchPoint = cc.p(0, 0); 583 584 cc.TouchDispatcher.isRegisterEvent = false; 585 586 cc.getHTMLElementPosition = function (element) { 587 var docElem = document.documentElement; 588 var win = window; 589 var box = null; 590 if (typeof element.getBoundingClientRect === 'function') { 591 box = element.getBoundingClientRect(); 592 } else { 593 if (element instanceof HTMLCanvasElement) { 594 box = { 595 left:0, 596 top:0, 597 width:element.width, 598 height:element.height 599 }; 600 } else { 601 box = { 602 left:0, 603 top:0, 604 width:parseInt(element.style.width), 605 height:parseInt(element.style.height) 606 }; 607 } 608 } 609 return { 610 left:box.left + win.pageXOffset - docElem.clientLeft, 611 top:box.top + win.pageYOffset - docElem.clientTop, 612 width:box.width, 613 height:box.height 614 }; 615 }; 616 617 cc.ProcessMouseupEvent = function (element, event) { 618 var pos = cc.getHTMLElementPosition(element); 619 620 var tx, ty; 621 if (event.pageX != null) { //not avalable in <= IE8 622 tx = event.pageX; 623 ty = event.pageY; 624 } else { 625 pos.left -= document.body.scrollLeft; 626 pos.top -= document.body.scrollTop; 627 tx = event.clientX; 628 ty = event.clientY; 629 } 630 631 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 632 633 var touch = new cc.Touch(location.x, location.y); 634 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 635 cc.TouchDispatcher.preTouchPoint.x = location.x; 636 cc.TouchDispatcher.preTouchPoint.y = location.y; 637 638 var posArr = []; 639 posArr.push(touch); 640 //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null); 641 cc.EGLView.getInstance().touchesEnded(posArr, null); 642 }; 643 644 /** 645 * @param {HTMLCanvasElement|HTMLDivElement} element 646 */ 647 cc.TouchDispatcher.registerHtmlElementEvent = function (element) { 648 if (cc.TouchDispatcher.isRegisterEvent) return; 649 650 if (!cc.Browser.isMobile) { 651 window.addEventListener('mousedown', function (event) { 652 cc.Director.getInstance().getTouchDispatcher()._setMousePressed(true); 653 }); 654 655 window.addEventListener('mouseup', function (event) { 656 cc.Director.getInstance().getTouchDispatcher()._setMousePressed(false); 657 658 var pos = cc.getHTMLElementPosition(element); 659 660 var tx, ty; 661 if (event.pageX != null) { //not avalable in <= IE8 662 tx = event.pageX; 663 ty = event.pageY; 664 } else { 665 pos.left -= document.body.scrollLeft; 666 pos.top -= document.body.scrollTop; 667 tx = event.clientX; 668 ty = event.clientY; 669 } 670 671 if (!cc.rectContainsPoint(new cc.Rect(pos.left, pos.top, pos.width, pos.height), cc.p(tx, ty))) { 672 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 673 var touch = new cc.Touch(location.x, location.y); 674 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 675 cc.TouchDispatcher.preTouchPoint.x = location.x; 676 cc.TouchDispatcher.preTouchPoint.y = location.y; 677 678 var posArr = []; 679 posArr.push(touch); 680 //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null); 681 cc.EGLView.getInstance().touchesEnded(posArr, null); 682 } 683 }); 684 685 //register canvas mouse event 686 element.addEventListener("mousedown", function (event) { 687 var pos = cc.getHTMLElementPosition(element); 688 689 var tx, ty; 690 if (event.pageX != null) { //not avalable in <= IE8 691 tx = event.pageX; 692 ty = event.pageY; 693 } else { 694 pos.left -= document.body.scrollLeft; 695 pos.top -= document.body.scrollTop; 696 tx = event.clientX; 697 ty = event.clientY; 698 } 699 700 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 701 var touch = new cc.Touch(location.x, location.y); 702 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 703 cc.TouchDispatcher.preTouchPoint.x = location.x; 704 cc.TouchDispatcher.preTouchPoint.y = location.y; 705 706 var posArr = []; 707 posArr.push(touch); 708 //csx cc.Director.getInstance().getTouchDispatcher().touchesBegan(posArr, null); 709 cc.EGLView.getInstance().touchesBegan(posArr, null); 710 }); 711 712 element.addEventListener("mouseup", function (event) { 713 cc.ProcessMouseupEvent(element, event); 714 }); 715 716 element.addEventListener("mousemove", function (event) { 717 var pos = cc.getHTMLElementPosition(element); 718 719 var tx, ty; 720 if (event.pageX != null) { //not avalable in <= IE8 721 tx = event.pageX; 722 ty = event.pageY; 723 } else { 724 pos.left -= document.body.scrollLeft; 725 pos.top -= document.body.scrollTop; 726 tx = event.clientX; 727 ty = event.clientY; 728 } 729 730 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 731 var touch = new cc.Touch(location.x, location.y); 732 //TODO this feature only chrome support 733 //if((event.button == 0) && (event.which == 1)) 734 // touch._setPressed(true); 735 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 736 cc.TouchDispatcher.preTouchPoint.x = location.x; 737 cc.TouchDispatcher.preTouchPoint.y = location.y; 738 739 var posArr = []; 740 posArr.push(touch); 741 742 //csx cc.Director.getInstance().getTouchDispatcher().touchesMoved(posArr, null); 743 cc.EGLView.getInstance().touchesMoved(posArr, null); 744 }); 745 } 746 else if(window.navigator.msPointerEnabled){ 747 var _pointerEventsMap = { 748 "MSPointerDown" : "touchesBegan", 749 "MSPointerMove" : "touchesMoved", 750 "MSPointerUp" : "touchesEnded", 751 "MSPointerCancel" : "touchesCancelled" 752 }; 753 754 for(var i in _pointerEventsMap){ 755 (function(_pointerEvent, _touchEvent){ 756 element.addEventListener(_pointerEvent, function (event){ 757 var pos = cc.getHTMLElementPosition(element); 758 759 pos.left -= document.body.scrollLeft; 760 pos.top -= document.body.scrollTop; 761 762 var tx, ty, touch, preLocation; 763 tx = event.clientX; 764 ty = event.clientY; 765 766 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 767 var touch = new cc.Touch(location.x, location.y); 768 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 769 cc.TouchDispatcher.preTouchPoint.x = location.x; 770 cc.TouchDispatcher.preTouchPoint.y = location.y; 771 772 cc.Director.getInstance().getTouchDispatcher()[_touchEvent]([touch], null); 773 event.stopPropagation(); 774 event.preventDefault(); 775 }, false); 776 })(i, _pointerEventsMap[i]); 777 } 778 } 779 else { 780 781 //register canvas touch event 782 element.addEventListener("touchstart", function (event) { 783 if (!event.changedTouches) return; 784 785 var posArr = []; 786 var pos = cc.getHTMLElementPosition(element); 787 788 pos.left -= document.body.scrollLeft; 789 pos.top -= document.body.scrollTop; 790 791 var touch_event, tx, ty, touch, preLocation; 792 var length = event.changedTouches.length; 793 for (var i = 0; i < length; i++) { 794 touch_event = event.changedTouches[i]; 795 //tx = touch_event.pageX; 796 //ty = touch_event.pageY; 797 if (touch_event) { 798 tx = touch_event.clientX; 799 ty = touch_event.clientY; 800 801 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 802 touch = null; 803 if (touch_event.hasOwnProperty("identifier")) { 804 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 805 //use Touch Pool 806 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 807 touch._setPrevPoint(preLocation.x, preLocation.y); 808 cc.TouchDispatcher._setPreTouch(touch); 809 } else { 810 touch = new cc.Touch(location.x, location.y); 811 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 812 } 813 cc.TouchDispatcher.preTouchPoint.x = location.x; 814 cc.TouchDispatcher.preTouchPoint.y = location.y; 815 816 posArr.push(touch); 817 } 818 } 819 //csx cc.Director.getInstance().getTouchDispatcher().touchesBegan(posArr, null); 820 cc.EGLView.getInstance().touchesBegan(posArr, null); 821 event.stopPropagation(); 822 event.preventDefault(); 823 }, false); 824 825 element.addEventListener("touchmove", function (event) { 826 if (!event.changedTouches) return; 827 828 var posArr = []; 829 var pos = cc.getHTMLElementPosition(element); 830 831 pos.left -= document.body.scrollLeft; 832 pos.top -= document.body.scrollTop; 833 834 var touch_event, tx, ty, touch, preLocation; 835 var length = event.changedTouches.length; 836 for (var i = 0; i < length; i++) { 837 touch_event = event.changedTouches[i]; 838 //tx = touch_event.pageX; 839 //ty = touch_event.pageY; 840 if (touch_event) { 841 tx = touch_event.clientX; 842 ty = touch_event.clientY; 843 844 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 845 846 touch = null; 847 if (touch_event.hasOwnProperty("identifier")) { 848 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 849 //use Touch Pool 850 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 851 touch._setPrevPoint(preLocation.x, preLocation.y); 852 cc.TouchDispatcher._setPreTouch(touch); 853 } else { 854 touch = new cc.Touch(location.x, location.y); 855 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 856 } 857 cc.TouchDispatcher.preTouchPoint.x = location.x; 858 cc.TouchDispatcher.preTouchPoint.y = location.y; 859 860 posArr.push(touch); 861 } 862 } 863 //csx cc.Director.getInstance().getTouchDispatcher().touchesMoved(posArr, null); 864 cc.EGLView.getInstance().touchesMoved(posArr, null); 865 event.stopPropagation(); 866 event.preventDefault(); 867 }, false); 868 869 element.addEventListener("touchend", function (event) { 870 if (!event.changedTouches) return; 871 872 var posArr = []; 873 var pos = cc.getHTMLElementPosition(element); 874 875 pos.left -= document.body.scrollLeft; 876 pos.top -= document.body.scrollTop; 877 878 var touch_event, tx, ty, touch, preLocation; 879 var length = event.changedTouches.length; 880 for (var i = 0; i < length; i++) { 881 touch_event = event.changedTouches[i]; 882 //tx = touch_event.pageX; 883 //ty = touch_event.pageY; 884 if (touch_event) { 885 tx = touch_event.clientX; 886 ty = touch_event.clientY; 887 888 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 889 890 touch = null; 891 if (touch_event.hasOwnProperty("identifier")) { 892 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 893 //use Touch Pool 894 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 895 touch._setPrevPoint(preLocation.x, preLocation.y); 896 cc.TouchDispatcher._deletePreTouchWithSameId(touch); 897 } else { 898 touch = new cc.Touch(location.x, location.y); 899 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 900 } 901 cc.TouchDispatcher.preTouchPoint.x = location.x; 902 cc.TouchDispatcher.preTouchPoint.y = location.y; 903 904 posArr.push(touch); 905 } 906 } 907 //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null); 908 cc.EGLView.getInstance().touchesEnded(posArr, null); 909 event.stopPropagation(); 910 event.preventDefault(); 911 }, false); 912 913 element.addEventListener("touchcancel", function (event) { 914 if (!event.changedTouches) return; 915 916 var posArr = []; 917 var pos = cc.getHTMLElementPosition(element); 918 919 pos.left -= document.body.scrollLeft; 920 pos.top -= document.body.scrollTop; 921 922 var touch_event, tx, ty, touch, preLocation; 923 var length = event.changedTouches.length; 924 for (var i = 0; i < length; i++) { 925 touch_event = event.changedTouches[i]; 926 //tx = touch_event.pageX; 927 //ty = touch_event.pageY; 928 if (touch_event) { 929 tx = touch_event.clientX; 930 ty = touch_event.clientY; 931 932 var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos); 933 934 touch = null; 935 if (touch_event.hasOwnProperty("identifier")) { 936 touch = new cc.Touch(location.x, location.y, touch_event.identifier); 937 //use Touch Pool 938 preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation(); 939 touch._setPrevPoint(preLocation.x, preLocation.y); 940 cc.TouchDispatcher._deletePreTouchWithSameId(touch); 941 } else { 942 touch = new cc.Touch(location.x, location.y); 943 touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y); 944 } 945 cc.TouchDispatcher.preTouchPoint.x = location.x; 946 cc.TouchDispatcher.preTouchPoint.y = location.y; 947 948 posArr.push(touch); 949 } 950 } 951 //csx cc.Director.getInstance().getTouchDispatcher().touchesCancelled(posArr, null); 952 cc.EGLView.getInstance().touchesCancelled(posArr, null); 953 event.stopPropagation(); 954 event.preventDefault(); 955 }, false); 956 } 957 958 cc.TouchDispatcher.isRegisterEvent = true; 959 }; 960 961 /** 962 * @param {cc.Touch} touch 963 * @return {cc.Touch} preTouch 964 */ 965 cc.TouchDispatcher._getPreTouch = function (touch) { 966 var preTouch = null; 967 var preTouchPool = cc.TouchDispatcher._preTouchPool; 968 var id = touch.getId(); 969 for (var i = preTouchPool.length - 1; i >= 0; i--) { 970 if (preTouchPool[i].getId() == id) { 971 preTouch = preTouchPool[i]; 972 break; 973 } 974 } 975 if (!preTouch) { 976 preTouch = touch; 977 } 978 return preTouch; 979 }; 980 981 /** 982 * @param {cc.Touch} touch 983 */ 984 cc.TouchDispatcher._setPreTouch = function (touch) { 985 var find = false; 986 var preTouchPool = cc.TouchDispatcher._preTouchPool; 987 var id = touch.getId(); 988 for (var i = preTouchPool.length - 1; i >= 0; i--) { 989 if (preTouchPool[i].getId() == id) { 990 preTouchPool[i] = touch; 991 find = true; 992 break; 993 } 994 } 995 if (!find) { 996 //debug touches{ 997 //cc.log("Pool.length: " + preTouchPool.length); 998 //} 999 if (preTouchPool.length <= 50) { 1000 preTouchPool.push(touch); 1001 } else { 1002 preTouchPool[cc.TouchDispatcher._preTouchPoolPointer] = touch; 1003 cc.TouchDispatcher._preTouchPoolPointer = (cc.TouchDispatcher._preTouchPoolPointer + 1) % 50; 1004 } 1005 } 1006 }; 1007 1008 /** 1009 * @param {cc.Touch} touch 1010 */ 1011 cc.TouchDispatcher._deletePreTouchWithSameId = function (touch) { 1012 var changeTouch; 1013 var preTouchPool = cc.TouchDispatcher._preTouchPool; 1014 var id = touch.getId(); 1015 for (var i = preTouchPool.length - 1; i >= 0; i--) { 1016 if (preTouchPool[i].getId() == id) { 1017 changeTouch = preTouchPool.pop(); 1018 if (i != preTouchPool.length) { 1019 preTouchPool[i] = changeTouch; 1020 } 1021 break; 1022 } 1023 } 1024 }; 1025 1026 /** 1027 * @type {Array} 1028 */ 1029 cc.TouchDispatcher._preTouchPool = []; 1030 1031 /** 1032 * @type {Number} 1033 */ 1034 cc.TouchDispatcher._preTouchPoolPointer = 0; 1035 1036 /** 1037 * register a targeted touch delegate to the dispatcher's list. 1038 * @param {Number} priority 1039 * @param {Boolean} swallowsTouches 1040 * @param {Object} delegate 1041 */ 1042 cc.registerTargetedDelegate = function(priority, swallowsTouches, delegate){ 1043 cc.Director.getInstance().getTouchDispatcher()._addTargetedDelegate(delegate, priority, swallowsTouches); 1044 }; 1045 1046 /** 1047 * Adds a standard touch delegate to the dispatcher's list. 1048 * See StandardTouchDelegate description. 1049 * @param {Object} delegate 1050 * @param {Number} [priority=] 1051 */ 1052 cc.registerStandardDelegate = function(delegate, priority){ 1053 cc.Director.getInstance().getTouchDispatcher()._addStandardDelegate(delegate, priority); 1054 }; 1055 1056 /** 1057 * Removes a touch delegate. from TouchDispatcher 1058 * @param delegate 1059 */ 1060 cc.unregisterTouchDelegate = function(delegate){ 1061 cc.Director.getInstance().getTouchDispatcher()._removeDelegate(delegate); 1062 };