CCMouseDispatcher.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /****************************************************************************
  2. Copyright (c) 2010-2012 cocos2d-x.org
  3. Copyright (c) 2008-2010 Ricardo Quesada
  4. Copyright (c) 2011 Zynga Inc.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. /**
  23. * @constant
  24. * @type Number
  25. */
  26. cc.MOUSE_DOWN = 1 << 0;
  27. /**
  28. * @constant
  29. * @type Number
  30. */
  31. cc.MOUSE_MOVED = 1 << 1;
  32. /**
  33. * @constant
  34. * @type Number
  35. */
  36. cc.MOUSE_DRAGGED = 1 << 2;
  37. /**
  38. * @constant
  39. * @type Number
  40. */
  41. cc.MOUSE_UP = 1 << 3;
  42. /**
  43. * @constant
  44. * @type Number
  45. */
  46. cc.RIGHT_MOUSE_DOWN = 1 << 4;
  47. /**
  48. * @constant
  49. * @type Number
  50. */
  51. cc.RIGHT_MOUSE_DRAGGED = 1 << 5;
  52. /**
  53. * @constant
  54. * @type Number
  55. */
  56. cc.RIGHT_MOUSE_UP = 1 << 6;
  57. /**
  58. * @constant
  59. * @type Number
  60. */
  61. cc.OTHER_MOUSE_DOWN = 1 << 7;
  62. /**
  63. * @constant
  64. * @type Number
  65. */
  66. cc.OTHER_MOUSE_DRAGGED = 1 << 8;
  67. /**
  68. * @constant
  69. * @type Number
  70. */
  71. cc.OTHER_MOUSE_UP = 1 << 9;
  72. /**
  73. * @constant
  74. * @type Number
  75. */
  76. cc.SCROLL_WHEEL = 1 << 10;
  77. /**
  78. * @constant
  79. * @type Number
  80. */
  81. cc.MOUSE_ENTERED = 1 << 11;
  82. /**
  83. * @constant
  84. * @type Number
  85. */
  86. cc.MOUSE_EXITED = 1 << 12;
  87. /**
  88. * @constant
  89. * @type Number
  90. */
  91. cc.MOUSE_LEFTBUTTON = 0;
  92. /**
  93. * @constant
  94. * @type Number
  95. */
  96. cc.MOUSE_MIDDLEBUTTON = 1;
  97. /**
  98. * @constant
  99. * @type Number
  100. */
  101. cc.MOUSE_RIGHTBUTTON = 2;
  102. /**
  103. * CCMouseEventDelegate protocol.
  104. * Implement it in your node to receive any of mouse events
  105. */
  106. cc.MouseEventDelegate = cc.Class.extend({
  107. /**
  108. * <p>called when the "mouseDown" event is received. <br/>
  109. * Return YES to avoid propagating the event to other delegates. </p>
  110. * @param {cc.Mouse} event
  111. * @return {Boolean}
  112. */
  113. onMouseDown:function (event) {
  114. return false;
  115. },
  116. /**
  117. * <p>called when the "mouseDragged" event is received. <br/>
  118. * Return YES to avoid propagating the event to other delegates.</p>
  119. * @param {cc.Mouse} event
  120. * @return {Boolean}
  121. */
  122. onMouseDragged:function (event) {
  123. return false;
  124. },
  125. /**
  126. * <p> called when the "mouseMoved" event is received. <br/>
  127. * Return YES to avoid propagating the event to other delegates. </p>
  128. * @param {cc.Mouse} event
  129. * @return {Boolean}
  130. */
  131. onMouseMoved:function (event) {
  132. return false;
  133. },
  134. /**
  135. * <p> called when the "mouseUp" event is received. <br/>
  136. * Return YES to avoid propagating the event to other delegates. </p>
  137. * @param {cc.Mouse} event
  138. * @return {Boolean}
  139. */
  140. onMouseUp:function (event) {
  141. return false;
  142. },
  143. //right
  144. /**
  145. * <p> called when the "rightMouseDown" event is received. <br/>
  146. * Return YES to avoid propagating the event to other delegates. </p>
  147. * @param {cc.Mouse} event
  148. * @return {Boolean}
  149. */
  150. onRightMouseDown:function (event) {
  151. return false;
  152. },
  153. /**
  154. * <p> called when the "rightMouseDragged" event is received. <br/>
  155. * Return YES to avoid propagating the event to other delegates. </p>
  156. * @param {cc.Mouse} event
  157. * @return {Boolean}
  158. */
  159. onRightMouseDragged:function (event) {
  160. return false;
  161. },
  162. /**
  163. * <p> called when the "rightMouseUp" event is received. <br/>
  164. * Return YES to avoid propagating the event to other delegates. </p>
  165. * @param {cc.Mouse} event
  166. * @return {Boolean}
  167. */
  168. onRightMouseUp:function (event) {
  169. return false;
  170. },
  171. //other
  172. /**
  173. * <p>called when the "otherMouseDown" event is received. <br/>
  174. * Return YES to avoid propagating the event to other delegates. </p>
  175. * @param {cc.Mouse} event
  176. * @return {Boolean}
  177. */
  178. onOtherMouseDown:function (event) {
  179. return false;
  180. },
  181. /**
  182. * <p> called when the "otherMouseDragged" event is received. <br/>
  183. * Return YES to avoid propagating the event to other delegates. </p>
  184. * @param {cc.Mouse} event
  185. * @return {Boolean}
  186. */
  187. onOtherMouseDragged:function (event) {
  188. return false;
  189. },
  190. /**
  191. * <p> called when the "otherMouseUp" event is received. <br/>
  192. * Return YES to avoid propagating the event to other delegates. </p>
  193. * @param {cc.Mouse} event
  194. * @return {Boolean}
  195. */
  196. onOtherMouseUp:function (event) {
  197. return false;
  198. },
  199. //scroll wheel
  200. /**
  201. * <p> called when the "scrollWheel" 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. onScrollWheel:function (event) {
  207. return false;
  208. },
  209. // enter / exit
  210. /**
  211. * <p> called when the "mouseEntered" event is received. <br/>
  212. * Return YES to avoid propagating the event to other delegates. </p>
  213. * @param {cc.Mouse} theEvent
  214. * @return {Boolean}
  215. */
  216. onMouseEntered:function (theEvent) {
  217. return false;
  218. },
  219. /**
  220. * <p> called when the "mouseExited" event is received. <br/>
  221. * Return YES to avoid propagating the event to other delegates. </p>
  222. * @param {cc.Mouse} theEvent
  223. * @return {Boolean}
  224. */
  225. onMouseExited:function (theEvent) {
  226. return false;
  227. }
  228. });
  229. /**
  230. * The data of Mouse event
  231. * @class
  232. * @extends cc.Touch
  233. */
  234. cc.Mouse = cc.Touch.extend(/** @lends cc.Mouse# */{
  235. _wheelDelta: 0,
  236. _button: cc.MOUSE_LEFTBUTTON,
  237. /**
  238. * Gets mouse wheel delta
  239. * @returns {number}
  240. */
  241. getWheelDelta: function () {
  242. return this._wheelDelta;
  243. },
  244. /**
  245. * Sets mouse wheel delta
  246. * @param delta
  247. */
  248. setWheelDelta: function (delta) {
  249. this._wheelDelta = delta;
  250. },
  251. /**
  252. * Gets mouse button
  253. * @returns {number}
  254. */
  255. getButton: function () {
  256. return this._button;
  257. },
  258. /**
  259. * Sets mouse button
  260. * @param {number} button
  261. */
  262. setButton: function (button) {
  263. this._button = button;
  264. }
  265. });
  266. /**
  267. * cc.MouseHandler
  268. * Object than contains the delegate and priority of the event handler.
  269. * @class
  270. * @extends cc.Class
  271. */
  272. cc.MouseHandler = cc.Class.extend(/** @lends cc.MouseHandler# */{
  273. _delegate:null,
  274. _priority:0,
  275. _enabledSelectors:0,
  276. /**
  277. * @return {cc.MouseEventDelegate}
  278. */
  279. getDelegate:function () {
  280. return this._delegate;
  281. },
  282. /**
  283. * @param {cc.TouchDelegate} delegate
  284. */
  285. setDelegate:function (delegate) {
  286. this._delegate = delegate;
  287. },
  288. /**
  289. * @return {Number}
  290. */
  291. getPriority:function () {
  292. return this._priority;
  293. },
  294. /**
  295. * @param {Number} priority
  296. */
  297. setPriority:function (priority) {
  298. this._priority = priority;
  299. },
  300. /**
  301. * Enabled selectors
  302. * @return {Number}
  303. */
  304. getEnabledSelectors:function () {
  305. return this._enabledSelectors;
  306. },
  307. /**
  308. * @param {Number} value
  309. */
  310. setEnalbedSelectors:function (value) {
  311. this._enabledSelectors = value;
  312. },
  313. initWithDelegate:function (delegate, priority) {
  314. this._delegate = delegate;
  315. this._priority = priority;
  316. }
  317. });
  318. cc.MouseHandler.create = function (delegate, priority) {
  319. var handler = new cc.MouseHandler();
  320. handler.initWithDelegate(delegate, priority);
  321. return handler;
  322. };
  323. /**
  324. * cc.MouseDispatcher. <br/>
  325. * Singleton that handles all the mouse events.
  326. * @class
  327. * @extends cc.Class
  328. */
  329. cc.MouseDispatcher = cc.Class.extend(/** @lends cc.MouseDispatcher# */{
  330. _mousePressed:false,
  331. _rightMousePressed:false,
  332. _mouseDelegateHandlers:null,
  333. _dispatchEvents:false,
  334. init:function () {
  335. this._dispatchEvents = true;
  336. this._mouseDelegateHandlers = [];
  337. this._mousePressed = false;
  338. this._rightMousePressed = false;
  339. cc.MouseDispatcher._registerHtmlElementEvent(cc.canvas);
  340. return true;
  341. },
  342. _setMousePressed:function (pressed) {
  343. this._mousePressed = pressed;
  344. },
  345. _getMousePressed:function () {
  346. return this._mousePressed;
  347. },
  348. _setRightMousePressed:function (pressed) {
  349. this._rightMousePressed = pressed;
  350. },
  351. _getRightMousePressed:function () {
  352. return this._rightMousePressed;
  353. },
  354. /**
  355. * Adds a mouse delegate to the dispatcher's list. <br/>
  356. * Delegates with a lower priority value will be called before higher priority values. <br/>
  357. * All the events will be propagated to all the delegates, unless the one delegate returns YES. </br>
  358. * @param delegate
  359. * @param priority
  360. */
  361. addMouseDelegate:function (delegate, priority) {
  362. var handler = cc.MouseHandler.create(delegate, priority);
  363. this._mouseDelegateHandlers = this.forceAddHandler(handler, this._mouseDelegateHandlers);
  364. },
  365. /**
  366. * Force add handler
  367. * @param {cc.TouchHandler} handler
  368. * @param {Array} array
  369. * @return {Array}
  370. */
  371. forceAddHandler:function (handler, array) {
  372. var u = 0;
  373. for (var i = 0; i < array.length; i++) {
  374. var h = array[i];
  375. if (h) {
  376. if (h.getPriority() < handler.getPriority())
  377. ++u;
  378. if (h.getDelegate() == handler.getDelegate()) {
  379. cc.log("cc.MouseDispatcher.forceAddHandler(): handler has been added.") ;
  380. return array;
  381. }
  382. }
  383. }
  384. return cc.ArrayAppendObjectToIndex(array, handler, u);
  385. },
  386. /**
  387. * removes a mouse delegate
  388. * @param delegate
  389. */
  390. removeMouseDelegate:function (delegate) {
  391. if (delegate == null)
  392. return;
  393. for (var i = 0; i < this._mouseDelegateHandlers.length; i++) {
  394. var handler = this._mouseDelegateHandlers[i];
  395. if (handler && handler.getDelegate() == delegate) {
  396. cc.ArrayRemoveObject(this._mouseDelegateHandlers, handler);
  397. break;
  398. }
  399. }
  400. },
  401. _findHandler:function (delegate) {
  402. for (var i = 0; i < this._mouseDelegateHandlers.length; i++) {
  403. if (this._mouseDelegateHandlers[i] && this._mouseDelegateHandlers[i].getDelegate() == delegate) {
  404. return this._mouseDelegateHandlers[i];
  405. }
  406. }
  407. return null;
  408. },
  409. setPriority:function (priority, delegate) {
  410. if(!delegate)
  411. throw "cc.MouseDispatcher.setPriority(): delegate should be non-null";
  412. var handler = this._findHandler(delegate);
  413. if(!handler) {
  414. cc.log("cc.MouseDispatcher.setPriority(): Can't find MouseHandler in array");
  415. return;
  416. }
  417. if (handler.getPriority() != priority) {
  418. handler.setPriority(priority);
  419. this._mouseDelegateHandlers.sort(cc.less);
  420. }
  421. },
  422. /**
  423. * Removes all mouse delegates, releasing all the delegates
  424. */
  425. removeAllMouseDelegates:function () {
  426. this._mouseDelegateHandlers.length = 0;
  427. },
  428. mouseHandle:function (mouseObj, event, index) {
  429. for (var i = 0; i < this._mouseDelegateHandlers.length; i++) {
  430. var handler = this._mouseDelegateHandlers[i];
  431. switch (index) {
  432. case cc.MOUSE_DOWN:
  433. if (mouseObj.getButton() == cc.MOUSE_RIGHTBUTTON) {
  434. if (handler.getDelegate().onRightMouseDown)
  435. handler.getDelegate().onRightMouseDown(mouseObj);
  436. } else {
  437. if (handler.getDelegate().onMouseDown)
  438. handler.getDelegate().onMouseDown(mouseObj);
  439. }
  440. break;
  441. case cc.MOUSE_UP:
  442. if (mouseObj.getButton() == cc.MOUSE_RIGHTBUTTON) {
  443. if (handler.getDelegate().onRightMouseUp)
  444. handler.getDelegate().onRightMouseUp(mouseObj);
  445. } else {
  446. if (handler.getDelegate().onMouseUp)
  447. handler.getDelegate().onMouseUp(mouseObj);
  448. }
  449. break;
  450. case cc.MOUSE_MOVED:
  451. if (this._mousePressed) {
  452. if (handler.getDelegate().onMouseDragged)
  453. handler.getDelegate().onMouseDragged(mouseObj);
  454. } else if (this._rightMousePressed) {
  455. if (handler.getDelegate().onRightMouseDragged)
  456. handler.getDelegate().onRightMouseDragged(mouseObj);
  457. } else {
  458. if (handler.getDelegate().onMouseMoved)
  459. handler.getDelegate().onMouseMoved(mouseObj);
  460. }
  461. break;
  462. case cc.MOUSE_ENTERED:
  463. if (handler.getDelegate().onMouseEntered)
  464. handler.getDelegate().onMouseEntered(mouseObj);
  465. break;
  466. case cc.MOUSE_EXITED:
  467. if (handler.getDelegate().onMouseExited)
  468. handler.getDelegate().onMouseExited(mouseObj);
  469. break;
  470. case cc.SCROLL_WHEEL:
  471. if (handler.getDelegate().onScrollWheel)
  472. handler.getDelegate().onScrollWheel(mouseObj);
  473. break;
  474. }
  475. }
  476. }
  477. });
  478. cc.MouseDispatcher._preMousePoint = cc.p(0, 0);
  479. cc.MouseDispatcher._isRegisterEvent = false;
  480. cc.MouseDispatcher._registerHtmlElementEvent = function (element) {
  481. if (cc.MouseDispatcher._isRegisterEvent)
  482. return;
  483. window.addEventListener('mousedown', function (event) {
  484. if (event.button == cc.MOUSE_RIGHTBUTTON) {
  485. cc.Director.getInstance().getMouseDispatcher()._setRightMousePressed(true);
  486. } else {
  487. cc.Director.getInstance().getMouseDispatcher()._setMousePressed(true);
  488. }
  489. });
  490. window.addEventListener('mouseup', function (event) {
  491. if (event.button == cc.MOUSE_RIGHTBUTTON) {
  492. cc.Director.getInstance().getMouseDispatcher()._setRightMousePressed(false);
  493. } else {
  494. cc.Director.getInstance().getMouseDispatcher()._setMousePressed(false);
  495. }
  496. });
  497. function getMouseByEvent(event) {
  498. var pos = cc.getHTMLElementPosition(element);
  499. var tx = event.pageX;
  500. var ty = event.pageY;
  501. var eglViewer = cc.EGLView.getInstance();
  502. var pixelRatio = eglViewer.getDevicePixelRatio();
  503. var mouseX = (tx - pos.left) * pixelRatio / eglViewer.getScaleX();
  504. var mouseY = (pos.height - (ty - pos.top)) * pixelRatio / eglViewer.getScaleY();
  505. var mouse = new cc.Mouse(mouseX, mouseY);
  506. mouse._setPrevPoint(cc.MouseDispatcher._preMousePoint.x, cc.MouseDispatcher._preMousePoint.y);
  507. mouse.setButton(event.button);
  508. cc.MouseDispatcher._preMousePoint.x = mouseX;
  509. cc.MouseDispatcher._preMousePoint.y = mouseY;
  510. return mouse;
  511. }
  512. //register canvas mouse event
  513. element.addEventListener("mousedown", function (event) {
  514. cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_DOWN);
  515. });
  516. element.addEventListener("mouseup", function (event) {
  517. cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_UP);
  518. });
  519. element.addEventListener("mousemove", function (event) {
  520. cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_MOVED);
  521. });
  522. element.addEventListener("mousewheel", function (event) {
  523. var mouse = getMouseByEvent(event);
  524. mouse.setWheelDelta(event.wheelDelta);
  525. cc.Director.getInstance().getMouseDispatcher().mouseHandle(mouse, event, cc.SCROLL_WHEEL);
  526. }, false);
  527. /* firefox fix */
  528. element.addEventListener("DOMMouseScroll", function(event) {
  529. var mouse = getMouseByEvent(event);
  530. mouse.setWheelDelta(event.detail * -120);
  531. cc.Director.getInstance().getMouseDispatcher().mouseHandle(mouse, event, cc.SCROLL_WHEEL);
  532. });
  533. element.addEventListener("mouseout", function (event) {
  534. cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_EXITED);
  535. }, false);
  536. element.addEventListener("mouseover", function (event) {
  537. cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_ENTERED);
  538. }, false);
  539. };