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 _mouseDelegateHandlers:null, 353 _dispatchEvents:false, 354 355 init:function () { 356 this._dispatchEvents = true; 357 this._mouseDelegateHandlers = []; 358 this._mousePressed = false; 359 360 cc.MouseDispatcher._registerHtmlElementEvent(cc.canvas); 361 return true; 362 }, 363 364 _setMousePressed:function (pressed) { 365 this._mousePressed = pressed; 366 }, 367 368 _getMousePressed:function () { 369 return this._mousePressed; 370 }, 371 372 /** 373 * Adds a mouse delegate to the dispatcher's list. <br/> 374 * Delegates with a lower priority value will be called before higher priority values. <br/> 375 * All the events will be propagated to all the delegates, unless the one delegate returns YES. </br> 376 * @param delegate 377 * @param priority 378 */ 379 addMouseDelegate:function (delegate, priority) { 380 var handler = cc.MouseHandler.create(delegate, priority); 381 382 this._mouseDelegateHandlers = this.forceAddHandler(handler, this._mouseDelegateHandlers); 383 }, 384 385 /** 386 * Force add handler 387 * @param {cc.TouchHandler} handler 388 * @param {Array} array 389 * @return {Array} 390 */ 391 forceAddHandler:function (handler, array) { 392 var u = 0; 393 394 for (var i = 0; i < array.length; i++) { 395 var h = array[i]; 396 if (h) { 397 if (h.getPriority() < handler.getPriority()) { 398 ++u; 399 } 400 if (h.getDelegate() == handler.getDelegate()) { 401 cc.Assert(0, "TouchDispatcher.forceAddHandler()"); 402 return array; 403 } 404 } 405 } 406 return cc.ArrayAppendObjectToIndex(array, handler, u); 407 }, 408 409 /** 410 * removes a mouse delegate 411 * @param delegate 412 */ 413 removeMouseDelegate:function (delegate) { 414 if (delegate == null) 415 return; 416 417 for (var i = 0; i < this._mouseDelegateHandlers.length; i++) { 418 var handler = this._mouseDelegateHandlers[i]; 419 if (handler && handler.getDelegate() == delegate) { 420 cc.ArrayRemoveObject(this._mouseDelegateHandlers, handler); 421 break; 422 } 423 } 424 }, 425 426 _findHandler:function (delegate) { 427 for (i = 0; i < this._mouseDelegateHandlers.length; i++) { 428 if (this._mouseDelegateHandlers[i] && this._mouseDelegateHandlers[i].getDelegate() == delegate) { 429 return this._mouseDelegateHandlers[i]; 430 } 431 } 432 }, 433 434 setPriority:function (priority, delegate) { 435 cc.Assert(delegate != null, "MouseDispatcher.setPriority():Arguments is null"); 436 var handler = this._findHandler(delegate); 437 cc.Assert(handler != null, "MouseDispatcher.setPriority():Cant find MouseHandler"); 438 439 if (handler.getPriority() != priority) { 440 handler.setPriority(priority); 441 this._mouseDelegateHandlers.sort(cc.less); 442 } 443 }, 444 445 /** 446 * Removes all mouse delegates, releasing all the delegates 447 */ 448 removeAllMouseDelegates:function () { 449 this._mouseDelegateHandlers.length = 0; 450 }, 451 452 mouseHandle:function (mouseObj, event, index) { 453 for (var i = 0; i < this._mouseDelegateHandlers.length; i++) { 454 var handler = this._mouseDelegateHandlers[i]; 455 456 switch (index) { 457 case cc.MOUSE_DOWN: 458 if (handler.getDelegate().onMouseDown) 459 handler.getDelegate().onMouseDown(mouseObj); 460 break; 461 case cc.MOUSE_UP: 462 if (handler.getDelegate().onMouseUp) 463 handler.getDelegate().onMouseUp(mouseObj); 464 break; 465 case cc.MOUSE_MOVED: 466 if (this._mousePressed) { 467 if (handler.getDelegate().onMouseDragged) 468 handler.getDelegate().onMouseDragged(mouseObj); 469 } else { 470 if (handler.getDelegate().onMouseMoved) 471 handler.getDelegate().onMouseMoved(mouseObj); 472 } 473 break; 474 case cc.MOUSE_ENTERED: 475 if (handler.getDelegate().onMouseEntered) 476 handler.getDelegate().onMouseEntered(mouseObj); 477 break; 478 case cc.MOUSE_EXITED: 479 if (handler.getDelegate().onMouseExited) 480 handler.getDelegate().onMouseExited(mouseObj); 481 break; 482 case cc.SCROLL_WHEEL: 483 if (handler.getDelegate().onScrollWheel) 484 handler.getDelegate().onScrollWheel(mouseObj); 485 break; 486 } 487 } 488 } 489 }); 490 491 cc.MouseDispatcher._preMousePoint = cc.p(0, 0); 492 493 cc.MouseDispatcher._isRegisterEvent = false; 494 495 cc.MouseDispatcher._registerHtmlElementEvent = function (element) { 496 if (cc.MouseDispatcher._isRegisterEvent) 497 return; 498 499 window.addEventListener('mousedown', function (event) { 500 cc.Director.getInstance().getMouseDispatcher()._setMousePressed(true); 501 }); 502 503 window.addEventListener('mouseup', function (event) { 504 cc.Director.getInstance().getMouseDispatcher()._setMousePressed(false); 505 }); 506 507 function getMouseByEvent(event) { 508 var pos = cc.getHTMLElementPosition(element); 509 510 var tx = event.pageX; 511 var ty = event.pageY; 512 513 var mouseX = (tx - pos.left) / cc.Director.getInstance().getContentScaleFactor(); 514 var mouseY = (pos.height - (ty - pos.top)) / cc.Director.getInstance().getContentScaleFactor(); 515 516 var mouse = new cc.Mouse(mouseX, mouseY); 517 mouse._setPrevPoint(cc.MouseDispatcher._preMousePoint.x, cc.MouseDispatcher._preMousePoint.y); 518 mouse.setButton(event.button); 519 cc.MouseDispatcher._preMousePoint.x = mouseX; 520 cc.MouseDispatcher._preMousePoint.y = mouseY; 521 522 return mouse; 523 } 524 525 //register canvas mouse event 526 element.addEventListener("mousedown", function (event) { 527 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_DOWN); 528 }); 529 530 element.addEventListener("mouseup", function (event) { 531 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_UP); 532 }); 533 534 element.addEventListener("mousemove", function (event) { 535 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_MOVED); 536 }); 537 538 element.addEventListener("mousewheel", function (event) { 539 var mouse = getMouseByEvent(event); 540 mouse.setWheelDelta(event.wheelDelta); 541 cc.Director.getInstance().getMouseDispatcher().mouseHandle(mouse, event, cc.SCROLL_WHEEL); 542 }, false); 543 544 element.addEventListener("mouseout", function (event) { 545 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_EXITED); 546 }, false); 547 548 element.addEventListener("mouseover", function (event) { 549 cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_ENTERED); 550 }, false); 551 }; 552 553 554 555