You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

328 rivejä
6.9 KiB

  1. define([
  2. 'js/system/events',
  3. 'js/rendering/renderer'
  4. ], function (
  5. events,
  6. renderer
  7. ) {
  8. return {
  9. axes: {
  10. horizontal: {
  11. negative: ['left', 'a', 'q', 'z'],
  12. positive: ['right', 'd', 'e', 'c']
  13. },
  14. vertical: {
  15. negative: ['up', 'w', 'q', 'e'],
  16. positive: ['down', 's', 'x', 'z', 'c']
  17. }
  18. },
  19. //Certain keys should always register even if they don't get emitted
  20. modifiers: [
  21. 'shift', 'ctrl'
  22. ],
  23. numericalKeyCodeMappings: {
  24. Digit1: 49,
  25. Digit2: 50,
  26. Digit3: 51,
  27. Digit4: 52,
  28. Digit5: 53
  29. },
  30. mappings: {
  31. 8: 'backspace',
  32. 9: 'tab',
  33. 13: 'enter',
  34. 16: 'shift',
  35. 17: 'ctrl',
  36. 27: 'esc',
  37. 37: 'left',
  38. 38: 'up',
  39. 39: 'right',
  40. 40: 'down',
  41. 46: 'del',
  42. //hacks for mac cmd key
  43. 224: 'ctrl',
  44. 91: 'ctrl',
  45. 93: 'ctrl'
  46. },
  47. mouse: {
  48. button: null,
  49. x: 0,
  50. y: 0
  51. },
  52. mouseRaw: null,
  53. keys: {},
  54. enabled: true,
  55. blacklistedKeys: [],
  56. whitelistedKeys: [],
  57. init: function () {
  58. $(window).on('keydown', this.events.keyboard.keyDown.bind(this));
  59. $(window).on('keyup', this.events.keyboard.keyUp.bind(this));
  60. events.on('onSceneMove', this.events.mouse.mouseMove.bind(this));
  61. $('.ui-container')
  62. .on('mousedown', this.events.mouse.mouseDown.bind(this))
  63. .on('mouseup', this.events.mouse.mouseUp.bind(this))
  64. .on('mousemove', this.events.mouse.mouseMove.bind(this))
  65. .on('touchstart', this.events.touch.touchStart.bind(this))
  66. .on('touchmove', this.events.touch.touchMove.bind(this))
  67. .on('touchend', this.events.touch.touchEnd.bind(this))
  68. .on('touchcancel', this.events.touch.touchCancel.bind(this));
  69. if (isMobile)
  70. require(['plugins/shake.js'], this.onLoadShake.bind(this));
  71. },
  72. blacklistKeys: function (list) {
  73. this.blacklistedKeys.push(...list);
  74. },
  75. unBlacklistKeys: function (list) {
  76. this.blacklistedKeys.spliceWhere(d => list.includes(d));
  77. },
  78. whitelistKeys: function (list) {
  79. this.whitelistedKeys.push(...list);
  80. },
  81. unWhitelistKeys: function (list) {
  82. this.whitelistedKeys.spliceWhere(d => list.includes(d));
  83. },
  84. onLoadShake: function (shake) {
  85. let shaker = new shake({
  86. threshold: 5,
  87. timeout: 1000
  88. });
  89. shaker.start();
  90. window.addEventListener('shake', this.events.mobile.onShake.bind(this), false);
  91. },
  92. resetKeys: function () {
  93. for (let k in this.keys)
  94. events.emit('onKeyUp', k);
  95. this.keys = {};
  96. },
  97. getMapping: function (charCode) {
  98. if (charCode >= 97)
  99. return (charCode - 96).toString();
  100. return (
  101. this.mappings[charCode] ||
  102. String.fromCharCode(charCode).toLowerCase()
  103. );
  104. },
  105. isKeyDown: function (key, noConsume) {
  106. if (this.keys.has(key)) {
  107. if (noConsume)
  108. return true;
  109. let down = this.keys[key];
  110. this.keys[key] = 2;
  111. return (down === 1);
  112. } return false;
  113. },
  114. getAxis: function (axisName) {
  115. let axis = this.axes[axisName];
  116. if (!axis)
  117. return 0;
  118. let result = 0;
  119. for (let i = 0; i < axis.negative.length; i++) {
  120. if (this.keys[axis.negative[i]]) {
  121. result--;
  122. break;
  123. }
  124. }
  125. for (let i = 0; i < axis.positive.length; i++) {
  126. if (this.keys[axis.positive[i]]) {
  127. result++;
  128. break;
  129. }
  130. }
  131. return result;
  132. },
  133. events: {
  134. keyboard: {
  135. /* eslint-disable-next-line max-lines-per-function */
  136. keyDown: function (e) {
  137. if (!this.enabled)
  138. return;
  139. let code = this.numericalKeyCodeMappings[e.code] || e.which;
  140. let key = this.getMapping(code);
  141. let isModifier = this.modifiers.indexOf(key) > -1;
  142. let isBody = e.target === document.body;
  143. if (!isModifier && !isBody)
  144. return true;
  145. if ((e.keyCode === 9) || (e.keyCode === 8) || (e.keyCode === 122))
  146. e.preventDefault();
  147. const allowKey = (
  148. key.length > 1 ||
  149. this.whitelistedKeys.includes(key) ||
  150. (
  151. !this.blacklistedKeys.includes(key) &&
  152. !this.blacklistedKeys.includes('*')
  153. )
  154. );
  155. if (!allowKey)
  156. return;
  157. if (this.keys.has(key))
  158. this.keys[key] = 2;
  159. else {
  160. this.keys[key] = 1;
  161. if (isBody || isModifier) {
  162. let keyEvent = {
  163. key: key,
  164. consumed: false
  165. };
  166. events.emit('onUiKeyDown', keyEvent);
  167. if (!keyEvent.consumed)
  168. events.emit('onCanvasKeyDown', keyEvent);
  169. events.emit('onKeyDown', key);
  170. }
  171. }
  172. if (key === 'backspace')
  173. return false;
  174. else if (e.key === 'F11')
  175. events.emit('onToggleFullscreen');
  176. },
  177. keyUp: function (e) {
  178. if (!this.enabled)
  179. return;
  180. let key = this.getMapping(e.which);
  181. let isModifier = this.modifiers.indexOf(key) > -1;
  182. let isBody = e.target === document.body;
  183. if (!isModifier && !isBody)
  184. return;
  185. delete this.keys[key];
  186. events.emit('onKeyUp', key);
  187. }
  188. },
  189. mouse: {
  190. mouseDown: function (e) {
  191. let el = $(e.target);
  192. if ((!el.hasClass('ui-container')) || (el.hasClass('blocking')))
  193. return;
  194. let button = e.button;
  195. this.mouse.button = button;
  196. this.mouse.down = true;
  197. this.mouse.event = e;
  198. //This is needed for casting targetted spells on Mobile...it's hacky.
  199. this.mouse.worldX = e.pageX + renderer.pos.x;
  200. this.mouse.worldY = e.pageY + renderer.pos.y;
  201. events.emit('mouseDown', this.mouse);
  202. },
  203. mouseUp: function (e) {
  204. let el = $(e.target);
  205. if ((!el.hasClass('ui-container')) || (el.hasClass('blocking')))
  206. return;
  207. this.mouse.button = null;
  208. this.mouse.down = false;
  209. events.emit('mouseUp', this.mouse);
  210. },
  211. mouseMove: function (e) {
  212. if (e)
  213. this.mouseRaw = e;
  214. else
  215. e = this.mouseRaw;
  216. if (!e)
  217. return;
  218. let el = $(e.target);
  219. if ((!el.hasClass('ui-container')) || (el.hasClass('blocking')))
  220. return;
  221. this.mouse.x = e.offsetX + renderer.pos.x;
  222. this.mouse.y = e.offsetY + renderer.pos.y;
  223. }
  224. },
  225. touch: {
  226. touchStart: function (e) {
  227. let el = $(e.target);
  228. if ((!el.hasClass('ui-container')) || (el.hasClass('blocking')))
  229. return;
  230. let touch = e.touches[0];
  231. events.emit('onTouchStart', {
  232. x: touch.clientX,
  233. y: touch.clientY,
  234. worldX: touch.clientX + renderer.pos.x,
  235. worldY: touch.clientY + renderer.pos.y
  236. });
  237. },
  238. touchMove: function (e) {
  239. let el = $(e.target);
  240. if ((!el.hasClass('ui-container')) || (el.hasClass('blocking')))
  241. return;
  242. let touch = e.touches[0];
  243. events.emit('onTouchMove', {
  244. x: touch.clientX,
  245. y: touch.clientY,
  246. touches: e.touches.length
  247. });
  248. },
  249. touchEnd: function (e) {
  250. let el = $(e.target);
  251. if ((!el.hasClass('ui-container')) || (el.hasClass('blocking')))
  252. return;
  253. events.emit('onTouchEnd');
  254. },
  255. touchCancel: function (e) {
  256. let el = $(e.target);
  257. if ((!el.hasClass('ui-container')) || (el.hasClass('blocking')))
  258. return;
  259. events.emit('onTouchCancel');
  260. }
  261. },
  262. mobile: {
  263. onShake: function (e) {
  264. events.emit('onShake', e);
  265. }
  266. }
  267. }
  268. };
  269. });