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.MOUSE_DOWN = 1 << 0; 32 33 /** 34 * @constant 35 * @type Number 36 */ 37 cc.MOUSE_MOVED = 1 << 1; 38 39 /** 40 * @constant 41 * @type Number 42 */ 43 cc.MOUSE_DRAGGED = 1 << 2; 44 45 /** 46 * @constant 47 * @type Number 48 */ 49 cc.MOUSE_UP = 1 << 3; 50 51 /** 52 * @constant 53 * @type Number 54 */ 55 cc.RIGHT_MOUSE_DOWN = 1 << 4; 56 57 /** 58 * @constant 59 * @type Number 60 */ 61 cc.RIGHT_MOUSE_DRAGGED = 1 << 5; 62 63 /** 64 * @constant 65 * @type Number 66 */ 67 cc.RIGHT_MOUSE_UP = 1 << 6; 68 69 /** 70 * @constant 71 * @type Number 72 */ 73 cc.OTHER_MOUSE_DOWN = 1 << 7; 74 75 /** 76 * @constant 77 * @type Number 78 */ 79 cc.OTHER_MOUSE_DRAGGED = 1 << 8; 80 81 /** 82 * @constant 83 * @type Number 84 */ 85 cc.OTHER_MOUSE_UP = 1 << 9; 86 87 /** 88 * @constant 89 * @type Number 90 */ 91 cc.SCROLL_WHEEL = 1 << 10; 92 93 /** 94 * @constant 95 * @type Number 96 */ 97 cc.MOUSE_ENTERED = 1 << 11; 98 99 /** 100 * @constant 101 * @type Number 102 */ 103 cc.MOUSE_EXITED = 1 << 12; 104 105 /** 106 * @constant 107 * @type Number 108 */ 109 cc.MOUSE_LEFTBUTTON = 0; 110 111 /** 112 * @constant 113 * @type Number 114 */ 115 cc.MOUSE_MIDDLEBUTTON = 1; 116 117 /** 118 * @constant 119 * @type Number 120 */ 121 cc.MOUSE_RIGHTBUTTON = 2; 122 123 /** 124 * CCMouseEventDelegate protocol. 125 * Implement it in your node to receive any of mouse events 126 */ 127 cc.MouseEventDelegate = cc.Class.extend({ 128 /** 129 * <p>called when the "mouseDown" event is received. <br/> 130 * Return YES to avoid propagating the event to other delegates. </p> 131 * @param {cc.Mouse} event 132 * @return {Boolean} 133 */ 134 onMouseDown:function (event) { 135 return false; 136 }, 137 138 /** 139 * <p>called when the "mouseDragged" event is received. <br/> 140 * Return YES to avoid propagating the event to other delegates.</p> 141 * @param {cc.Mouse} event 142 * @return {Boolean} 143 */ 144 onMouseDragged:function (event) { 145 return false; 146 }, 147 148 /** 149 * <p> called when the "mouseMoved" event is received. <br/> 150 * Return YES to avoid propagating the event to other delegates. </p> 151 * @param {cc.Mouse} event 152 * @return {Boolean} 153 */ 154 onMouseMoved:function (event) { 155 return false; 156 }, 157 158 /** 159 * <p> called when the "mouseUp" event is received. <br/> 160 * Return YES to avoid propagating the event to other delegates. </p> 161 * @param {cc.Mouse} event 162 * @return {Boolean} 163 */ 164 onMouseUp:function (event) { 165 return false; 166 }, 167 168 //right 169 /** 170 * <p> called when the "rightMouseDown" event is received. <br/> 171 * Return YES to avoid propagating the event to other delegates. </p> 172 * @param {cc.Mouse} event 173 * @return {Boolean} 174 */ 175 onRightMouseDown:function (event) { 176 return false; 177 }, 178 179 /** 180 * <p> called when the "rightMouseDragged" event is received. <br/> 181 * Return YES to avoid propagating the event to other delegates. </p> 182 * @param {cc.Mouse} event 183 * @return {Boolean} 184 */ 185 onRightMouseDragged:function (event) { 186 return false; 187 }, 188 189 /** 190 * <p> called when the "rightMouseUp" event is received. <br/> 191 * Return YES to avoid propagating the event to other delegates. </p> 192 * @param {cc.Mouse} event 193 * @return {Boolean} 194 */ 195 onRightMouseUp:function (event) { 196 return false; 197 }, 198 199 //other 200 /** 201 * <p>called when the "otherMouseDown" event is received. <br/> 202 * Return YES to avoid propagating the event to other delegates. </p> 203 * @param {cc.Mouse} event 204 * @return {Boolean} 205 */ 206 onOtherMouseDown:function (event) { 207 return false; 208 }, 209 210 /** 211 * <p> called when the "otherMouseDragged" event is received. <br/> 212 * Return YES to avoid propagating the event to other delegates. </p> 213 * @param {cc.Mouse} event 214 * @return {Boolean} 215 */ 216 onOtherMouseDragged:function (event) { 217 return false; 218 }, 219 220 /** 221 * <p> called when the "otherMouseUp" event is received. <br/> 222 * Return YES to avoid propagating the event to other delegates. </p> 223 * @param {cc.Mouse} event 224 * @return {Boolean} 225 */ 226 onOtherMouseUp:function (event) { 227 return false; 228 }, 229 230 //scroll wheel 231 /** 232 * <p> called when the "scrollWheel" event is received. <br/> 233 * Return YES to avoid propagating the event to other delegates. </p> 234 * @param {cc.Mouse} event 235 * @return {Boolean} 236 */ 237 onScrollWheel:function (event) { 238 return false; 239 }, 240 241 // enter / exit 242 /** 243 * <p> called when the "mouseEntered" event is received. <br/> 244 * Return YES to avoid propagating the event to other delegates. </p> 245 * @param {cc.Mouse} theEvent 246 * @return {Boolean} 247 */ 248 onMouseEntered:function (theEvent) { 249 return false; 250 }, 251 252 /** 253 * <p> called when the "mouseExited" event is received. <br/> 254 * Return YES to avoid propagating the event to other delegates. </p> 255 * @param {cc.Mouse} theEvent 256 * @return {Boolean} 257 */ 258 onMouseExited:function (theEvent) { 259 return false; 260 } 261 }); 262 263 cc.Mouse = cc.Touch.extend({ 264 _wheelDelta:0, 265 _button:cc.MOUSE_LEFTBUTTON, 266 267 getWheelDelta:function () { 268 return this._wheelDelta; 269 }, 270 271 setWheelDelta:function (delta) { 272 this._wheelDelta = delta; 273 }, 274 275 getButton:function () { 276 return this._button; 277 }, 278 279 setButton:function (button) { 280 this._button = button; 281 } 282 }); 283 284 /** 285 * cc.MouseHandler 286 * Object than contains the delegate and priority of the event handler. 287 * @class 288 * @extends cc.Class 289 */ 290 cc.MouseHandler = cc.Class.extend(/** @lends cc.MouseHandler# */{ 291 _delegate:null, 292 _priority:0, 293 _enabledSelectors:0, 294 295 /** 296 * @return {cc.MouseEventDelegate} 297 */ 298 getDelegate:function () { 299 return this._delegate; 300 }, 301 302 /** 303 * @param {cc.TouchDelegate} delegate 304 */ 305 setDelegate:function (delegate) { 306 this._delegate = delegate; 307 }, 308 309 /** 310 * @return {Number} 311 */ 312 getPriority:function () { 313 return this._priority; 314 }, 315 316 /** 317 * @param {Number} priority 318 */ 319 setPriority:function (priority) { 320 this._priority = priority; 321 }, 322 323 /** 324 * Enabled selectors 325 * @return {Number} 326 */ 327 getEnabledSelectors:function () { 328 return this._enabledSelectors; 329 }, 330 331 /** 332 * @param {Number} value 333 */ 334 setEnalbedSelectors:function (value) { 335 this._enabledSelectors = value; 336 }, 337 338 initWithDelegate:function (delegate, priority) { 339 this._delegate = delegate; 340 this._priority = priority; 341 } 342 }); 343 344 cc.MouseHandler.create = function (delegate, priority) { 345 var handler = new cc.MouseHandler(); 346 handler.initWithDelegate(delegate, priority); 347 return handler; 348 }; 349 350 cc.MouseDispatcher = cc.Class.extend({ 351 _mousePressed:false, 352 _rightMousePressed:false, 353 _mouseDelegateHandlers:null, 354 _dispatchEvents:false, 355 356 init:function () { 357 this._dispatchEvents = true; 358 this._mouseDelegateHandlers = []; 359 this._mousePressed = false; 360 this._rightMousePressed = false; 361 362 cc.MouseDispatcher._registerHtmlElementEvent(cc.canvas); 363 return true; 364 }, 365 366 _setMousePressed:function (pressed) { 367 this._mousePressed = pressed; 368 }, 369 370 _getMousePressed:function () { 371 return this._mousePressed; 372 }, 373 374 _setRightMousePressed:function (pressed) { 375 this._rightMousePressed = pressed; 376 }, 377 378 _getRightMousePressed:function () { 379 return this._rightMousePressed; 380 }, 381 382 /** 383 * Adds a mouse delegate to the dispatcher's list. <br/> 384 * Delegates with a lower priority value will be called before higher priority values. <br/> 385 * All the events will be propagated to all the delegates, unless the one delegate returns YES. </br> 386 * @param delegate 387 * @param priority 388 */ 389 addMouseDelegate:function (delegate, priority) { 390 var handler = cc.MouseHandler.create(delegate, priority); 391 392 this._mouseDelegateHandlers = this.forceAddHandler(handler, this._mouseDelegateHandlers); 393 }, 394 395 /** 396 * Force add handler 397 * @param {cc.TouchHandler} handler 398 * @param {Array} array 399 * @return {Array} 400 */ 401 forceAddHandler:function (handler, array) { 402 var u = 0; 403 404 for (var i = 0; i < array.length; i++) { 405 var h = array[i]; 406 if (h) { 407 if (h.getPriority() < handler.getPriority()) 408 ++u; 409 if (h.getDelegate() == handler.getDelegate()) { 410 cc.log("cc.MouseDispatcher.forceAddHandler(): handler has been added.") ; 411 return array; 412 } 413 } 414 } 415 return cc.ArrayAppendObjectToIndex(array, handler, u); 416 }, 417 418 /** 419 * removes a mouse delegate 420 * @param delegate 421 */ 422 removeMouseDelegate:function (delegate) { 423 if (delegate == null) 424 return; 425 426 for (var i = 0; i < this._mouseDelegateHandlers.length; i++) { 427 var handler = this._mouseDelegateHandlers[i]; 428 if (handler && handler.getDelegate() == delegate) { 429 cc.ArrayRemoveObject(this._mouseDelegateHandlers, handler); 430 break; 431 } 432 } 433 }, 434 435 _findHandler:function (delegate) { 436 for (var i = 0; i < this._mouseDelegateHandlers.length; i++) { 437 if (this._mouseDelegateHandlers[i] && this._mouseDelegateHandlers[i].getDelegate() == delegate) { 438 return this._mouseDelegateHandlers[i]; 439 } 440 } 441 return null; 442 }, 443 444 setPriority:function (priority, delegate) { 445 if(!delegate) 446 throw "cc.MouseDispatcher.setPriority(): delegate should be non-null"; 447 var handler = this._findHandler(delegate); 448 if(!handler) { 449 cc.log("cc.MouseDispatcher.setPriority(): Can't find MouseHandler in array"); 450 return; 451 } 452 453 454 if (handler.getPriority() != priority) { 455 handler.setPriority(priority); 456 this._mouseDelegateHandlers.sort(cc.less); 457 } 458 }, 459 460 /** 461 * Removes all mouse delegates, releasing all the delegates 462 */ 463 removeAllMouseDelegates:function () { 464 this._mouseDelegateHandlers.length = 0; 465 }, 466 467 mouseHandle:function (mouseObj, event, index) { 468 for (var i = 0; i < this._mouseDelegateHandlers.length; i++) { 469 var handler = this._mouseDelegateHandlers[i]; 470 471 switch (index) { 472 case cc.MOUSE_DOWN: 473 if (mouseObj.getButton() == cc.MOUSE_RIGHTBUTTON) { 474 if (handler.getDelegate().onRightMouseDown) 475 handler.getDelegate().onRightMouseDown(mouseObj); 476 } else { 477 if (handler.getDelegate().onMouseDown) 478 handler.getDelegate().onMouseDown(mouseObj); 479 } 480 break; 481 case cc.MOUSE_UP: 482 if (mouseObj.getButton() == cc.MOUSE_RIGHTBUTTON) { 483 if (handler.getDelegate().onRightMouseUp) 484 handler.getDelegate().onRightMouseUp(mouseObj); 485 } else { 486 if (handler.getDelegate().onMouseUp) 487 handler.getDelegate().onMouseUp(mouseObj); 488 } 489 break; 490 case cc.MOUSE_MOVED: 491 if (this._mousePressed) { 492 if (handler.getDelegate().onMouseDragged) 493 handler.getDelegate().onMouseDragged(mouseObj); 494 } else if (this._rightMousePressed) { 495 if (handler.getDelegate().onRightMouseDragged) 496 handler.getDelegate().onRightMouseDragged(mouseObj); 497 } else { 498 if (handler.getDelegate().onMouseMoved) 499 handler.getDelegate().onMouseMoved(mouseObj); 500 } 501 break; 502 case cc.MOUSE_ENTERED: 503 if (handler.getDelegate().onMouseEntered) 504 handler.getDelegate().onMouseEntered(mouseObj); 505 break; 506 case cc.MOUSE_EXITED: 507 if (handler.getDelegate().onMouseExited) 508 handler.getDelegate().onMouseExited(mouseObj); 509 break; 510 case cc.SCROLL_WHEEL: 511 if (handler.getDelegate().onScrollWheel) 512 handler.getDelegate().onScrollWheel(mouseObj); 513 break; 514 } 515 } 516 } 517 }); 518 519 cc.MouseDispatcher._preMousePoint = cc.p(0, 0); 520 521 cc.MouseDispatcher._isRegisterEvent = false; 522 523 cc.MouseDispatcher._registerHtmlElementEvent = function (element) { 524 if (cc.MouseDispatcher._isRegisterEvent) 525 return; 526 527 window.addEventListener('mousedown', function (event) { 528 if (event.button == cc.MOUSE_RIGHTBUTTON) { 529 cc.Director.getInstance().getMouseDispatcher()._setRightMousePressed(true); 530 } else { 531 cc.Director.getInstance().getMouseDispatcher()._setMousePressed(true); 532 } 533 }); 534 535 window.addEventListener('mouseup', function (event) { 536 if (event.button == cc.MOUSE_RIGHTBUTTON) { 537 cc.Director.getInstance().getMouseDispatcher()._setRightMousePressed(false); 538 } else { 539 cc.Director.getInstance().getMouseDispatcher()._setMousePressed(false); 540 } 541 }); 542 543 function getMouseByEvent(event) { 544 var pos = cc.getHTMLElementPosition(element); 545 546 var tx = event.pageX; 547 var ty = event.pageY; 548 var eglViewer = cc.EGLView.getInstance(); 549 550 var mouseX = (tx - pos.left) / eglViewer.getScaleX(); 551 var mouseY = (pos.height - (ty - pos.top)) / eglViewer.getScaleY(); 552 553 var mouse = new cc.Mouse(mouseX, mouseY); 554 mouse._setPrevPoint(cc.MouseDispatcher._preMousePoint.x, cc.MouseDispatcher._preMousePoint.y); 555 mouse.setButton(event.button); 556 cc.MouseDispatcher._preMousePoint.x = mouseX; 557 cc.MouseDispatcher._preMousePoint.y = mouseY; 558 559 return mouse; 560 } 561 562 //register canvas mouse event 563 element.addEventListener("mousedown", function (event) { 564 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_DOWN); 565 }); 566 567 element.addEventListener("mouseup", function (event) { 568 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_UP); 569 }); 570 571 element.addEventListener("mousemove", function (event) { 572 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_MOVED); 573 }); 574 575 element.addEventListener("mousewheel", function (event) { 576 var mouse = getMouseByEvent(event); 577 mouse.setWheelDelta(event.wheelDelta); 578 cc.Director.getInstance().getMouseDispatcher().mouseHandle(mouse, event, cc.SCROLL_WHEEL); 579 }, false); 580 581 /* firefox fix */ 582 element.addEventListener("DOMMouseScroll", function(event) { 583 var mouse = getMouseByEvent(event); 584 mouse.setWheelDelta(event.detail * -120); 585 cc.Director.getInstance().getMouseDispatcher().mouseHandle(mouse, event, cc.SCROLL_WHEEL); 586 }); 587 588 element.addEventListener("mouseout", function (event) { 589 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_EXITED); 590 }, false); 591 592 element.addEventListener("mouseover", function (event) { 593 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_ENTERED); 594 }, false); 595 }; 596 597 598