@al8b/input 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +25 -0
  2. package/dist/core/input-manager.d.mts +25 -0
  3. package/dist/core/input-manager.d.ts +25 -0
  4. package/dist/core/input-manager.js +724 -0
  5. package/dist/core/input-manager.js.map +1 -0
  6. package/dist/core/input-manager.mjs +701 -0
  7. package/dist/core/input-manager.mjs.map +1 -0
  8. package/dist/devices/gamepad.d.mts +24 -0
  9. package/dist/devices/gamepad.d.ts +24 -0
  10. package/dist/devices/gamepad.js +244 -0
  11. package/dist/devices/gamepad.js.map +1 -0
  12. package/dist/devices/gamepad.mjs +221 -0
  13. package/dist/devices/gamepad.mjs.map +1 -0
  14. package/dist/devices/keyboard.d.mts +16 -0
  15. package/dist/devices/keyboard.d.ts +16 -0
  16. package/dist/devices/keyboard.js +131 -0
  17. package/dist/devices/keyboard.js.map +1 -0
  18. package/dist/devices/keyboard.mjs +106 -0
  19. package/dist/devices/keyboard.mjs.map +1 -0
  20. package/dist/devices/mouse.d.mts +21 -0
  21. package/dist/devices/mouse.d.ts +21 -0
  22. package/dist/devices/mouse.js +207 -0
  23. package/dist/devices/mouse.js.map +1 -0
  24. package/dist/devices/mouse.mjs +182 -0
  25. package/dist/devices/mouse.mjs.map +1 -0
  26. package/dist/devices/touch.d.mts +22 -0
  27. package/dist/devices/touch.d.ts +22 -0
  28. package/dist/devices/touch.js +186 -0
  29. package/dist/devices/touch.js.map +1 -0
  30. package/dist/devices/touch.mjs +161 -0
  31. package/dist/devices/touch.mjs.map +1 -0
  32. package/dist/index.d.mts +6 -0
  33. package/dist/index.d.ts +6 -0
  34. package/dist/index.js +735 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/index.mjs +706 -0
  37. package/dist/index.mjs.map +1 -0
  38. package/dist/shared/constants.d.mts +6 -0
  39. package/dist/shared/constants.d.ts +6 -0
  40. package/dist/shared/constants.js +40 -0
  41. package/dist/shared/constants.js.map +1 -0
  42. package/dist/shared/constants.mjs +12 -0
  43. package/dist/shared/constants.mjs.map +1 -0
  44. package/dist/shared/utils.d.mts +9 -0
  45. package/dist/shared/utils.d.ts +9 -0
  46. package/dist/shared/utils.js +56 -0
  47. package/dist/shared/utils.js.map +1 -0
  48. package/dist/shared/utils.mjs +29 -0
  49. package/dist/shared/utils.mjs.map +1 -0
  50. package/dist/types/index.d.mts +41 -0
  51. package/dist/types/index.d.ts +41 -0
  52. package/dist/types/index.js +19 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/dist/types/index.mjs +1 -0
  55. package/dist/types/index.mjs.map +1 -0
  56. package/package.json +34 -0
@@ -0,0 +1,724 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/core/input-manager.ts
22
+ var input_manager_exports = {};
23
+ __export(input_manager_exports, {
24
+ Input: () => Input
25
+ });
26
+ module.exports = __toCommonJS(input_manager_exports);
27
+ var import_diagnostics = require("@al8b/diagnostics");
28
+
29
+ // src/devices/gamepad.ts
30
+ var createState = /* @__PURE__ */ __name(() => ({
31
+ press: {},
32
+ release: {}
33
+ }), "createState");
34
+ var BUTTONS_MAP = {
35
+ 0: "A",
36
+ 1: "B",
37
+ 2: "X",
38
+ 3: "Y",
39
+ 4: "LB",
40
+ 5: "RB",
41
+ 8: "VIEW",
42
+ 9: "MENU",
43
+ 10: "LS",
44
+ 11: "RS",
45
+ 12: "DPAD_UP",
46
+ 13: "DPAD_DOWN",
47
+ 14: "DPAD_LEFT",
48
+ 15: "DPAD_RIGHT"
49
+ };
50
+ var TRIGGERS_MAP = {
51
+ 6: "LT",
52
+ 7: "RT"
53
+ };
54
+ var ensureState = /* @__PURE__ */ __name((state) => {
55
+ if (!state) {
56
+ return createState();
57
+ }
58
+ state.press ??= {};
59
+ state.release ??= {};
60
+ return state;
61
+ }, "ensureState");
62
+ var GamepadInput = class {
63
+ static {
64
+ __name(this, "GamepadInput");
65
+ }
66
+ status;
67
+ previous;
68
+ count = 0;
69
+ constructor() {
70
+ this.status = createState();
71
+ this.previous = {
72
+ global: createState()
73
+ };
74
+ }
75
+ update() {
76
+ const pads = this.getGamepads();
77
+ if (!pads) {
78
+ this.count = 0;
79
+ return;
80
+ }
81
+ let padCount = 0;
82
+ for (let i = 0; i < pads.length; i++) {
83
+ const pad = pads[i];
84
+ if (!pad) {
85
+ break;
86
+ }
87
+ padCount++;
88
+ this.status[i] = ensureState(this.status[i]);
89
+ this.previous[i] = ensureState(this.previous[i]);
90
+ for (const [index, name] of Object.entries(BUTTONS_MAP)) {
91
+ const idx = Number(index);
92
+ const button = pad.buttons[idx];
93
+ if (button) {
94
+ this.status[i][name] = button.pressed ? 1 : 0;
95
+ }
96
+ }
97
+ for (const [index, name] of Object.entries(TRIGGERS_MAP)) {
98
+ const idx = Number(index);
99
+ const trigger = pad.buttons[idx];
100
+ if (trigger) {
101
+ this.status[i][name] = trigger.value ?? 0;
102
+ }
103
+ }
104
+ if (pad.axes.length >= 2) {
105
+ this.updateStick(pad.axes[0], -pad.axes[1], this.status[i], "LEFT");
106
+ }
107
+ if (pad.axes.length >= 4) {
108
+ this.updateStick(pad.axes[2], -pad.axes[3], this.status[i], "RIGHT");
109
+ }
110
+ }
111
+ this.aggregateStatus(pads, padCount);
112
+ this.count = padCount;
113
+ this.updateChanges(this.status, this.previous.global);
114
+ for (let i = 0; i < padCount; i++) {
115
+ this.updateChanges(this.status[i], this.previous[i]);
116
+ }
117
+ for (let i = padCount; i < 4; i++) {
118
+ delete this.status[i];
119
+ delete this.previous[i];
120
+ }
121
+ }
122
+ getGamepads() {
123
+ if (typeof navigator === "undefined" || !navigator.getGamepads) {
124
+ return null;
125
+ }
126
+ try {
127
+ return navigator.getGamepads();
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+ updateStick(x, y, target, prefix) {
133
+ const radius = Math.sqrt(x * x + y * y);
134
+ const angle = Math.floor((Math.atan2(y, x) + Math.PI * 2) % (Math.PI * 2) / (Math.PI * 2) * 360);
135
+ target[`${prefix}_STICK_ANGLE`] = angle;
136
+ target[`${prefix}_STICK_AMOUNT`] = radius;
137
+ target[`${prefix}_STICK_UP`] = y > 0.5 ? 1 : 0;
138
+ target[`${prefix}_STICK_DOWN`] = y < -0.5 ? 1 : 0;
139
+ target[`${prefix}_STICK_LEFT`] = x < -0.5 ? 1 : 0;
140
+ target[`${prefix}_STICK_RIGHT`] = x > 0.5 ? 1 : 0;
141
+ }
142
+ aggregateStatus(pads, padCount) {
143
+ for (const [index, name] of Object.entries(BUTTONS_MAP)) {
144
+ this.status[name] = 0;
145
+ const idx = Number(index);
146
+ for (const pad of pads) {
147
+ if (!pad) break;
148
+ if (pad.buttons[idx]?.pressed) {
149
+ this.status[name] = 1;
150
+ break;
151
+ }
152
+ }
153
+ }
154
+ for (const [index, name] of Object.entries(TRIGGERS_MAP)) {
155
+ this.status[name] = 0;
156
+ const idx = Number(index);
157
+ for (const pad of pads) {
158
+ if (!pad) break;
159
+ const button = pad.buttons[idx];
160
+ if (button) {
161
+ this.status[name] = button.value ?? 0;
162
+ }
163
+ }
164
+ }
165
+ this.status.UP = 0;
166
+ this.status.DOWN = 0;
167
+ this.status.LEFT = 0;
168
+ this.status.RIGHT = 0;
169
+ this.status.LEFT_STICK_UP = 0;
170
+ this.status.LEFT_STICK_DOWN = 0;
171
+ this.status.LEFT_STICK_LEFT = 0;
172
+ this.status.LEFT_STICK_RIGHT = 0;
173
+ this.status.RIGHT_STICK_UP = 0;
174
+ this.status.RIGHT_STICK_DOWN = 0;
175
+ this.status.RIGHT_STICK_LEFT = 0;
176
+ this.status.RIGHT_STICK_RIGHT = 0;
177
+ this.status.LEFT_STICK_ANGLE = 0;
178
+ this.status.LEFT_STICK_AMOUNT = 0;
179
+ this.status.RIGHT_STICK_ANGLE = 0;
180
+ this.status.RIGHT_STICK_AMOUNT = 0;
181
+ this.status.RT = 0;
182
+ this.status.LT = 0;
183
+ for (let i = 0; i < padCount; i++) {
184
+ const padState = this.status[i];
185
+ if (!padState) continue;
186
+ padState.UP = padState.DPAD_UP || padState.LEFT_STICK_UP || padState.RIGHT_STICK_UP || 0 ? 1 : 0;
187
+ padState.DOWN = padState.DPAD_DOWN || padState.LEFT_STICK_DOWN || padState.RIGHT_STICK_DOWN || 0 ? 1 : 0;
188
+ padState.LEFT = padState.DPAD_LEFT || padState.LEFT_STICK_LEFT || padState.RIGHT_STICK_LEFT || 0 ? 1 : 0;
189
+ padState.RIGHT = padState.DPAD_RIGHT || padState.LEFT_STICK_RIGHT || padState.RIGHT_STICK_RIGHT || 0 ? 1 : 0;
190
+ if (padState.UP) this.status.UP = 1;
191
+ if (padState.DOWN) this.status.DOWN = 1;
192
+ if (padState.LEFT) this.status.LEFT = 1;
193
+ if (padState.RIGHT) this.status.RIGHT = 1;
194
+ if (padState.LEFT_STICK_UP) this.status.LEFT_STICK_UP = 1;
195
+ if (padState.LEFT_STICK_DOWN) this.status.LEFT_STICK_DOWN = 1;
196
+ if (padState.LEFT_STICK_LEFT) this.status.LEFT_STICK_LEFT = 1;
197
+ if (padState.LEFT_STICK_RIGHT) this.status.LEFT_STICK_RIGHT = 1;
198
+ if (padState.RIGHT_STICK_UP) this.status.RIGHT_STICK_UP = 1;
199
+ if (padState.RIGHT_STICK_DOWN) this.status.RIGHT_STICK_DOWN = 1;
200
+ if (padState.RIGHT_STICK_LEFT) this.status.RIGHT_STICK_LEFT = 1;
201
+ if (padState.RIGHT_STICK_RIGHT) this.status.RIGHT_STICK_RIGHT = 1;
202
+ if (padState.LT) this.status.LT = padState.LT;
203
+ if (padState.RT) this.status.RT = padState.RT;
204
+ if ((padState.LEFT_STICK_AMOUNT ?? 0) > (this.status.LEFT_STICK_AMOUNT ?? 0)) {
205
+ this.status.LEFT_STICK_AMOUNT = padState.LEFT_STICK_AMOUNT;
206
+ this.status.LEFT_STICK_ANGLE = padState.LEFT_STICK_ANGLE;
207
+ }
208
+ if ((padState.RIGHT_STICK_AMOUNT ?? 0) > (this.status.RIGHT_STICK_AMOUNT ?? 0)) {
209
+ this.status.RIGHT_STICK_AMOUNT = padState.RIGHT_STICK_AMOUNT;
210
+ this.status.RIGHT_STICK_ANGLE = padState.RIGHT_STICK_ANGLE;
211
+ }
212
+ }
213
+ }
214
+ updateChanges(current, previous) {
215
+ for (const key in current.press) {
216
+ current.press[key] = 0;
217
+ }
218
+ for (const key in current.release) {
219
+ current.release[key] = 0;
220
+ }
221
+ for (const key in previous) {
222
+ if (key === "press" || key === "release") continue;
223
+ if (previous[key] && !current[key]) {
224
+ current.release[key] = 1;
225
+ }
226
+ }
227
+ for (const key in current) {
228
+ if (key === "press" || key === "release") continue;
229
+ if (current[key] && !previous[key]) {
230
+ current.press[key] = 1;
231
+ }
232
+ }
233
+ for (const key in previous) {
234
+ if (key === "press" || key === "release") continue;
235
+ previous[key] = 0;
236
+ }
237
+ for (const key in current) {
238
+ if (key === "press" || key === "release") continue;
239
+ previous[key] = current[key];
240
+ }
241
+ }
242
+ };
243
+
244
+ // src/shared/constants.ts
245
+ var NORMALIZED_SCALE = 200;
246
+ var OUT_OF_BOUNDS = -1e4;
247
+ var PREVENT_DEFAULT_REGEX = /Escape|(F\d+)/;
248
+ var TOUCH_MOUSE_ID = "mouse";
249
+
250
+ // src/shared/utils.ts
251
+ var hasDocument = typeof document !== "undefined";
252
+ var computeRelativePosition = /* @__PURE__ */ __name((canvas, clientX, clientY) => {
253
+ const rect = canvas.getBoundingClientRect();
254
+ const min = Math.min(canvas.clientWidth, canvas.clientHeight) || 1;
255
+ const x = (clientX - rect.left - canvas.clientWidth / 2) / min * NORMALIZED_SCALE;
256
+ const y = (canvas.clientHeight / 2 - (clientY - rect.top)) / min * NORMALIZED_SCALE;
257
+ return {
258
+ x,
259
+ y
260
+ };
261
+ }, "computeRelativePosition");
262
+
263
+ // src/devices/keyboard.ts
264
+ var KeyboardInput = class {
265
+ static {
266
+ __name(this, "KeyboardInput");
267
+ }
268
+ state = {
269
+ press: {},
270
+ release: {},
271
+ UP: 0,
272
+ DOWN: 0,
273
+ LEFT: 0,
274
+ RIGHT: 0
275
+ };
276
+ previous = {};
277
+ // Track only keys that changed since last update() — avoids O(n) iteration of all keys
278
+ dirtyKeys = /* @__PURE__ */ new Set();
279
+ constructor(target = hasDocument ? document : void 0) {
280
+ if (!target) {
281
+ return;
282
+ }
283
+ target.addEventListener("keydown", (event) => this.handleKeyDown(event));
284
+ target.addEventListener("keyup", (event) => this.handleKeyUp(event));
285
+ }
286
+ convertCode(code) {
287
+ let res = "";
288
+ let low = false;
289
+ for (let i = 0; i < code.length; i++) {
290
+ const c = code.charAt(i);
291
+ if (c === c.toUpperCase() && low) {
292
+ res += "_";
293
+ low = false;
294
+ } else {
295
+ low = true;
296
+ }
297
+ res += c.toUpperCase();
298
+ }
299
+ return res;
300
+ }
301
+ handleKeyDown(event) {
302
+ if (!(event.altKey || event.ctrlKey || event.metaKey || PREVENT_DEFAULT_REGEX.test(event.key))) {
303
+ event.preventDefault();
304
+ }
305
+ const codeKey = this.convertCode(event.code);
306
+ const upperKey = event.key.toUpperCase();
307
+ this.state[codeKey] = 1;
308
+ this.state[upperKey] = 1;
309
+ this.dirtyKeys.add(codeKey);
310
+ this.dirtyKeys.add(upperKey);
311
+ this.updateDirectional();
312
+ }
313
+ handleKeyUp(event) {
314
+ const codeKey = this.convertCode(event.code);
315
+ const upperKey = event.key.toUpperCase();
316
+ this.state[codeKey] = 0;
317
+ this.state[upperKey] = 0;
318
+ this.dirtyKeys.add(codeKey);
319
+ this.dirtyKeys.add(upperKey);
320
+ this.updateDirectional();
321
+ }
322
+ updateDirectional() {
323
+ this.state.UP = this.state.KEY_W || this.state.ARROW_UP || 0;
324
+ this.state.DOWN = this.state.KEY_S || this.state.ARROW_DOWN || 0;
325
+ this.state.LEFT = this.state.KEY_A || this.state.ARROW_LEFT || 0;
326
+ this.state.RIGHT = this.state.KEY_D || this.state.ARROW_RIGHT || 0;
327
+ }
328
+ update() {
329
+ for (const key of this.dirtyKeys) {
330
+ if (this.state.press[key]) this.state.press[key] = 0;
331
+ if (this.state.release[key]) this.state.release[key] = 0;
332
+ }
333
+ for (const key of this.dirtyKeys) {
334
+ const current = this.state[key];
335
+ const prev = this.previous[key] || 0;
336
+ if (current && !prev) {
337
+ this.state.press[key] = 1;
338
+ } else if (!current && prev) {
339
+ this.state.release[key] = 1;
340
+ }
341
+ this.previous[key] = current;
342
+ }
343
+ this.dirtyKeys.clear();
344
+ }
345
+ reset() {
346
+ for (const key in this.state) {
347
+ if (key === "press" || key === "release") continue;
348
+ this.state[key] = 0;
349
+ }
350
+ for (const key in this.previous) {
351
+ this.previous[key] = 0;
352
+ }
353
+ this.dirtyKeys.clear();
354
+ }
355
+ };
356
+
357
+ // src/devices/mouse.ts
358
+ var MouseInput = class {
359
+ static {
360
+ __name(this, "MouseInput");
361
+ }
362
+ state = {
363
+ x: OUT_OF_BOUNDS,
364
+ y: OUT_OF_BOUNDS,
365
+ pressed: 0,
366
+ left: 0,
367
+ middle: 0,
368
+ right: 0,
369
+ press: 0,
370
+ release: 0,
371
+ wheel: 0
372
+ };
373
+ previousPressed = false;
374
+ wheel = 0;
375
+ canvas;
376
+ removeListeners;
377
+ constructor(canvas) {
378
+ if (canvas) {
379
+ this.setCanvas(canvas);
380
+ }
381
+ }
382
+ setCanvas(canvas) {
383
+ this.detach();
384
+ this.canvas = canvas;
385
+ this.attach();
386
+ }
387
+ syncFromTouch(x, y, touching) {
388
+ this.state.x = x;
389
+ this.state.y = y;
390
+ if (touching) {
391
+ this.state.left = 1;
392
+ this.state.middle = 0;
393
+ this.state.right = 0;
394
+ this.state.pressed = 1;
395
+ } else {
396
+ this.state.left = 0;
397
+ this.state.middle = 0;
398
+ this.state.right = 0;
399
+ this.state.pressed = 0;
400
+ }
401
+ }
402
+ update() {
403
+ if (this.state.pressed && !this.previousPressed) {
404
+ this.previousPressed = true;
405
+ this.state.press = 1;
406
+ } else {
407
+ this.state.press = 0;
408
+ }
409
+ if (!this.state.pressed && this.previousPressed) {
410
+ this.previousPressed = false;
411
+ this.state.release = 1;
412
+ } else {
413
+ this.state.release = 0;
414
+ }
415
+ this.state.wheel = this.wheel;
416
+ this.wheel = 0;
417
+ }
418
+ attach() {
419
+ if (!hasDocument) {
420
+ return;
421
+ }
422
+ const target = document;
423
+ const onDown = /* @__PURE__ */ __name((event) => this.handleMouseDown(event), "onDown");
424
+ const onMove = /* @__PURE__ */ __name((event) => this.handleMouseMove(event), "onMove");
425
+ const onUp = /* @__PURE__ */ __name((event) => this.handleMouseUp(event), "onUp");
426
+ const onWheel = /* @__PURE__ */ __name((event) => this.handleWheel(event), "onWheel");
427
+ const onDomWheel = /* @__PURE__ */ __name((event) => this.handleWheel(event), "onDomWheel");
428
+ target.addEventListener("mousedown", onDown, {
429
+ passive: false
430
+ });
431
+ target.addEventListener("mousemove", onMove, {
432
+ passive: false
433
+ });
434
+ target.addEventListener("mouseup", onUp, {
435
+ passive: false
436
+ });
437
+ target.addEventListener("mousewheel", onWheel, {
438
+ passive: false
439
+ });
440
+ target.addEventListener("DOMMouseScroll", onDomWheel, {
441
+ passive: false
442
+ });
443
+ this.removeListeners = () => {
444
+ target.removeEventListener("mousedown", onDown);
445
+ target.removeEventListener("mousemove", onMove);
446
+ target.removeEventListener("mouseup", onUp);
447
+ target.removeEventListener("mousewheel", onWheel);
448
+ target.removeEventListener("DOMMouseScroll", onDomWheel);
449
+ };
450
+ }
451
+ detach() {
452
+ this.removeListeners?.();
453
+ this.removeListeners = void 0;
454
+ this.canvas = void 0;
455
+ }
456
+ handleMouseDown(event) {
457
+ if (!this.canvas) return;
458
+ event.preventDefault();
459
+ const { x, y } = computeRelativePosition(this.canvas, event.clientX, event.clientY);
460
+ this.state.x = x;
461
+ this.state.y = y;
462
+ switch (event.button) {
463
+ case 0:
464
+ this.state.left = 1;
465
+ break;
466
+ case 1:
467
+ this.state.middle = 1;
468
+ break;
469
+ case 2:
470
+ this.state.right = 1;
471
+ break;
472
+ }
473
+ this.state.pressed = Math.min(1, this.state.left + this.state.right + this.state.middle);
474
+ }
475
+ handleMouseMove(event) {
476
+ if (!this.canvas) return;
477
+ event.preventDefault();
478
+ const { x, y } = computeRelativePosition(this.canvas, event.clientX, event.clientY);
479
+ this.state.x = x;
480
+ this.state.y = y;
481
+ }
482
+ handleMouseUp(event) {
483
+ if (!this.canvas) return;
484
+ event.preventDefault();
485
+ const { x, y } = computeRelativePosition(this.canvas, event.clientX, event.clientY);
486
+ this.state.x = x;
487
+ this.state.y = y;
488
+ switch (event.button) {
489
+ case 0:
490
+ this.state.left = 0;
491
+ break;
492
+ case 1:
493
+ this.state.middle = 0;
494
+ break;
495
+ case 2:
496
+ this.state.right = 0;
497
+ break;
498
+ }
499
+ this.state.pressed = Math.min(1, this.state.left + this.state.right + this.state.middle);
500
+ }
501
+ handleWheel(event) {
502
+ const wheelEvent = event;
503
+ if (typeof wheelEvent.deltaY === "number" && wheelEvent.deltaY !== 0) {
504
+ this.wheel = wheelEvent.deltaY > 0 ? -1 : 1;
505
+ } else if (typeof wheelEvent.wheelDelta === "number" && wheelEvent.wheelDelta !== 0) {
506
+ this.wheel = wheelEvent.wheelDelta < 0 ? -1 : 1;
507
+ } else if (typeof wheelEvent.detail === "number" && wheelEvent.detail !== 0) {
508
+ this.wheel = wheelEvent.detail > 0 ? -1 : 1;
509
+ } else {
510
+ this.wheel = 0;
511
+ }
512
+ event.preventDefault();
513
+ }
514
+ };
515
+
516
+ // src/devices/touch.ts
517
+ var TouchInput = class {
518
+ static {
519
+ __name(this, "TouchInput");
520
+ }
521
+ mouse;
522
+ state = {
523
+ touching: 0,
524
+ x: 0,
525
+ y: 0,
526
+ press: 0,
527
+ release: 0,
528
+ touches: []
529
+ };
530
+ touches = /* @__PURE__ */ new Map();
531
+ previousTouching = false;
532
+ canvas;
533
+ removeListeners;
534
+ constructor(mouse, canvas) {
535
+ this.mouse = mouse;
536
+ if (canvas) {
537
+ this.setCanvas(canvas);
538
+ }
539
+ }
540
+ setCanvas(canvas) {
541
+ this.detach();
542
+ this.canvas = canvas;
543
+ this.attach();
544
+ }
545
+ update() {
546
+ this.syncMouseTouch();
547
+ const list = [];
548
+ for (const [id, { x, y }] of this.touches.entries()) {
549
+ list.push({
550
+ id,
551
+ x,
552
+ y
553
+ });
554
+ this.state.x = x;
555
+ this.state.y = y;
556
+ }
557
+ this.state.touches = list;
558
+ this.state.touching = this.touches.size > 0 ? 1 : 0;
559
+ if (this.state.touching && !this.previousTouching) {
560
+ this.previousTouching = true;
561
+ this.state.press = 1;
562
+ } else {
563
+ this.state.press = 0;
564
+ }
565
+ if (!this.state.touching && this.previousTouching) {
566
+ this.previousTouching = false;
567
+ this.state.release = 1;
568
+ } else {
569
+ this.state.release = 0;
570
+ }
571
+ }
572
+ syncMouseTouch() {
573
+ const mouseState = this.mouse.state;
574
+ if (mouseState.pressed) {
575
+ this.touches.set(TOUCH_MOUSE_ID, {
576
+ x: mouseState.x,
577
+ y: mouseState.y
578
+ });
579
+ } else {
580
+ this.touches.delete(TOUCH_MOUSE_ID);
581
+ }
582
+ }
583
+ attach() {
584
+ if (!hasDocument) return;
585
+ const onStart = /* @__PURE__ */ __name((event) => this.handleTouchStart(event), "onStart");
586
+ const onMove = /* @__PURE__ */ __name((event) => this.handleTouchMove(event), "onMove");
587
+ const onEnd = /* @__PURE__ */ __name((event) => this.handleTouchEnd(event), "onEnd");
588
+ document.addEventListener("touchstart", onStart, {
589
+ passive: false
590
+ });
591
+ document.addEventListener("touchmove", onMove, {
592
+ passive: false
593
+ });
594
+ document.addEventListener("touchend", onEnd, {
595
+ passive: false
596
+ });
597
+ document.addEventListener("touchcancel", onEnd, {
598
+ passive: false
599
+ });
600
+ this.removeListeners = () => {
601
+ document.removeEventListener("touchstart", onStart);
602
+ document.removeEventListener("touchmove", onMove);
603
+ document.removeEventListener("touchend", onEnd);
604
+ document.removeEventListener("touchcancel", onEnd);
605
+ };
606
+ }
607
+ detach() {
608
+ this.removeListeners?.();
609
+ this.removeListeners = void 0;
610
+ this.canvas = void 0;
611
+ this.touches.clear();
612
+ }
613
+ handleTouchStart(event) {
614
+ if (!this.canvas) return;
615
+ event.preventDefault();
616
+ event.stopPropagation();
617
+ for (let i = 0; i < event.changedTouches.length; i++) {
618
+ const t = event.changedTouches[i];
619
+ const { x, y } = computeRelativePosition(this.canvas, t.clientX, t.clientY);
620
+ this.touches.set(t.identifier, {
621
+ x,
622
+ y
623
+ });
624
+ this.mouse.syncFromTouch(x, y, true);
625
+ }
626
+ }
627
+ handleTouchMove(event) {
628
+ if (!this.canvas) return;
629
+ event.preventDefault();
630
+ event.stopPropagation();
631
+ for (let i = 0; i < event.changedTouches.length; i++) {
632
+ const t = event.changedTouches[i];
633
+ if (!this.touches.has(t.identifier)) continue;
634
+ const { x, y } = computeRelativePosition(this.canvas, t.clientX, t.clientY);
635
+ this.touches.set(t.identifier, {
636
+ x,
637
+ y
638
+ });
639
+ this.mouse.syncFromTouch(x, y, true);
640
+ }
641
+ }
642
+ handleTouchEnd(event) {
643
+ if (!this.canvas) return;
644
+ event.preventDefault();
645
+ event.stopPropagation();
646
+ for (let i = 0; i < event.changedTouches.length; i++) {
647
+ const t = event.changedTouches[i];
648
+ this.touches.delete(t.identifier);
649
+ }
650
+ this.mouse.syncFromTouch(this.state.x, this.state.y, false);
651
+ }
652
+ };
653
+
654
+ // src/core/input-manager.ts
655
+ var Input = class {
656
+ static {
657
+ __name(this, "Input");
658
+ }
659
+ keyboard;
660
+ mouse;
661
+ touch;
662
+ gamepad;
663
+ runtime;
664
+ constructor(canvas, runtime) {
665
+ this.runtime = runtime;
666
+ this.keyboard = new KeyboardInput();
667
+ this.mouse = new MouseInput(canvas);
668
+ this.touch = new TouchInput(this.mouse, canvas);
669
+ this.gamepad = new GamepadInput();
670
+ }
671
+ /**
672
+ * Poll all devices for state updates.
673
+ */
674
+ update() {
675
+ this.keyboard.update();
676
+ this.mouse.update();
677
+ this.touch.update();
678
+ this.gamepad.update();
679
+ }
680
+ getKeyboard() {
681
+ if (!this.keyboard || !this.keyboard.state) {
682
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7052, {
683
+ error: "Keyboard state not available"
684
+ });
685
+ return {};
686
+ }
687
+ return this.keyboard.state;
688
+ }
689
+ getMouse() {
690
+ if (!this.mouse || !this.mouse.state) {
691
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7052, {
692
+ error: "Mouse state not available"
693
+ });
694
+ return {};
695
+ }
696
+ return this.mouse.state;
697
+ }
698
+ getTouch() {
699
+ if (!this.touch || !this.touch.state) {
700
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7052, {
701
+ error: "Touch state not available"
702
+ });
703
+ return {};
704
+ }
705
+ return this.touch.state;
706
+ }
707
+ getGamepad() {
708
+ if (!this.gamepad || !navigator.getGamepads) {
709
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7051, {
710
+ device: "gamepad"
711
+ });
712
+ }
713
+ return this.gamepad;
714
+ }
715
+ setCanvas(canvas) {
716
+ this.mouse.setCanvas(canvas);
717
+ this.touch.setCanvas(canvas);
718
+ }
719
+ };
720
+ // Annotate the CommonJS export names for ESM import in node:
721
+ 0 && (module.exports = {
722
+ Input
723
+ });
724
+ //# sourceMappingURL=input-manager.js.map