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