@oidoid/void 0.1.0-6 → 0.1.0-7

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 (111) hide show
  1. package/dist/meta.json +1 -1
  2. package/dist/package.json +5 -5
  3. package/dist/public/favicon/favicon16.png +0 -0
  4. package/dist/public/favicon/favicon16.webp +0 -0
  5. package/dist/public/favicon/favicon192.png +0 -0
  6. package/dist/public/favicon/favicon192.webp +0 -0
  7. package/dist/public/favicon/favicon32.png +0 -0
  8. package/dist/public/favicon/favicon32.webp +0 -0
  9. package/dist/public/favicon/favicon48.png +0 -0
  10. package/dist/public/favicon/favicon48.webp +0 -0
  11. package/dist/public/favicon/favicon64.png +0 -0
  12. package/dist/public/favicon/favicon64.webp +0 -0
  13. package/dist/public/index.js +12 -3758
  14. package/dist/public/index.js.map +4 -4
  15. package/dist/public/preload-atlas.png +0 -0
  16. package/dist/public/preload-atlas.webp +0 -0
  17. package/dist/public/void-v0.1.0-6+20251020.7cdf98d.html +111 -0
  18. package/dist/public/void-v0.1.0-6+20251020.e4e9eef.html +111 -0
  19. package/dist/public/void-v0.1.0-7+20251021.7cdf98d.html +111 -0
  20. package/dist/schema/config-file.v0.json +1 -1
  21. package/dist/src/demo/assets/manifest.json +10 -15
  22. package/dist/src/demo/ents/clock-ent.d.ts +2 -1
  23. package/dist/src/demo/ents/clock-ent.js.map +1 -1
  24. package/dist/src/demo/ents/render-toggle-ent.d.ts +3 -1
  25. package/dist/src/demo/ents/render-toggle-ent.js +3 -0
  26. package/dist/src/demo/ents/render-toggle-ent.js.map +1 -1
  27. package/dist/src/demo/ents/work-counter-ent.d.ts +2 -2
  28. package/dist/src/demo/ents/work-counter-ent.js +1 -5
  29. package/dist/src/demo/ents/work-counter-ent.js.map +1 -1
  30. package/dist/src/demo/game.d.ts +1 -2
  31. package/dist/src/demo/game.js +14 -34
  32. package/dist/src/demo/game.js.map +1 -1
  33. package/dist/src/demo/void.json +1 -1
  34. package/dist/src/ents/button-ent.d.ts +2 -1
  35. package/dist/src/ents/button-ent.js +7 -3
  36. package/dist/src/ents/button-ent.js.map +1 -1
  37. package/dist/src/ents/cursor-ent.d.ts +2 -2
  38. package/dist/src/ents/cursor-ent.js +7 -2
  39. package/dist/src/ents/cursor-ent.js.map +1 -1
  40. package/dist/src/ents/ent.d.ts +3 -3
  41. package/dist/src/ents/follow-cam-ent.d.ts +1 -1
  42. package/dist/src/ents/nine-patch-ent.d.ts +1 -1
  43. package/dist/src/ents/text-ent.d.ts +1 -1
  44. package/dist/src/ents/zoo.d.ts +4 -3
  45. package/dist/src/ents/zoo.js +11 -4
  46. package/dist/src/ents/zoo.js.map +1 -1
  47. package/dist/src/graphics/cam.js +10 -1
  48. package/dist/src/graphics/cam.js.map +1 -1
  49. package/dist/src/graphics/renderer.d.ts +18 -4
  50. package/dist/src/graphics/renderer.js +20 -8
  51. package/dist/src/graphics/renderer.js.map +1 -1
  52. package/dist/src/graphics/sprite.d.ts +1 -1
  53. package/dist/src/graphics/sprite.js +4 -4
  54. package/dist/src/graphics/sprite.js.map +1 -1
  55. package/dist/src/index.js +1 -1
  56. package/dist/src/index.js.map +1 -1
  57. package/dist/src/looper.d.ts +5 -3
  58. package/dist/src/looper.js +7 -4
  59. package/dist/src/looper.js.map +1 -1
  60. package/dist/src/types/void-version.d.ts +0 -2
  61. package/dist/src/types/void-version.js.map +1 -1
  62. package/dist/src/utils/canvas-util.js +2 -2
  63. package/dist/src/utils/canvas-util.js.map +1 -1
  64. package/dist/src/utils/debug.d.ts +4 -2
  65. package/dist/src/utils/debug.js +4 -3
  66. package/dist/src/utils/debug.js.map +1 -1
  67. package/dist/src/utils/delay-interval.d.ts +7 -0
  68. package/dist/src/utils/delay-interval.js +29 -0
  69. package/dist/src/utils/delay-interval.js.map +1 -0
  70. package/dist/src/utils/dom-util.d.ts +2 -2
  71. package/dist/src/utils/dom-util.js +15 -15
  72. package/dist/src/utils/dom-util.js.map +1 -1
  73. package/dist/src/void.d.ts +8 -3
  74. package/dist/src/void.js +22 -15
  75. package/dist/src/void.js.map +1 -1
  76. package/dist/tools/atlas-pack/atlas-pack.d.ts +1 -1
  77. package/dist/tools/atlas-pack/atlas-pack.js +10 -5
  78. package/dist/tools/atlas-pack/atlas-pack.js.map +1 -1
  79. package/dist/tools/bundle/bundle.js +4 -4
  80. package/dist/tools/bundle/bundle.js.map +1 -1
  81. package/dist/tools/bundle/html-plugin.js +6 -4
  82. package/dist/tools/bundle/html-plugin.js.map +1 -1
  83. package/dist/tools/tsconfig-base.json +4 -1
  84. package/dist/tools/tsconfig.json +1 -3
  85. package/dist/tools/types/config.d.ts +8 -1
  86. package/dist/tools/types/config.js +17 -8
  87. package/dist/tools/types/config.js.map +1 -1
  88. package/dist/tools/types/package-json.d.ts +4 -0
  89. package/dist/tools/types/package-json.js +2 -0
  90. package/dist/tools/types/package-json.js.map +1 -0
  91. package/dist/tools/void.d.ts +1 -3
  92. package/dist/tools/void.js +8 -7
  93. package/dist/tools/void.js.map +1 -1
  94. package/package.json +5 -5
  95. package/schema/config-file.test.ts +2 -2
  96. package/schema/config-file.v0.json +1 -1
  97. package/tools/atlas-pack/atlas-pack.ts +20 -7
  98. package/tools/bundle/bundle.ts +3 -4
  99. package/tools/bundle/html-plugin.ts +10 -10
  100. package/tools/types/config.ts +29 -7
  101. package/tools/types/package-json.ts +4 -0
  102. package/tools/void.ts +11 -10
  103. package/dist/public/favicon/favicon512.png +0 -0
  104. package/dist/public/index.html +0 -23
  105. package/dist/public/manifest.json +0 -1
  106. package/dist/public/void-v0.1.0-4.html +0 -111
  107. package/dist/public/void-v0.1.0-5.html +0 -111
  108. package/dist/public/void-v0.1.0-6.html +0 -111
  109. package/dist/src/pixel-ratio-observer.d.ts +0 -10
  110. package/dist/src/pixel-ratio-observer.js +0 -26
  111. package/dist/src/pixel-ratio-observer.js.map +0 -1
@@ -1,2615 +1,7 @@
1
- new EventSource('/esbuild').addEventListener('change', () => location.reload());
2
-
3
- // <define:globalThis.voidVersion>
4
- var define_globalThis_voidVersion_default = { hash: "2eb97a3", published: "20250824", version: "0.1.0-4" };
5
-
6
- // src/types/void-version.ts
7
- var voidVersion = define_globalThis_voidVersion_default;
8
-
9
- // node_modules/mem-font/dist/mem-prop-5x6.json
10
- var mem_prop_5x6_default = {
11
- id: "mem-prop-5x6",
12
- name: "mem 5x6",
13
- cellWidth: 5,
14
- cellHeight: 6,
15
- leading: 1,
16
- lineHeight: 7,
17
- baseline: 1,
18
- kerning: {
19
- " 0": 0,
20
- " 1": 0,
21
- " 2": 0,
22
- " 3": 0,
23
- " 4": 0,
24
- " 5": 0,
25
- " 6": 0,
26
- " 7": 0,
27
- " 8": 0,
28
- " 9": 0,
29
- "##": -1,
30
- "#_": 0,
31
- "',": 0,
32
- "'.": 0,
33
- "'/": 0,
34
- "'J": 0,
35
- "'S": 0,
36
- "'_": 0,
37
- "'j": 0,
38
- "'s": 0,
39
- "(+": 0,
40
- "(-": 0,
41
- "(<": 0,
42
- "(f": 0,
43
- "({": 0,
44
- "(~": 0,
45
- ")_": 0,
46
- "*,": 0,
47
- "*.": 0,
48
- "*/": 0,
49
- "*S": 0,
50
- "*_": 0,
51
- "*j": 0,
52
- "*s": 0,
53
- "+)": 0,
54
- "+,": 0,
55
- "+.": 0,
56
- "+/": 0,
57
- "+>": 0,
58
- "+?": 0,
59
- "+I": 0,
60
- "+S": 0,
61
- "+T": 0,
62
- "+Z": 0,
63
- "+]": 0,
64
- "+_": 0,
65
- "+`": 0,
66
- "+j": 0,
67
- "+s": 0,
68
- "+}": 0,
69
- ",'": 0,
70
- ",*": 0,
71
- ",+": 0,
72
- ",-": 0,
73
- ",<": 0,
74
- ",?": 0,
75
- ",T": 0,
76
- ",Y": 0,
77
- ",Z": 0,
78
- ',"': 0,
79
- ",\\": 0,
80
- ",^": 0,
81
- ",`": 0,
82
- ",f": 0,
83
- ",t": 0,
84
- ",z": 0,
85
- ",{": 0,
86
- ",~": 0,
87
- "-)": 0,
88
- "-,": 0,
89
- "--": 0,
90
- "-.": 0,
91
- "-/": 0,
92
- "->": 0,
93
- "-?": 0,
94
- "-I": 0,
95
- "-S": 0,
96
- "-T": 0,
97
- "-Z": 0,
98
- "-]": 0,
99
- "-_": 0,
100
- "-`": 0,
101
- "-j": 0,
102
- "-s": 0,
103
- "-}": 0,
104
- ".'": 0,
105
- ".*": 0,
106
- ".+": 0,
107
- ".-": 0,
108
- ".<": 0,
109
- ".?": 0,
110
- ".T": 0,
111
- ".Y": 0,
112
- ".Z": 0,
113
- '."': 0,
114
- ".\\": 0,
115
- ".^": 0,
116
- ".`": 0,
117
- ".f": 0,
118
- ".t": 0,
119
- ".z": 0,
120
- ".{": 0,
121
- ".~": 0,
122
- "/,": 0,
123
- "/.": 0,
124
- "//": 0,
125
- "/J": 0,
126
- "/S": 0,
127
- "/_": 0,
128
- "/j": 0,
129
- "/s": 0,
130
- "0 ": 0,
131
- "1 ": 0,
132
- "1T": 0,
133
- "1Y": 0,
134
- "1Z": 0,
135
- "1f": 0,
136
- "1t": 0,
137
- "1z": 0,
138
- "2 ": 0,
139
- "3 ": 0,
140
- "4 ": 0,
141
- "5 ": 0,
142
- "6 ": 0,
143
- "7 ": 0,
144
- "8 ": 0,
145
- "9 ": 0,
146
- ":?": 0,
147
- ":T": 0,
148
- ":Z": 0,
149
- ":`": 0,
150
- ";?": 0,
151
- ";T": 0,
152
- ";Z": 0,
153
- "<+": 0,
154
- "<-": 0,
155
- "<<": 0,
156
- "<f": 0,
157
- "<{": 0,
158
- "<~": 0,
159
- "==": 0,
160
- "=_": 0,
161
- ">)": 0,
162
- ">,": 0,
163
- ">.": 0,
164
- ">/": 0,
165
- ">>": 0,
166
- ">?": 0,
167
- ">I": 0,
168
- ">S": 0,
169
- ">T": 0,
170
- ">Z": 0,
171
- ">]": 0,
172
- ">_": 0,
173
- ">`": 0,
174
- ">j": 0,
175
- ">s": 0,
176
- ">}": 0,
177
- "?,": 0,
178
- "?.": 0,
179
- "?/": 0,
180
- "?S": 0,
181
- "?_": 0,
182
- "?j": 0,
183
- "?s": 0,
184
- "@_": 0,
185
- "C+": 0,
186
- "C-": 0,
187
- "C<": 0,
188
- Cf: 0,
189
- "C{": 0,
190
- "C~": 0,
191
- D_: 0,
192
- "E+": 0,
193
- "E-": 0,
194
- "E<": 0,
195
- Ef: 0,
196
- "E{": 0,
197
- "E~": 0,
198
- "F&": 0,
199
- "F+": 0,
200
- "F,": 0,
201
- "F-": 0,
202
- "F.": 0,
203
- "F/": 0,
204
- "F:": 0,
205
- "F;": 0,
206
- "F<": 0,
207
- FJ: 0,
208
- FS: 0,
209
- F_: 0,
210
- Fa: 0,
211
- Fe: 0,
212
- Ff: 0,
213
- Fg: 0,
214
- Fj: 0,
215
- Fq: 0,
216
- Fs: 0,
217
- "F{": 0,
218
- "F~": 0,
219
- "I+": 0,
220
- "I-": 0,
221
- "I<": 0,
222
- If: 0,
223
- "I{": 0,
224
- "I~": 0,
225
- "L'": 0,
226
- "L*": 0,
227
- "L+": 0,
228
- "L-": 0,
229
- L4: 0,
230
- L7: 0,
231
- "L<": 0,
232
- "L?": 0,
233
- LT: 0,
234
- LY: 0,
235
- LZ: 0,
236
- 'L"': 0,
237
- "L\\": 0,
238
- "L^": 0,
239
- "L`": 0,
240
- Lf: 0,
241
- Lt: 0,
242
- Lz: 0,
243
- "L{": 0,
244
- "L~": 0,
245
- "P,": 0,
246
- "P.": 0,
247
- "P/": 0,
248
- PS: 0,
249
- P_: 0,
250
- Pj: 0,
251
- Ps: 0,
252
- "S&": 0,
253
- "S+": 0,
254
- "S,": 0,
255
- "S-": 0,
256
- "S.": 0,
257
- "S/": 0,
258
- "S:": 0,
259
- "S;": 0,
260
- "S<": 0,
261
- SJ: 0,
262
- SS: 0,
263
- S_: 0,
264
- Sa: 0,
265
- Se: 0,
266
- Sf: 0,
267
- Sg: 0,
268
- Sj: 0,
269
- Sq: 0,
270
- Ss: 0,
271
- "S{": 0,
272
- "S~": 0,
273
- "T&": 0,
274
- "T+": 0,
275
- "T,": 0,
276
- "T-": 0,
277
- "T.": 0,
278
- "T/": 0,
279
- "T:": 0,
280
- "T;": 0,
281
- "T<": 0,
282
- TJ: 0,
283
- TS: 0,
284
- T_: 0,
285
- Ta: 0,
286
- Te: 0,
287
- Tf: 0,
288
- Tg: 0,
289
- Tj: 0,
290
- Tq: 0,
291
- Ts: 0,
292
- "T{": 0,
293
- "T~": 0,
294
- V_: 0,
295
- "Y,": 0,
296
- "Y.": 0,
297
- "Y/": 0,
298
- YS: 0,
299
- Y_: 0,
300
- Yj: 0,
301
- Ys: 0,
302
- "Z'": 0,
303
- "Z*": 0,
304
- "Z+": 0,
305
- "Z-": 0,
306
- Z4: 0,
307
- Z7: 0,
308
- "Z<": 0,
309
- "Z?": 0,
310
- ZT: 0,
311
- ZY: 0,
312
- ZZ: 0,
313
- 'Z"': 0,
314
- "Z\\": 0,
315
- "Z^": 0,
316
- "Z`": 0,
317
- Zf: 0,
318
- Zt: 0,
319
- Zz: 0,
320
- "Z{": 0,
321
- "Z~": 0,
322
- "[+": 0,
323
- "[-": 0,
324
- "[<": 0,
325
- "[f": 0,
326
- "[{": 0,
327
- "[~": 0,
328
- '",': 0,
329
- '".': 0,
330
- '"/': 0,
331
- '"J': 0,
332
- '"S': 0,
333
- '"_': 0,
334
- '"j': 0,
335
- '"s': 0,
336
- "\\'": 0,
337
- "\\*": 0,
338
- "\\+": 0,
339
- "\\-": 0,
340
- "\\<": 0,
341
- "\\?": 0,
342
- "\\T": 0,
343
- "\\Y": 0,
344
- "\\Z": 0,
345
- '\\"': 0,
346
- "\\\\": 0,
347
- "\\^": 0,
348
- "\\`": 0,
349
- "\\f": 0,
350
- "\\t": 0,
351
- "\\z": 0,
352
- "\\{": 0,
353
- "\\~": 0,
354
- "^,": 0,
355
- "^.": 0,
356
- "^/": 0,
357
- "^J": 0,
358
- "^S": 0,
359
- "^_": 0,
360
- "^j": 0,
361
- "^s": 0,
362
- "_#": 0,
363
- "_%": 0,
364
- "_'": 0,
365
- "_(": 0,
366
- "_*": 0,
367
- "_+": 0,
368
- "_-": 0,
369
- "_<": 0,
370
- "_=": 0,
371
- "_?": 0,
372
- "_@": 0,
373
- _T: 0,
374
- _V: 0,
375
- _Y: 0,
376
- _Z: 0,
377
- '_"': 0,
378
- "_\\": 0,
379
- "_^": 0,
380
- __: 0,
381
- "_`": 0,
382
- _a: 0,
383
- _e: 0,
384
- _f: 0,
385
- _t: 0,
386
- _v: 0,
387
- _z: 0,
388
- "_{": 0,
389
- "_~": 0,
390
- "`,": 0,
391
- "`.": 0,
392
- "`/": 0,
393
- "`J": 0,
394
- "`S": 0,
395
- "`_": 0,
396
- "`j": 0,
397
- "`s": 0,
398
- "f,": 0,
399
- "f.": 0,
400
- "f/": 0,
401
- fS: 0,
402
- f_: 0,
403
- fj: 0,
404
- fs: 0,
405
- "q#": 0,
406
- q$: 0,
407
- "q%": 0,
408
- "q&": 0,
409
- "q'": 0,
410
- "q(": 0,
411
- "q*": 0,
412
- "q+": 0,
413
- "q-": 0,
414
- q0: 0,
415
- q1: 0,
416
- q2: 0,
417
- q3: 0,
418
- q4: 0,
419
- q5: 0,
420
- q6: 0,
421
- q7: 0,
422
- q8: 0,
423
- q9: 0,
424
- "q<": 0,
425
- "q=": 0,
426
- "q?": 0,
427
- "q@": 0,
428
- qA: 0,
429
- qB: 0,
430
- qC: 0,
431
- qD: 0,
432
- qE: 0,
433
- qF: 0,
434
- qG: 0,
435
- qH: 0,
436
- qI: 0,
437
- qJ: 0,
438
- qK: 0,
439
- qL: 0,
440
- qM: 0,
441
- qN: 0,
442
- qO: 0,
443
- qP: 0,
444
- qQ: 0,
445
- qR: 0,
446
- qS: 0,
447
- qT: 0,
448
- qU: 0,
449
- qV: 0,
450
- qW: 0,
451
- qX: 0,
452
- qY: 0,
453
- qZ: 0,
454
- "q[": 0,
455
- 'q"': 0,
456
- "q\\": 0,
457
- "q]": 0,
458
- "q^": 0,
459
- "q`": 0,
460
- qa: 0,
461
- qb: 0,
462
- qc: 0,
463
- qd: 0,
464
- qe: 0,
465
- qf: 0,
466
- qh: 0,
467
- qk: 0,
468
- qm: 0,
469
- qn: 0,
470
- qo: 0,
471
- qq: 0,
472
- qr: 0,
473
- qs: 0,
474
- qt: 0,
475
- qu: 0,
476
- qv: 0,
477
- qw: 0,
478
- qx: 0,
479
- qz: 0,
480
- "q{": 0,
481
- "q}": 0,
482
- "q~": 0,
483
- "r,": 0,
484
- "r.": 0,
485
- "r/": 0,
486
- rS: 0,
487
- r_: 0,
488
- rj: -1,
489
- rs: 0,
490
- "s,": 0,
491
- "s.": 0,
492
- "s/": 0,
493
- sJ: 0,
494
- sS: 0,
495
- s_: 0,
496
- sj: 0,
497
- ss: 0,
498
- "z'": 0,
499
- "z*": 0,
500
- "z+": 0,
501
- "z-": 0,
502
- z4: 0,
503
- z7: 0,
504
- "z<": 0,
505
- "z?": 0,
506
- zT: 0,
507
- zY: 0,
508
- zZ: 0,
509
- 'z"': 0,
510
- "z\\": 0,
511
- "z^": 0,
512
- "z`": 0,
513
- zf: 0,
514
- zt: 0,
515
- zz: 0,
516
- "z{": 0,
517
- "z~": 0,
518
- "{+": 0,
519
- "{-": 0,
520
- "{<": 0,
521
- "{f": 0,
522
- "{{": 0,
523
- "{~": 0,
524
- "})": 0,
525
- "},": 0,
526
- "}.": 0,
527
- "}/": 0,
528
- "}>": 0,
529
- "}?": 0,
530
- "}I": 0,
531
- "}S": 0,
532
- "}T": 0,
533
- "}Z": 0,
534
- "}]": 0,
535
- "}_": 0,
536
- "}`": 0,
537
- "}j": 0,
538
- "}s": 0,
539
- "}}": 0,
540
- "~'": 0,
541
- "~?": 0,
542
- "~T": 0,
543
- "~Z": 0,
544
- '~"': 0,
545
- "~\\": 0,
546
- "~^": 0,
547
- "~_": 0,
548
- "~`": 0,
549
- "~t": 0,
550
- "~z": 0
551
- },
552
- defaultKerning: 1,
553
- defaultWhitespaceKerning: -1,
554
- endOfLineKerning: 0,
555
- charWidth: {
556
- " ": 4,
557
- "!": 1,
558
- "#": 5,
559
- "&": 4,
560
- "'": 1,
561
- "(": 2,
562
- ")": 2,
563
- ",": 1,
564
- ".": 1,
565
- ":": 1,
566
- ";": 1,
567
- "@": 5,
568
- M: 5,
569
- W: 5,
570
- "[": 2,
571
- "\n": 0,
572
- "]": 2,
573
- "`": 2,
574
- i: 1,
575
- l: 1,
576
- m: 5,
577
- q: 4,
578
- w: 5,
579
- "|": 1
580
- },
581
- defaultCharWidth: 3
582
- };
583
-
584
- // node_modules/mem-font/dist/index.js
585
- var memProp5x6 = mem_prop_5x6_default;
586
-
587
- // src/graphics/layer.ts
588
- var Layer = {
589
- Top: 0,
590
- UIA: 1,
591
- UIB: 2,
592
- UIC: 3,
593
- UID: 4,
594
- UIE: 5,
595
- UIF: 6,
596
- UIG: 7,
597
- A: 8,
598
- B: 9,
599
- C: 10,
600
- D: 11,
601
- E: 12,
602
- F: 13,
603
- Bottom: 14,
604
- Hidden: 15
605
- };
606
- function layerOffset(layer, offset) {
607
- return Math.max(Layer.Top, Math.min(Layer.Bottom, layer + offset));
608
- }
609
-
610
- // src/types/geo.ts
611
- function boxHits(l, r) {
612
- const rWH = { w: r.w ?? 1, h: r.h ?? 1 };
613
- if (!l.w || !l.h || !rWH.w || !rWH.h) return false;
614
- const lXY = { x: l.x ?? 0, y: l.y ?? 0 };
615
- return lXY.x < r.x + rWH.w && lXY.x + l.w > r.x && lXY.y < r.y + rWH.h && lXY.y + l.h > r.y;
616
- }
617
- function whAssign(l, r) {
618
- l.w = r.w;
619
- l.h = r.h;
620
- }
621
- function whEq(l, r) {
622
- return l.w === r.w && l.h === r.h;
623
- }
624
- function xyAdd(l, r) {
625
- return { x: l.x + r.x, y: l.y + r.y };
626
- }
627
- function xyAssign(l, r) {
628
- l.x = r.x;
629
- l.y = r.y;
630
- }
631
- function xyDistance(from, to) {
632
- return xyMagnitude(xySub(from, to));
633
- }
634
- function xyEq(l, r) {
635
- return l.x === r.x && l.y === r.y;
636
- }
637
- function xyMagnitude(xy) {
638
- return Math.hypot(xy.x, xy.y);
639
- }
640
- function xyMax(l, r) {
641
- return { x: Math.max(l.x, r.x), y: Math.max(l.y, r.y) };
642
- }
643
- function xyMin(l, r) {
644
- return { x: Math.min(l.x, r.x), y: Math.min(l.y, r.y) };
645
- }
646
- function xySub(l, r) {
647
- return { x: l.x - r.x, y: l.y - r.y };
648
- }
649
-
650
- // src/ents/nine-patch-ent.ts
651
- var NinePatchEnt = class {
652
- #dir;
653
- #margin;
654
- #invalid = true;
655
- constructor(v2, opts) {
656
- this.#dir = {
657
- w: v2.sprites.alloc(),
658
- nw: v2.sprites.alloc(),
659
- n: v2.sprites.alloc(),
660
- ne: v2.sprites.alloc(),
661
- e: v2.sprites.alloc(),
662
- se: v2.sprites.alloc(),
663
- s: v2.sprites.alloc(),
664
- sw: v2.sprites.alloc(),
665
- origin: v2.sprites.alloc()
666
- };
667
- this.#dir.w.tag = opts.w?.tag ?? opts.e?.tag ?? opts.n.tag;
668
- this.#dir.n.tag = opts.n.tag;
669
- this.#dir.e.tag = opts.e?.tag ?? this.#dir.w.tag;
670
- this.#dir.s.tag = opts.s?.tag ?? this.#dir.n.tag;
671
- this.#dir.nw.tag = opts.nw?.tag ?? opts.se?.tag ?? opts.n.tag;
672
- this.#dir.ne.tag = opts.ne?.tag ?? opts.sw?.tag ?? opts.nw?.tag ?? opts.n.tag;
673
- this.#dir.se.tag = opts.se?.tag ?? this.#dir.nw.tag;
674
- this.#dir.sw.tag = opts.sw?.tag ?? this.#dir.ne.tag;
675
- this.#dir.origin.tag = opts.origin.tag;
676
- this.#dir.w.z = this.#dir.nw.z = this.#dir.n.z = this.#dir.ne.z = this.#dir.e.z = this.#dir.se.z = this.#dir.s.z = this.#dir.sw.z = this.#dir.origin.z = opts.z ?? 0;
677
- this.#dir.w.stretch = opts.w?.stretch ?? opts.e?.stretch ?? false;
678
- this.#dir.n.stretch = opts.n.stretch ?? opts.s?.stretch ?? false;
679
- this.#dir.e.stretch = opts.e?.stretch ?? this.#dir.w.stretch;
680
- this.#dir.s.stretch = opts.s?.stretch ?? this.#dir.n.stretch;
681
- this.#dir.nw.stretch = opts.nw?.stretch ?? opts.se?.stretch ?? false;
682
- this.#dir.ne.stretch = opts.ne?.stretch ?? opts.sw?.stretch ?? false;
683
- this.#dir.se.stretch = opts.se?.stretch ?? this.#dir.nw.stretch;
684
- this.#dir.sw.stretch = opts.sw?.stretch ?? this.#dir.ne.stretch;
685
- this.#dir.origin.stretch = opts.origin.stretch ?? false;
686
- this.#dir.w.flipX = opts.w?.flip?.x ?? !opts.e?.flip?.x;
687
- this.#dir.w.flipY = opts.w?.flip?.y ?? !!opts.e?.flip?.y;
688
- this.#dir.n.flipX = opts.n.flip?.x ?? !!opts.s?.flip?.x;
689
- this.#dir.n.flipY = opts.n.flip?.y ?? !opts.s?.flip?.y;
690
- this.#dir.e.flipX = opts.e?.flip?.x ?? !this.#dir.w.flipX;
691
- this.#dir.e.flipY = opts.e?.flip?.y ?? this.#dir.w.flipY;
692
- this.#dir.s.flipX = opts.s?.flip?.x ?? this.#dir.n.flipX;
693
- this.#dir.s.flipY = opts.s?.flip?.y ?? !this.#dir.n.flipY;
694
- this.#dir.origin.flipX = !!opts.origin.flip?.x;
695
- this.#dir.origin.flipY = !!opts.origin.flip?.y;
696
- this.#dir.n.h = opts.border?.n ?? opts.border?.s ?? this.#dir.n.h;
697
- this.#dir.w.w = opts.border?.w ?? opts.border?.e ?? this.#dir.n.h;
698
- this.#dir.e.w = opts.border?.e ?? this.#dir.w.w;
699
- this.#dir.s.h = opts.border?.s ?? this.#dir.n.h;
700
- this.#dir.nw.w = this.#dir.w.w;
701
- this.#dir.nw.h = this.#dir.n.h;
702
- this.#dir.ne.w = this.#dir.e.w;
703
- this.#dir.ne.h = this.#dir.n.h;
704
- this.#dir.se.w = this.#dir.e.w;
705
- this.#dir.se.h = this.#dir.s.h;
706
- this.#dir.sw.w = this.#dir.w.w;
707
- this.#dir.sw.h = this.#dir.s.h;
708
- this.#margin = { w: opts.margin?.w ?? 0, h: opts.margin?.h ?? 0 };
709
- const w = opts.wh?.w == null ? this.#dir.w.w + this.#dir.n.w + this.#dir.e.w : opts.wh.w;
710
- this.#dir.n.w = w - 1;
711
- this.wh = {
712
- w,
713
- h: opts.wh?.h == null ? this.#dir.n.h + this.#dir.e.h + this.#dir.s.h : opts.wh.h
714
- };
715
- this.#dir.nw.x = (opts.x ?? 0) - 1;
716
- this.xy = { x: opts.x ?? 0, y: opts.y ?? 0 };
717
- }
718
- free(v2) {
719
- v2.sprites.free(
720
- this.#dir.w,
721
- this.#dir.nw,
722
- this.#dir.n,
723
- this.#dir.ne,
724
- this.#dir.e,
725
- this.#dir.se,
726
- this.#dir.s,
727
- this.#dir.sw,
728
- this.#dir.origin
729
- );
730
- }
731
- update() {
732
- if (!this.#invalid) return;
733
- this.#invalid = false;
734
- return true;
735
- }
736
- get wh() {
737
- return {
738
- w: this.#dir.w.w + this.#dir.n.w + this.#dir.e.w + this.#margin.w,
739
- h: this.#dir.n.h + this.#dir.w.h + this.#dir.s.h + this.#margin.h
740
- };
741
- }
742
- set wh(wh) {
743
- if (whEq(wh, this.wh)) return;
744
- this.#dir.w.h = wh.h - this.#dir.n.h - this.#dir.s.h - this.#margin.h;
745
- this.#dir.n.w = wh.w - this.#dir.w.w - this.#dir.e.w - this.#margin.w;
746
- this.#dir.s.w = this.#dir.n.w;
747
- this.#dir.e.h = this.#dir.w.h;
748
- this.#dir.origin.w = this.#dir.n.w;
749
- this.#dir.origin.h = this.#dir.e.h;
750
- this.#setXYRight();
751
- this.#invalid = true;
752
- }
753
- get xy() {
754
- return {
755
- x: this.#dir.nw.x - this.#margin.w / 2,
756
- y: this.#dir.nw.y - this.#margin.h / 2
757
- };
758
- }
759
- set xy(xy) {
760
- if (xyEq(xy, this.xy)) return;
761
- this.#dir.nw.x = xy.x + this.#margin.w / 2;
762
- this.#dir.nw.y = xy.y + this.#margin.h / 2;
763
- this.#dir.w.x = this.#dir.nw.x;
764
- this.#dir.w.y = this.#dir.nw.y + this.#dir.nw.h;
765
- this.#dir.n.x = this.#dir.nw.x + this.#dir.nw.w;
766
- this.#dir.n.y = this.#dir.nw.y;
767
- this.#dir.origin.x = this.#dir.n.x;
768
- this.#dir.origin.y = this.#dir.nw.y + this.#dir.ne.h;
769
- this.#setXYRight();
770
- this.#invalid = true;
771
- }
772
- #setXYRight() {
773
- this.#dir.ne.x = this.#dir.n.x + this.#dir.n.w;
774
- this.#dir.ne.y = this.#dir.nw.y;
775
- this.#dir.e.x = this.#dir.ne.x;
776
- this.#dir.e.y = this.#dir.nw.y + this.#dir.ne.h;
777
- this.#dir.se.x = this.#dir.e.x;
778
- this.#dir.se.y = this.#dir.e.y + this.#dir.e.h;
779
- this.#dir.s.x = this.#dir.n.x;
780
- this.#dir.s.y = this.#dir.se.y;
781
- this.#dir.sw.x = this.#dir.nw.x;
782
- this.#dir.sw.y = this.#dir.se.y;
783
- }
784
- };
785
-
786
- // src/text/font.ts
787
- function fontCharToTag(font, char) {
788
- let pt = char.codePointAt(0);
789
- if (pt == null || pt > 255) pt = 63;
790
- return `${font.id}--${pt.toString(16).padStart(2, "0")}`;
791
- }
792
- function fontKerning(font, l, r) {
793
- if (r == null) return font.endOfLineKerning;
794
- if (font.kerning[l + r] != null) return font.kerning[l + r];
795
- if (/^\s?$/.test(l) || /^\s?$/.test(r)) return font.defaultWhitespaceKerning;
796
- return font.defaultKerning;
797
- }
798
- function fontCharWidth(font, letter) {
799
- return font.charWidth[letter] ?? font.defaultCharWidth;
800
- }
801
-
802
- // src/text/text-layout.ts
803
- function layoutText(opts) {
804
- const chars = [];
805
- const scale = opts.scale ?? 1;
806
- const start = opts.start ?? { x: 0, y: 0 };
807
- const maxW = opts.maxW ?? Infinity;
808
- let cursor = { x: start.x, y: start.y };
809
- let w = 0;
810
- while (chars.length < opts.str.length) {
811
- const i = chars.length;
812
- const char = opts.str[i];
813
- let layout;
814
- if (char === "\n") layout = layoutNewline(opts.font, cursor, start.x, scale);
815
- else if (/^\s*$/.test(char)) {
816
- layout = layoutSpace(
817
- opts.font,
818
- cursor,
819
- maxW,
820
- tracking(opts.font, char, opts.str[i + 1], scale),
821
- start.x,
822
- scale
823
- );
824
- } else {
825
- layout = layoutWord(opts.font, cursor, maxW, opts.str, i, start.x, scale);
826
- if (cursor.x > 0 && layout.cursor.y === nextLine(opts.font, start.x, cursor.y, scale).y) {
827
- const wordW = maxW - cursor.x + layout.cursor.x;
828
- if (wordW <= maxW) {
829
- cursor = nextLine(opts.font, start.x, cursor.y, scale);
830
- layout = layoutWord(
831
- opts.font,
832
- cursor,
833
- maxW,
834
- opts.str,
835
- i,
836
- start.x,
837
- scale
838
- );
839
- }
840
- }
841
- }
842
- chars.push(...layout.chars);
843
- cursor.x = layout.cursor.x;
844
- cursor.y = layout.cursor.y;
845
- w = Math.max(w, layout.cursor.x - start.x);
846
- }
847
- return {
848
- chars,
849
- cursor,
850
- wh: { w, h: nextLine(opts.font, start.x, cursor.y, scale).y - start.y }
851
- };
852
- }
853
- function layoutWord(font, cursor, maxW, word, index, startX, scale) {
854
- const chars = [];
855
- let { x, y } = cursor;
856
- for (; ; index++) {
857
- const char = word[index];
858
- if (!char || /^\s*$/.test(char)) break;
859
- const span = tracking(font, char, word[index + 1], scale);
860
- if (x > startX && x + span > startX + maxW)
861
- ({ x, y } = nextLine(font, startX, y, scale));
862
- chars.push({ x, y, w: fontCharWidth(font, char), h: font.cellHeight });
863
- x += span;
864
- }
865
- return { chars, cursor: { x, y } };
866
- }
867
- function nextLine(font, startX, curY, scale) {
868
- return { x: startX, y: curY + font.lineHeight * scale };
869
- }
870
- function layoutNewline(font, cursor, startX, scale) {
871
- return { chars: [void 0], cursor: nextLine(font, startX, cursor.y, scale) };
872
- }
873
- function layoutSpace(font, cursor, w, span, startX, scale) {
874
- const nextCursor = cursor.x > 0 && cursor.x + span >= w ? nextLine(font, startX, cursor.y, scale) : { x: cursor.x + span, y: cursor.y };
875
- return { chars: [void 0], cursor: nextCursor };
876
- }
877
- function tracking(font, l, r, scale) {
878
- return scale * (fontCharWidth(font, l) + fontKerning(font, l, r));
879
- }
880
-
881
- // src/ents/text-ent.ts
882
- var TextEnt = class {
883
- #maxW = Infinity;
884
- #layout = "Outdated";
885
- #z = Layer.UIA;
886
- #scale = 1;
887
- #sprites = [];
888
- #str = "";
889
- #wh = { w: 0, h: 0 };
890
- #xy = { x: 0, y: 0 };
891
- free(v2) {
892
- v2.sprites.free(...this.#sprites);
893
- }
894
- layout(v2) {
895
- if (this.#layout !== "Outdated") return false;
896
- let len = 0;
897
- const layout = layoutText({
898
- font: memProp5x6,
899
- maxW: this.#maxW,
900
- scale: this.#scale,
901
- start: this.#xy,
902
- str: this.#str
903
- });
904
- this.#wh = { w: layout.wh.w, h: layout.wh.h };
905
- for (const [i, char] of layout.chars.entries()) {
906
- if (char == null) continue;
907
- const sprite = this.#sprites[len] ??= v2.sprites.alloc();
908
- sprite.x = char.x;
909
- sprite.y = char.y;
910
- sprite.tag = fontCharToTag(memProp5x6, this.#str[i]);
911
- sprite.stretch = true;
912
- sprite.w *= this.#scale;
913
- sprite.h *= this.#scale;
914
- sprite.z = this.#z;
915
- len++;
916
- }
917
- while (this.#sprites.length > len) v2.sprites.free(this.#sprites.pop());
918
- this.#layout = "Updated";
919
- return true;
920
- }
921
- get maxW() {
922
- return this.#maxW;
923
- }
924
- set maxW(w) {
925
- if (w === this.#maxW) return;
926
- this.#maxW = w;
927
- this.#layout = "Outdated";
928
- }
929
- get scale() {
930
- return this.#scale;
931
- }
932
- set scale(scale) {
933
- if (scale === this.#scale) return;
934
- this.#scale = scale;
935
- this.#layout = "Outdated";
936
- }
937
- get text() {
938
- return this.#str;
939
- }
940
- set text(str) {
941
- if (str === this.#str) return;
942
- this.#str = str;
943
- this.#layout = "Outdated";
944
- }
945
- update(v2) {
946
- if (this.#layout === "Rendered") return;
947
- if (this.#layout === "Outdated") this.layout(v2);
948
- this.#layout = "Rendered";
949
- return true;
950
- }
951
- get scaledLeading() {
952
- return memProp5x6.leading * this.#scale;
953
- }
954
- get wh() {
955
- return this.#wh;
956
- }
957
- get xy() {
958
- return this.#xy;
959
- }
960
- set xy(xy) {
961
- if (xyEq(xy, this.#xy)) return;
962
- this.#xy.x = xy.x;
963
- this.#xy.y = xy.y;
964
- this.#layout = "Outdated";
965
- }
966
- get z() {
967
- return this.#z;
968
- }
969
- set z(layer) {
970
- if (layer === this.#z) return;
971
- this.#z = layer;
972
- this.#layout = "Outdated";
973
- }
974
- };
975
-
976
- // src/ents/button-ent.ts
977
- var ButtonEnt = class {
978
- #button;
979
- #invalid = true;
980
- #pressed;
981
- #selected;
982
- #started = false;
983
- #toggle = false;
984
- #text = new TextEnt();
985
- #xy = { x: 0, y: 0 };
986
- constructor(v2, opts) {
987
- const buttonZ = opts.button.z ?? Layer.UID;
988
- this.#button = new NinePatchEnt(v2, {
989
- ...opts.button,
990
- x: opts.x,
991
- y: opts.y,
992
- z: buttonZ,
993
- wh: { w: opts.w, h: opts.h }
994
- });
995
- this.#pressed = {
996
- sprite: v2.sprites.alloc(),
997
- z: opts.pressed.z ?? layerOffset(buttonZ, 2)
998
- };
999
- this.#selected = {
1000
- sprite: v2.sprites.alloc(),
1001
- z: opts.selected.z ?? layerOffset(this.#pressed.z, -1)
1002
- };
1003
- this.#pressed.sprite.tag = opts.pressed.tag;
1004
- this.#pressed.sprite.x = opts.x ?? 0;
1005
- this.#pressed.sprite.y = opts.y ?? 0;
1006
- this.#pressed.sprite.w = opts.w ?? this.#button.wh.w;
1007
- this.#pressed.sprite.h = opts.h ?? this.#button.wh.h;
1008
- this.#pressed.sprite.z = Layer.Hidden;
1009
- this.#selected.sprite.tag = opts.selected.tag;
1010
- this.#selected.sprite.x = opts.x ?? 0;
1011
- this.#selected.sprite.y = opts.y ?? 0;
1012
- this.#selected.sprite.w = opts.w ?? this.#button.wh.w;
1013
- this.#selected.sprite.h = opts.h ?? this.#button.wh.h;
1014
- this.#selected.sprite.z = Layer.Hidden;
1015
- this.#text.text = opts.text?.text ?? "";
1016
- this.#text.scale = opts.text?.scale ?? 1;
1017
- this.#text.layout(v2);
1018
- this.#moveText(v2);
1019
- this.#text.maxW = opts.w ?? this.#button.wh.w;
1020
- this.#text.z = opts.text?.z ?? layerOffset(buttonZ, -1);
1021
- this.#toggle = opts.toggle ?? false;
1022
- }
1023
- get selected() {
1024
- return this.#selected.z !== Layer.Hidden;
1025
- }
1026
- free(v2) {
1027
- this.#button.free(v2);
1028
- this.#text.free(v2);
1029
- v2.sprites.free(this.#selected.sprite, this.#pressed.sprite);
1030
- }
1031
- get on() {
1032
- return this.#pressed.sprite.z !== Layer.Hidden;
1033
- }
1034
- // to-do: offStart() for pointer up listen? would need a boundary check too.
1035
- get onStart() {
1036
- return this.on && this.#started;
1037
- }
1038
- set text(str) {
1039
- this.#text.text = str;
1040
- }
1041
- update(v2) {
1042
- let invalid = this.#invalid;
1043
- if (this.#button.update()) invalid = true;
1044
- if (this.#text.update(v2)) invalid = true;
1045
- const hitsCursor = !v2.input.handled && !!v2.zoo.cursor?.hits(v2, this.#selected.sprite, "UI");
1046
- const clickStarted = hitsCursor && v2.input.isOnStart("Click") || v2.zoo.cursor?.keyboard && v2.input.isOnStart("A");
1047
- const on = clickStarted ? this.#toggle ? !this.on : true : this.#toggle ? this.on : v2.input.isOn("Click") || v2.zoo.cursor?.keyboard && v2.input.isOn("A");
1048
- this.#started = this.on !== on;
1049
- if (this.#started) {
1050
- this.#pressed.sprite.z = on ? this.#pressed.z : Layer.Hidden;
1051
- invalid = true;
1052
- }
1053
- if (hitsCursor && (v2.input.point?.click || v2.input.point?.type === "Mouse")) {
1054
- invalid ||= this.#selected.sprite.z !== this.#selected.z;
1055
- this.#selected.sprite.z = this.#selected.z;
1056
- } else {
1057
- invalid ||= this.#selected.z !== Layer.Hidden;
1058
- this.#selected.sprite.z = Layer.Hidden;
1059
- }
1060
- v2.input.handled ||= hitsCursor;
1061
- this.#invalid = false;
1062
- return invalid;
1063
- }
1064
- setXY(v2, xy) {
1065
- if (xyEq(xy, this.#xy)) return;
1066
- this.#xy.x = xy.x;
1067
- this.#xy.y = xy.y;
1068
- this.#button.xy = xy;
1069
- this.#moveText(v2);
1070
- this.#pressed.sprite.xy = xy;
1071
- this.#selected.sprite.xy = xy;
1072
- this.#invalid = true;
1073
- }
1074
- #moveText(v2) {
1075
- this.#text.layout(v2);
1076
- this.#text.xy = {
1077
- x: this.#button.xy.x + this.#button.wh.w / 2 - this.#text.wh.w / 2,
1078
- y: this.#button.xy.y + this.#button.wh.h / 2 - (this.#text.wh.h - this.#text.scaledLeading) / 2
1079
- };
1080
- }
1081
- };
1082
-
1083
- // src/ents/cursor-ent.ts
1084
- var CursorEnt = class {
1085
- keyboard = false;
1086
- #sprite;
1087
- constructor(v2, tag) {
1088
- this.#sprite = v2.sprites.alloc();
1089
- this.#sprite.tag = tag;
1090
- this.#sprite.z = Layer.Hidden;
1091
- }
1092
- free(v2) {
1093
- v2.sprites.free(this.#sprite);
1094
- }
1095
- hitbox(v2, coords) {
1096
- const lvl = coords === "Level";
1097
- const hitbox = this.#sprite.hitbox;
1098
- if (!hitbox) throw Error("cursor has no hitbox");
1099
- return {
1100
- x: (lvl ? v2.cam.x : 0) + hitbox.x,
1101
- y: (lvl ? v2.cam.y : 0) + hitbox.y,
1102
- w: hitbox.w,
1103
- h: hitbox.h
1104
- };
1105
- }
1106
- hits(v2, box, coords) {
1107
- return this.visible && boxHits(this.hitbox(v2, coords), box);
1108
- }
1109
- update(v2) {
1110
- if (v2.input.point?.invalid) {
1111
- this.#sprite.xy = v2.input.point.local;
1112
- this.#sprite.z = v2.input.point?.type === "Mouse" ? Layer.Top : Layer.Hidden;
1113
- return true;
1114
- }
1115
- if (this.keyboard && v2.input.isAnyOn("L", "R", "U", "D")) {
1116
- const epsilon = 1;
1117
- if (v2.input.isOn("L")) this.#sprite.x -= epsilon;
1118
- if (v2.input.isOn("R")) this.#sprite.x += epsilon;
1119
- if (v2.input.isOn("U")) this.#sprite.y -= epsilon;
1120
- if (v2.input.isOn("D")) this.#sprite.y += epsilon;
1121
- this.#sprite.z = Layer.Top;
1122
- return true;
1123
- }
1124
- }
1125
- get visible() {
1126
- return this.#sprite.z !== Layer.Hidden;
1127
- }
1128
- };
1129
-
1130
- // src/ents/follow-cam-ent.ts
1131
- var FollowCamEnt = class {
1132
- #fill;
1133
- #invalid = true;
1134
- #margin = { w: 0, h: 0 };
1135
- #modulo = { x: 0, y: 0 };
1136
- #pivot;
1137
- #sprite;
1138
- constructor(v2, tag, pivot) {
1139
- this.#sprite = v2.sprites.alloc();
1140
- this.#sprite.tag = tag;
1141
- this.#pivot = pivot;
1142
- }
1143
- get fill() {
1144
- return this.#fill;
1145
- }
1146
- set fill(fill) {
1147
- if (this.#fill === fill) return;
1148
- this.#fill = fill;
1149
- this.#invalid = true;
1150
- }
1151
- free(v2) {
1152
- v2.sprites.free(this.#sprite);
1153
- }
1154
- get h() {
1155
- return this.#sprite.h;
1156
- }
1157
- set h(h) {
1158
- if (this.#sprite.h === h) return;
1159
- this.#sprite.h = h;
1160
- this.#invalid = true;
1161
- }
1162
- get margin() {
1163
- return this.#margin;
1164
- }
1165
- set margin(margin) {
1166
- if (whEq(margin, this.#margin)) return;
1167
- whAssign(this.#margin, margin);
1168
- this.#invalid = true;
1169
- }
1170
- get modulo() {
1171
- return this.#modulo;
1172
- }
1173
- set modulo(modulo) {
1174
- if (xyEq(modulo, this.#modulo)) return;
1175
- xyAssign(this.#modulo, modulo);
1176
- this.#invalid = true;
1177
- }
1178
- get pivot() {
1179
- return this.#pivot;
1180
- }
1181
- set pivot(pivot) {
1182
- if (this.#pivot === pivot) return;
1183
- this.#pivot = pivot;
1184
- this.#invalid = true;
1185
- }
1186
- update(v2) {
1187
- if (!this.#invalid && !v2.cam.invalid) return;
1188
- const follow = v2.cam.follow(
1189
- { w: this.#sprite.w, h: this.#sprite.h },
1190
- this.#sprite.z,
1191
- this.#pivot,
1192
- { fill: this.#fill, modulo: this.#modulo, margin: this.#margin }
1193
- );
1194
- this.#sprite.x = follow.x;
1195
- this.#sprite.y = follow.y;
1196
- this.#invalid = false;
1197
- return true;
1198
- }
1199
- get w() {
1200
- return this.#sprite.w;
1201
- }
1202
- set w(w) {
1203
- if (this.#sprite.w === w) return;
1204
- this.#sprite.w = w;
1205
- this.#invalid = true;
1206
- }
1207
- get z() {
1208
- return this.#sprite.z;
1209
- }
1210
- set z(z) {
1211
- this.#sprite.z = z;
1212
- }
1213
- };
1214
-
1215
- // src/ents/zoo.ts
1216
- var Zoo = class {
1217
- #cursor;
1218
- #ents = /* @__PURE__ */ new Set();
1219
- add(...ents) {
1220
- for (const ent of ents) {
1221
- this.#ents.add(ent);
1222
- if (ent instanceof CursorEnt) this.#cursor = ent;
1223
- }
1224
- }
1225
- clear() {
1226
- this.#cursor = void 0;
1227
- this.#ents.clear();
1228
- }
1229
- get cursor() {
1230
- return this.#cursor;
1231
- }
1232
- remove(...ents) {
1233
- for (const ent of ents) {
1234
- this.#ents.delete(ent);
1235
- if (ent === this.#cursor) this.#cursor = void 0;
1236
- }
1237
- }
1238
- update(v2) {
1239
- let invalid = false;
1240
- for (const ent of this.#ents) if (ent.update?.(v2)) invalid = true;
1241
- return invalid;
1242
- }
1243
- };
1244
-
1245
- // src/graphics/atlas.ts
1246
- var animCels = 16;
1247
- var animMillis = 1e3;
1248
- var celMillis = animMillis / animCels;
1249
-
1250
- // src/graphics/atlas-parser.ts
1251
- function parseAtlas(json) {
1252
- return {
1253
- anim: json.anim,
1254
- celXYWH: parseCelXYWH(json),
1255
- tags: Object.keys(json.anim)
1256
- };
1257
- }
1258
- function parseCelXYWH(json) {
1259
- const cels = [];
1260
- let i = 0;
1261
- for (const anim of Object.values(json.anim)) {
1262
- cels.push(...parseXYWH(anim, json.celXY, i));
1263
- i += anim.cels * 2;
1264
- }
1265
- return cels;
1266
- }
1267
- function parseXYWH(anim, celXY, i) {
1268
- const xywh = [];
1269
- for (let ii = 0; ii < animCels; ii++) {
1270
- const iii = i + 2 * (ii % anim.cels);
1271
- xywh.push(celXY[iii], celXY[iii + 1], anim.w, anim.h);
1272
- }
1273
- return xywh;
1274
- }
1275
-
1276
- // src/graphics/cam.ts
1277
- var Cam = class {
1278
- #h = 1;
1279
- #invalid = true;
1280
- #minScale = 1;
1281
- #minWH = { w: Infinity, h: Infinity };
1282
- #mode = "Int";
1283
- #scale = 1;
1284
- #w = 1;
1285
- #whClient = { w: 1, h: 1 };
1286
- #x = 0;
1287
- #y = 0;
1288
- #zoomOut = 0;
1289
- center(xy) {
1290
- this.x = Math.floor(xy.x - this.w / 2);
1291
- this.y = Math.floor(xy.y - this.h / 2);
1292
- }
1293
- /** position in fractional level coordinates. */
1294
- clientToXY(client) {
1295
- const local = this.clientToXYLocal(client);
1296
- return { x: this.#x + local.x, y: this.#y + local.y };
1297
- }
1298
- /**
1299
- * position relative canvas top-left in level scale (like level xy but no cam
1300
- * offset). often used for UI that is fixed within the cam.
1301
- */
1302
- clientToXYLocal(client) {
1303
- return {
1304
- x: client.x / this.#whClient.w * this.#w,
1305
- y: client.y / this.#whClient.h * this.#h
1306
- };
1307
- }
1308
- follow(wh, z, pivot, opts) {
1309
- const marginW = opts?.margin?.w ?? 0;
1310
- let x = z > Layer.UIG ? Math.trunc(this.x) : 0;
1311
- switch (pivot) {
1312
- case "SW":
1313
- case "W":
1314
- case "NW":
1315
- x += marginW;
1316
- break;
1317
- case "SE":
1318
- case "E":
1319
- case "NE":
1320
- x += this.w - (wh.w + marginW);
1321
- break;
1322
- case "N":
1323
- case "S":
1324
- case "Origin":
1325
- x += Math.trunc(this.w / 2) - Math.trunc(wh.w / 2);
1326
- break;
1327
- }
1328
- x -= x % ((opts?.modulo?.x ?? x) || 1);
1329
- const marginH = opts?.margin?.h ?? 0;
1330
- let y = z > Layer.UIG ? Math.trunc(this.y) : 0;
1331
- switch (pivot) {
1332
- case "N":
1333
- case "NE":
1334
- case "NW":
1335
- y += marginH;
1336
- break;
1337
- case "SE":
1338
- case "S":
1339
- case "SW":
1340
- y += this.h - (wh.h + marginH);
1341
- break;
1342
- case "E":
1343
- case "W":
1344
- case "Origin":
1345
- y += Math.trunc(this.h / 2) - Math.trunc(wh.h / 2);
1346
- break;
1347
- }
1348
- y -= y % ((opts?.modulo?.y ?? y) || 1);
1349
- const w = opts?.fill === "X" || opts?.fill === "XY" ? this.w - 2 * marginW : wh.w;
1350
- const h = opts?.fill === "Y" || opts?.fill === "XY" ? this.h - 2 * marginH : wh.h;
1351
- return { x, y, w, h };
1352
- }
1353
- /** positive int in level px. */
1354
- get h() {
1355
- return this.#h;
1356
- }
1357
- isVisible(box) {
1358
- return boxHits(this, box);
1359
- }
1360
- /** true if cam moved or resized since last update. */
1361
- get invalid() {
1362
- return this.#invalid;
1363
- }
1364
- /** positive int or fraction depending on mode. */
1365
- get minScale() {
1366
- return this.#minScale;
1367
- }
1368
- set minScale(scale) {
1369
- if (this.#scale === scale) return;
1370
- this.#scale = scale;
1371
- this.#invalidateWH();
1372
- }
1373
- /**
1374
- * positive int or infinite min dimensions. set to
1375
- * `{w: Infinity, h: Infinity}` to always use min scale.
1376
- */
1377
- get minWH() {
1378
- return this.#minWH;
1379
- }
1380
- set minWH(wh) {
1381
- if (this.#minWH.w === wh.w && this.#minWH.h === wh.h) return;
1382
- this.#minWH.w = wh.w;
1383
- this.#minWH.h = wh.h;
1384
- this.#invalidateWH();
1385
- }
1386
- get mode() {
1387
- return this.#mode;
1388
- }
1389
- set mode(mode) {
1390
- if (this.#mode === mode) return;
1391
- this.#mode = mode;
1392
- this.#invalidateWH();
1393
- }
1394
- get portrait() {
1395
- return this.h > this.w;
1396
- }
1397
- postupdate() {
1398
- this.#invalid = false;
1399
- }
1400
- /** positive int or fraction depending on mode. */
1401
- get scale() {
1402
- return this.#scale;
1403
- }
1404
- toString() {
1405
- return `Cam{(${this.x} ${this.y}) ${this.w}\xD7${this.h}}`;
1406
- }
1407
- /**
1408
- * call after input processing but before ent processing. ents that move the
1409
- * camera should be called immediately after update so that the invalid state
1410
- * can be considered.
1411
- */
1412
- update(canvas) {
1413
- if (!canvas.parentElement) throw Error("canvas has no parent");
1414
- const { clientWidth, clientHeight } = canvas.parentElement;
1415
- this.#invalid ||= this.#whClient.w !== clientWidth || this.#whClient.h !== clientHeight;
1416
- if (!this.#invalid) return;
1417
- this.#whClient.w = clientWidth;
1418
- this.#whClient.h = clientHeight;
1419
- this.#invalidateWH();
1420
- canvas.width = this.#w;
1421
- canvas.height = this.#h;
1422
- canvas.style.width = `${this.#w * this.#scale / devicePixelRatio}px`;
1423
- canvas.style.height = `${this.#h * this.#scale / devicePixelRatio}px`;
1424
- }
1425
- /** positive int in level px. */
1426
- get w() {
1427
- return this.#w;
1428
- }
1429
- /**
1430
- * positive int dimensions in client px of canvas (often
1431
- * `canvas.parentElement.clientWidth/Height` since the canvas is resized)
1432
- * which is assumed to be max WH.
1433
- */
1434
- get whClient() {
1435
- return this.#whClient;
1436
- }
1437
- /** fractional. */
1438
- get x() {
1439
- return this.#x;
1440
- }
1441
- set x(x) {
1442
- this.#invalid ||= this.x !== x;
1443
- this.#x = x;
1444
- }
1445
- /** fractional. */
1446
- get y() {
1447
- return this.#y;
1448
- }
1449
- set y(y) {
1450
- this.#invalid ||= this.y !== y;
1451
- this.#y = y;
1452
- }
1453
- /** nonnegative int or fraction depending on mode. */
1454
- get zoomOut() {
1455
- return this.#zoomOut;
1456
- }
1457
- set zoomOut(out) {
1458
- out = Math.max(0, out);
1459
- if (this.#zoomOut === out) return;
1460
- this.#zoomOut = out;
1461
- this.#invalidateWH();
1462
- }
1463
- #invalidateWH() {
1464
- this.#invalid = true;
1465
- const phy = {
1466
- w: this.#whClient.w * devicePixelRatio,
1467
- h: this.#whClient.h * devicePixelRatio
1468
- };
1469
- const scale = Math.max(
1470
- this.#minScale,
1471
- Math.min(phy.w / this.#minWH.w, phy.h / this.#minWH.h) - (this.#mode === "Int" ? Math.trunc(this.#zoomOut) : this.#zoomOut)
1472
- );
1473
- this.#scale = this.#mode === "Int" ? Math.trunc(scale) : scale;
1474
- this.#w = Math.ceil(phy.w / this.#scale);
1475
- this.#h = Math.ceil(phy.h / this.#scale);
1476
- }
1477
- };
1478
-
1479
- // src/utils/math.ts
1480
- function mod(dividend, divisor) {
1481
- return (dividend % divisor + divisor) % divisor;
1482
- }
1483
-
1484
- // src/graphics/sprite.ts
1485
- var drawableBytes = 12;
1486
- var drawableEpsilon = 1 / 64;
1487
- var drawableMaxWH = { w: 4095, h: 4095 };
1488
- var Drawable = class {
1489
- i;
1490
- #pool;
1491
- constructor(pool, i) {
1492
- this.#pool = pool;
1493
- this.i = i;
1494
- }
1495
- above(draw) {
1496
- const compare = this.z === draw.z ? (draw.zend ? draw.y + draw.h : draw.y) - (this.zend ? this.y + this.h : this.y) : this.z - draw.z;
1497
- return compare < 0;
1498
- }
1499
- get cel() {
1500
- const iiic_cccc = this.#pool.view.getUint8(this.i + 10);
1501
- return iiic_cccc & 31;
1502
- }
1503
- /**
1504
- * [0, 31]. rendered cel offset. call reset() to play animation from start.
1505
- */
1506
- set cel(cel) {
1507
- const iiic_cccc = this.#pool.view.getUint8(this.i + 10);
1508
- this.#pool.view.setUint8(this.i + 10, iiic_cccc & ~31 | cel & 31);
1509
- }
1510
- /** test if render area overlaps box or sprite render area. */
1511
- clips(box) {
1512
- return boxHits(this, box);
1513
- }
1514
- get flipX() {
1515
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1516
- return !!(sxyz_llll & 64);
1517
- }
1518
- set flipX(flip) {
1519
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1520
- this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~64 | -flip & 64);
1521
- }
1522
- get flipY() {
1523
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1524
- return !!(sxyz_llll & 32);
1525
- }
1526
- set flipY(flip) {
1527
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1528
- this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~32 | -flip & 32);
1529
- }
1530
- get h() {
1531
- const h12_wwww = this.#pool.view.getUint16(this.i + 8, true);
1532
- return h12_wwww >>> 4;
1533
- }
1534
- /** [0, 4095]. */
1535
- set h(h) {
1536
- const h12_wwww = this.#pool.view.getUint16(this.i + 8, true);
1537
- this.#pool.view.setUint16(
1538
- this.i + 8,
1539
- h12_wwww & ~(4095 << 4) | (h & 4095) << 4,
1540
- true
1541
- );
1542
- }
1543
- get id() {
1544
- const i11_c5 = this.#pool.view.getUint16(this.i + 10, true);
1545
- return i11_c5 >>> 5 & 2047;
1546
- }
1547
- /** [0, 2047]. */
1548
- set id(id) {
1549
- const i11_c5 = this.#pool.view.getUint16(this.i + 10, true);
1550
- this.#pool.view.setUint16(
1551
- this.i + 10,
1552
- i11_c5 & ~(2047 << 5) | (id & 2047) << 5,
1553
- true
1554
- );
1555
- }
1556
- get stretch() {
1557
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1558
- return !!(sxyz_llll & 128);
1559
- }
1560
- /** wrap texture (default) or stretch to width and height. */
1561
- set stretch(stretch) {
1562
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1563
- this.#pool.view.setUint8(
1564
- this.i + 6,
1565
- sxyz_llll & ~128 | -stretch & 128
1566
- );
1567
- }
1568
- get w() {
1569
- const hhhh_w12 = this.#pool.view.getUint16(this.i + 7, true);
1570
- return hhhh_w12 & 4095;
1571
- }
1572
- /** [0, 4095]. */
1573
- set w(w) {
1574
- const hhhh_w12 = this.#pool.view.getUint16(this.i + 7, true);
1575
- this.#pool.view.setUint16(
1576
- this.i + 7,
1577
- hhhh_w12 & ~4095 | w & 4095,
1578
- true
1579
- );
1580
- }
1581
- get x() {
1582
- const y8_x24 = this.#pool.view.getUint32(this.i + 0, true);
1583
- return (y8_x24 << 8 >> 8) / 64;
1584
- }
1585
- /** [-131072, 131071.984375] with 1/64th (0.015625) granularity. */
1586
- set x(x) {
1587
- const y8_x24 = this.#pool.view.getUint32(this.i + 0, true);
1588
- this.#pool.view.setUint32(
1589
- this.i + 0,
1590
- y8_x24 & ~16777215 | x * 64 & 16777215,
1591
- true
1592
- );
1593
- }
1594
- get xy() {
1595
- return { x: this.x, y: this.y };
1596
- }
1597
- set xy(xy) {
1598
- this.x = xy.x;
1599
- this.y = xy.y;
1600
- }
1601
- get y() {
1602
- const sxyz_llll_y24 = this.#pool.view.getUint32(this.i + 3, true);
1603
- return (sxyz_llll_y24 << 8 >> 8) / 64;
1604
- }
1605
- /** [-131072, 131071.984375] with 1/64th (0.015625) granularity. */
1606
- set y(y) {
1607
- const sxyz_llll_y24 = this.#pool.view.getUint32(this.i + 3, true);
1608
- this.#pool.view.setUint32(
1609
- this.i + 3,
1610
- sxyz_llll_y24 & ~16777215 | y * 64 & 16777215,
1611
- true
1612
- );
1613
- }
1614
- get z() {
1615
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1616
- return sxyz_llll & 15;
1617
- }
1618
- /** layer [0 (closest), 14 (furthest)]; 15 is hidden. */
1619
- set z(z) {
1620
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1621
- this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~15 | z & 15);
1622
- }
1623
- get zend() {
1624
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1625
- return !!(sxyz_llll & 16);
1626
- }
1627
- /** z-order by top (default) or bottom of box. */
1628
- set zend(end) {
1629
- const sxyz_llll = this.#pool.view.getUint8(this.i + 6);
1630
- this.#pool.view.setUint8(this.i + 6, sxyz_llll & ~16 | -end & 16);
1631
- }
1632
- };
1633
- var Sprite = class _Sprite extends Drawable {
1634
- #atlas;
1635
- #framer;
1636
- #hitbox;
1637
- #hurtbox;
1638
- constructor(pool, i, atlas, framer) {
1639
- super(pool, i);
1640
- this.#atlas = atlas;
1641
- this.#framer = framer;
1642
- }
1643
- get anim() {
1644
- return this.#atlas.anim[this.tag];
1645
- }
1646
- get flipX() {
1647
- return super.flipX;
1648
- }
1649
- set flipX(flip) {
1650
- if (this.flipX === flip) return;
1651
- super.flipX = flip;
1652
- this.#hitbox = void 0;
1653
- this.#hurtbox = void 0;
1654
- }
1655
- get flipY() {
1656
- return super.flipY;
1657
- }
1658
- set flipY(flip) {
1659
- if (this.flipY === flip) return;
1660
- super.flipY = flip;
1661
- this.#hitbox = void 0;
1662
- this.#hurtbox = void 0;
1663
- }
1664
- get h() {
1665
- return super.h;
1666
- }
1667
- set h(h) {
1668
- if (this.h === h) return;
1669
- super.h = h;
1670
- this.#hitbox = void 0;
1671
- this.#hurtbox = void 0;
1672
- }
1673
- get hitbox() {
1674
- if (this.#hitbox) return this.#hitbox;
1675
- const { hitbox } = this.anim;
1676
- if (!hitbox) return;
1677
- return this.#hitbox ??= {
1678
- x: this.x + (this.flipX ? this.w - hitbox.w - hitbox.x : hitbox.x),
1679
- y: this.y + (this.flipY ? this.h - hitbox.h - hitbox.y : hitbox.y),
1680
- w: hitbox.w,
1681
- h: hitbox.h
1682
- };
1683
- }
1684
- hits(box) {
1685
- const hitbox = this.hitbox;
1686
- if (!hitbox) return false;
1687
- const hurtbox = box instanceof _Sprite ? box.hurtbox : box;
1688
- return !!hurtbox && boxHits(hitbox, hurtbox);
1689
- }
1690
- get hurtbox() {
1691
- if (this.#hurtbox) return this.#hurtbox;
1692
- const { hurtbox } = this.anim;
1693
- if (!hurtbox) return;
1694
- return this.#hurtbox ??= {
1695
- x: this.x + (this.flipX ? this.w - hurtbox.w - hurtbox.x : hurtbox.x),
1696
- y: this.y + (this.flipY ? this.h - hurtbox.h - hurtbox.y : hurtbox.y),
1697
- w: hurtbox.w,
1698
- h: hurtbox.h
1699
- };
1700
- }
1701
- get id() {
1702
- return super.id;
1703
- }
1704
- set id(id) {
1705
- if (this.id === id) return;
1706
- super.id = id;
1707
- this.#hitbox = void 0;
1708
- this.#hurtbox = void 0;
1709
- }
1710
- /** true if animation has played once. */
1711
- get looped() {
1712
- return mod(this.#currentCel - this.cel, animCels * 2) >= this.anim.cels;
1713
- }
1714
- /** sets cel to animation start. */
1715
- reset() {
1716
- this.cel = this.#currentCel;
1717
- }
1718
- // to-do: unit test and catch up on unit tests elsewhere.
1719
- get tag() {
1720
- return this.#atlas.tags[this.id];
1721
- }
1722
- /** sets animation, resets cel, dimensions, hitbox, and hurtbox. */
1723
- set tag(tag) {
1724
- const anim = this.#atlas.anim[tag];
1725
- this.w = anim.w;
1726
- this.h = anim.h;
1727
- this.id = anim.id;
1728
- this.reset();
1729
- }
1730
- toString() {
1731
- return `Sprite{${this.tag} (${this.x} ${this.y} ${this.z}) ${this.w}\xD7${this.h}}`;
1732
- }
1733
- get w() {
1734
- return super.w;
1735
- }
1736
- set w(w) {
1737
- if (this.w === w) return;
1738
- super.w = w;
1739
- this.#hitbox = void 0;
1740
- this.#hurtbox = void 0;
1741
- }
1742
- get x() {
1743
- return super.x;
1744
- }
1745
- set x(x) {
1746
- if (this.x === x) return;
1747
- super.x = x;
1748
- this.#hitbox = void 0;
1749
- this.#hurtbox = void 0;
1750
- }
1751
- get y() {
1752
- return super.y;
1753
- }
1754
- set y(y) {
1755
- if (this.y === y) return;
1756
- super.y = y;
1757
- this.#hitbox = void 0;
1758
- this.#hurtbox = void 0;
1759
- }
1760
- /** current fractional cel in [0, 2 * anim.cels). */
1761
- get #currentCel() {
1762
- const cel = this.#framer.age / celMillis;
1763
- return cel % (this.anim.cels * 2);
1764
- }
1765
- };
1766
-
1767
- // src/input/context-menu.ts
1768
- var ContextMenu = class {
1769
- enable = false;
1770
- #target;
1771
- constructor(target) {
1772
- this.#target = target;
1773
- }
1774
- register(op) {
1775
- const fn = this.#target[`${op}EventListener`].bind(this.#target);
1776
- fn("contextmenu", this.#onContextMenu);
1777
- fn("touchstart", this.#onContextMenu, { passive: false });
1778
- return this;
1779
- }
1780
- [Symbol.dispose]() {
1781
- this.register("remove");
1782
- }
1783
- #onContextMenu = (ev) => {
1784
- if (!ev.isTrusted || ev.metaKey || ev.altKey || ev.ctrlKey) return;
1785
- if (!this.enable) ev.preventDefault();
1786
- };
1787
- };
1788
-
1789
- // src/input/gamepad.ts
1790
- var Gamepad = class {
1791
- bits = 0;
1792
- // to-do: support analog button values, expose connected status and vibration,
1793
- // and distinct devices. would be nice if vibration could merge with
1794
- // navigator.vibrate().
1795
- bitByAxis = {};
1796
- bitByButton = {};
1797
- onEvent = () => {
1798
- };
1799
- #target;
1800
- constructor(target) {
1801
- this.#target = target;
1802
- }
1803
- get connected() {
1804
- return isSecureContext && navigator.getGamepads().filter(Boolean).length > 0;
1805
- }
1806
- register(op) {
1807
- const fn = this.#target[`${op}EventListener`].bind(this.#target);
1808
- fn("gamepadconnected", this.onEvent);
1809
- fn("gamepaddisconnected", this.onEvent);
1810
- return this;
1811
- }
1812
- reset() {
1813
- this.bits = 0;
1814
- }
1815
- [Symbol.dispose]() {
1816
- this.register("remove");
1817
- }
1818
- update() {
1819
- if (!isSecureContext) return;
1820
- for (const pad of navigator.getGamepads()) {
1821
- for (const [index, axis] of pad?.axes.entries() ?? []) {
1822
- const lessMore = this.bitByAxis[index];
1823
- if (!lessMore) continue;
1824
- const bit = axis < 0 ? lessMore[0] : axis === 0 ? 0 : lessMore[1];
1825
- this.bits |= Math.abs(axis) >= 0.5 ? bit : 0;
1826
- }
1827
- for (const [index, btn] of pad?.buttons.entries() ?? []) {
1828
- const bit = this.bitByButton[index];
1829
- if (bit == null) continue;
1830
- this.bits |= btn.pressed ? bit : 0;
1831
- }
1832
- }
1833
- }
1834
- };
1835
-
1836
- // src/input/keyboard.ts
1837
- var Keyboard = class {
1838
- /** KeyboardEvent.code to bit. */
1839
- bitByCode = {};
1840
- invalid = false;
1841
- /** KeyboardEvent.code to state. Multiple keys may map to the same bit. */
1842
- onEvent = () => {
1843
- };
1844
- #on = {};
1845
- #target;
1846
- constructor(target) {
1847
- this.#target = target;
1848
- }
1849
- get bits() {
1850
- let bits = 0;
1851
- for (const k in this.bitByCode) bits |= this.#on[k] ? this.bitByCode[k] : 0;
1852
- return bits;
1853
- }
1854
- postupdate() {
1855
- this.invalid = false;
1856
- }
1857
- register(op) {
1858
- const fn = this.#target[`${op}EventListener`].bind(this.#target);
1859
- for (const ev of ["keydown", "keyup"]) fn(ev, this.#onKey);
1860
- return this;
1861
- }
1862
- reset() {
1863
- this.invalid = false;
1864
- this.#on = {};
1865
- }
1866
- [Symbol.dispose]() {
1867
- this.register("remove");
1868
- }
1869
- #onKey = (ev) => {
1870
- if (!ev.isTrusted || this.bitByCode[ev.code] == null) return;
1871
- if (ev.type === "keydown" && (ev.metaKey || ev.altKey || ev.ctrlKey)) return;
1872
- this.invalid = true;
1873
- this.#on[ev.code] = ev.type === "keydown";
1874
- ev.preventDefault();
1875
- this.onEvent();
1876
- };
1877
- };
1878
-
1879
- // src/input/pointer.ts
1880
- var pointTypeByPointerType = {
1881
- mouse: "Mouse",
1882
- pen: "Pen",
1883
- touch: "Touch"
1884
- };
1885
- var pointEvents = [
1886
- "pointercancel",
1887
- "pointerdown",
1888
- "pointermove",
1889
- "pointerup"
1890
- ];
1891
- var Pointer = class {
1892
- bitByButton = {};
1893
- dragMinClient = 5;
1894
- invalid = false;
1895
- onEvent = () => {
1896
- };
1897
- /** primary may be on or off. */
1898
- primary;
1899
- /**
1900
- * secondaries are deleted when buttons are off. secondaries are only present
1901
- * when primary is defined.
1902
- */
1903
- secondary = {};
1904
- /** nonnegative. */
1905
- #pinchStartClient;
1906
- #target;
1907
- constructor(target) {
1908
- this.#target = target;
1909
- }
1910
- get boundsClient() {
1911
- if (!this.primary?.bits && !Object.keys(this.secondary).length) return;
1912
- let min = { x: Infinity, y: Infinity };
1913
- let max = { x: -Infinity, y: -Infinity };
1914
- for (const pt of [this.primary, ...Object.values(this.secondary)]) {
1915
- if (!pt?.bits) continue;
1916
- min = xyMin(min, pt.xyClient);
1917
- max = xyMax(max, pt.xyClient);
1918
- }
1919
- return { x: min.x, y: min.y, w: max.x - min.x, h: max.y - min.y };
1920
- }
1921
- get centerClient() {
1922
- const bounds = this.boundsClient;
1923
- if (!bounds) return this.primary?.xyClient;
1924
- return xyAdd(bounds, { x: bounds.w / 2, y: bounds.h / 2 });
1925
- }
1926
- get locked() {
1927
- return this.#target.ownerDocument.pointerLockElement === this.#target;
1928
- }
1929
- get pinchClient() {
1930
- if (!this.#pinchStartClient) return;
1931
- const end = this.#newPinchClient;
1932
- return end ? xySub(end, this.#pinchStartClient) : void 0;
1933
- }
1934
- postupdate() {
1935
- this.invalid = false;
1936
- }
1937
- register(op) {
1938
- const fn = this.#target[`${op}EventListener`].bind(this.#target);
1939
- for (const ev of pointEvents) fn(ev, this.#onInput);
1940
- return this;
1941
- }
1942
- reset() {
1943
- this.invalid = false;
1944
- this.primary = void 0;
1945
- for (const pt in this.secondary) delete this.secondary[pt];
1946
- this.#pinchStartClient = void 0;
1947
- }
1948
- update() {
1949
- const on = (this.primary?.bits ? 1 : 0) + Object.values(this.secondary).length;
1950
- if (on < 2 || !this.#pinchStartClient)
1951
- this.#pinchStartClient = this.#newPinchClient;
1952
- }
1953
- [Symbol.dispose]() {
1954
- this.register("remove");
1955
- }
1956
- #evButtonsToBits(btns) {
1957
- let bits = 0;
1958
- for (let btn = 1; btn <= btns; btn <<= 1)
1959
- if ((btn & btns) === btn) bits |= this.bitByButton[btn] ?? 0;
1960
- return bits;
1961
- }
1962
- #onInput = (ev) => {
1963
- if (!ev.isTrusted) return;
1964
- this.invalid = true;
1965
- const bits = ev.metaKey || ev.altKey || ev.ctrlKey ? 0 : this.#evButtonsToBits(ev.buttons);
1966
- if (bits) ev.preventDefault();
1967
- const locked = this.locked;
1968
- if (ev.type === "pointerdown" && !locked)
1969
- try {
1970
- this.#target.setPointerCapture(ev.pointerId);
1971
- } catch {
1972
- }
1973
- const prevPt = ev.isPrimary ? this.primary : this.secondary[ev.pointerId];
1974
- let xyClient;
1975
- if (locked) {
1976
- const scale = 1 / devicePixelRatio;
1977
- xyClient = {
1978
- x: Math.min(
1979
- Math.max(
1980
- 0,
1981
- (prevPt?.xyClient.x ?? ev.offsetX) + ev.movementX * scale
1982
- ),
1983
- this.#target.clientWidth
1984
- ),
1985
- y: Math.min(
1986
- Math.max(
1987
- 0,
1988
- (prevPt?.xyClient.y ?? ev.offsetY) + ev.movementY * scale
1989
- ),
1990
- this.#target.clientHeight
1991
- )
1992
- };
1993
- } else xyClient = { x: ev.offsetX, y: ev.offsetY };
1994
- const evType = ev.type;
1995
- const type = pointTypeByPointerType[ev.pointerType];
1996
- let clickClient;
1997
- if (ev.type === "pointerdown") clickClient = { x: xyClient.x, y: xyClient.y };
1998
- else if (ev.type === "pointermove") clickClient = prevPt?.clickClient;
1999
- const drag = !!bits && (prevPt?.drag || !!clickClient && xyDistance(clickClient, xyClient) >= this.dragMinClient);
2000
- const pt = {
2001
- clickClient,
2002
- bits,
2003
- drag,
2004
- ev: evType,
2005
- id: ev.pointerId,
2006
- primary: ev.isPrimary,
2007
- type,
2008
- xyClient
2009
- };
2010
- if (ev.isPrimary) this.primary = pt;
2011
- else if (!bits) delete this.secondary[ev.pointerId];
2012
- else this.secondary[ev.pointerId] = pt;
2013
- this.onEvent();
2014
- };
2015
- get #newPinchClient() {
2016
- if ((this.primary?.bits ? 1 : 0) + Object.values(this.secondary).length < 2)
2017
- return;
2018
- const bounds = this.boundsClient;
2019
- return bounds ? { x: bounds.w, y: bounds.h } : void 0;
2020
- }
2021
- };
2022
-
2023
- // src/input/wheel.ts
2024
- var Wheel = class {
2025
- deltaClient;
2026
- onEvent = () => {
2027
- };
2028
- #target;
2029
- constructor(target) {
2030
- this.#target = target;
2031
- }
2032
- postupdate() {
2033
- this.deltaClient = void 0;
2034
- }
2035
- register(op) {
2036
- const fn = this.#target[`${op}EventListener`].bind(this.#target);
2037
- fn("wheel", this.#onInput, { passive: true });
2038
- return this;
2039
- }
2040
- reset() {
2041
- this.deltaClient = void 0;
2042
- }
2043
- [Symbol.dispose]() {
2044
- this.register("remove");
2045
- }
2046
- #onInput = (ev) => {
2047
- if (!ev.isTrusted || ev.metaKey || ev.altKey || ev.ctrlKey) return;
2048
- this.deltaClient = { x: ev.deltaX, y: ev.deltaY, z: ev.deltaZ };
2049
- this.onEvent();
2050
- };
2051
- };
2052
-
2053
- // src/input/input.ts
2054
- var Input = class {
2055
- /** time allowed between combo inputs. */
2056
- comboMaxIntervalMillis = 300;
2057
- /**
2058
- * true if any button, key, or click was _ever_ on. doesn't consider handled.
2059
- */
2060
- gestured = false;
2061
- /** clear buttonish inputs for rest of frame. */
2062
- handled = false;
2063
- /** true if _any_ input has changed since previous update. */
2064
- invalid = false;
2065
- /**
2066
- * minimum duration for an input to be considered held. durations are
2067
- * calculated at frame boundaries, not on actual press. devices are treated
2068
- * strictly as polled aggregates.
2069
- */
2070
- minHeldMillis = 300;
2071
- #bitByButton = {};
2072
- #buttonByBit = {};
2073
- #bits = 0;
2074
- #cam;
2075
- /**
2076
- * sequence of nonzero bits ordered from oldest to latest. combos end only by
2077
- * expiration.
2078
- */
2079
- #combo = [];
2080
- #contextMenu;
2081
- #gamepad;
2082
- /** time since buttons changed. */
2083
- #heldMillis = 0;
2084
- #keyboard;
2085
- #pointer;
2086
- #pointerState;
2087
- /** bits last update. may not be equal to `#combo.at(-1)`. */
2088
- #prevBits = 0;
2089
- #wheel;
2090
- #wheelState;
2091
- constructor(cam, target) {
2092
- this.#cam = cam;
2093
- this.#contextMenu = new ContextMenu(target);
2094
- this.#gamepad = new Gamepad(globalThis);
2095
- this.#keyboard = new Keyboard(target.ownerDocument);
2096
- this.#pointer = new Pointer(target);
2097
- this.#wheel = new Wheel(target);
2098
- }
2099
- get anyOn() {
2100
- return this.#bits !== 0;
2101
- }
2102
- /** for debugging. */
2103
- get combo() {
2104
- const chords = [];
2105
- for (const bits of this.#combo) {
2106
- const chord = [];
2107
- for (let bit = 1; bit <= bits; bit <<= 1) {
2108
- if ((bit & bits) === bit && this.#buttonByBit[bit])
2109
- chord.push(this.#buttonByBit[bit]);
2110
- }
2111
- chord.sort();
2112
- chords.push(chord);
2113
- }
2114
- return chords;
2115
- }
2116
- /**
2117
- * enable when game is paused or in photo mode to allow right clicks and long
2118
- * presses to save canvas.
2119
- */
2120
- get contextMenu() {
2121
- return this.#contextMenu;
2122
- }
2123
- /** doesn't consider handled. gamepads must be polled. */
2124
- get gamepad() {
2125
- return this.#gamepad.connected ? {} : void 0;
2126
- }
2127
- /** true if bits hasn't changed for a while. */
2128
- get held() {
2129
- return !this.handled && this.#heldMillis >= this.minHeldMillis;
2130
- }
2131
- isAnyOn(...btns) {
2132
- return !this.handled && !!(this.#bits & this.#mapBits(btns));
2133
- }
2134
- isAnyOnStart(...btns) {
2135
- return this.started && this.isAnyOn(...btns);
2136
- }
2137
- /**
2138
- * buttons are exact. eg, up won't match up AND down like `isOn('U')` will.
2139
- * combo is exact too. `['A'], ['A']` will match `['A'], ['A']` but not
2140
- * `['A'], ['A'], ['A']`.
2141
- */
2142
- isCombo(...combo) {
2143
- return combo.length === this.#combo.length && this.isComboEndsWith(...combo);
2144
- }
2145
- /**
2146
- * `['A'], ['A']` will match `['A'], ['A']` and `['B'], ['A'], ['A']`. eg,
2147
- * double-clicks often don't care about any preceding buttons.
2148
- */
2149
- isComboEndsWith(...combo) {
2150
- for (const [i, btns] of combo.entries()) {
2151
- const bits = this.#mapBits(btns);
2152
- if (this.#combo.at(-combo.length + i) !== bits) return false;
2153
- }
2154
- return !this.handled && (this.#combo.at(-1) === this.#bits || !this.#bits);
2155
- }
2156
- /** like isComboEndsWith() but test if the last button is triggered. */
2157
- isComboEndsWithStart(...combo) {
2158
- return this.isOnStart(...combo.at(-1)) && this.isComboEndsWith(...combo);
2159
- }
2160
- /** like isCombo() but test if the last button is triggered. */
2161
- isComboStart(...combo) {
2162
- return this.isOnStart(...combo.at(-1)) && this.isCombo(...combo);
2163
- }
2164
- /*:
2165
- * true if any button in chord is not on. this is usually what's wanted. eg:
2166
- * ```ts
2167
- * if (isOn('A', 'B')) console.log('on')
2168
- * if (isOff('A', 'B')) console.log('not A+B; A and/or B is off')
2169
- * ```
2170
- */
2171
- isOff(...btns) {
2172
- return !this.handled && !this.isOn(...btns);
2173
- }
2174
- isOffStart(...btns) {
2175
- const bits = this.#mapBits(btns);
2176
- const wasOn = (this.#prevBits & bits) === bits;
2177
- return wasOn && this.started && this.isOff(...btns);
2178
- }
2179
- /**
2180
- * true if all buttons are on inclusively. eg, `isOn('U')` is true when up is
2181
- * pressed or when up and down are pressed.
2182
- */
2183
- isOn(...btns) {
2184
- const bits = this.#mapBits(btns);
2185
- return !this.handled && (this.#bits & bits) === bits;
2186
- }
2187
- isOnStart(...btns) {
2188
- return this.started && this.isOn(...btns);
2189
- }
2190
- get key() {
2191
- return { invalid: this.#keyboard.invalid };
2192
- }
2193
- mapDefault() {
2194
- const input = this;
2195
- input.mapKeyboardCode("L", "ArrowLeft");
2196
- input.mapKeyboardCode("R", "ArrowRight");
2197
- input.mapKeyboardCode("U", "ArrowUp");
2198
- input.mapKeyboardCode("D", "ArrowDown");
2199
- input.mapKeyboardCode("C", "KeyC");
2200
- input.mapKeyboardCode("A", "KeyX");
2201
- input.mapKeyboardCode("B", "KeyZ");
2202
- input.mapKeyboardCode("Menu", "Enter");
2203
- input.mapKeyboardCode("Back", "Escape");
2204
- input.mapGamepadAxis("L", "R", 0, 2);
2205
- input.mapGamepadAxis("U", "D", 1, 3);
2206
- input.mapGamepadButton("L", 14);
2207
- input.mapGamepadButton("R", 15);
2208
- input.mapGamepadButton("U", 12);
2209
- input.mapGamepadButton("D", 13);
2210
- input.mapGamepadButton("C", 2);
2211
- input.mapGamepadButton("B", 0);
2212
- input.mapGamepadButton("A", 1);
2213
- input.mapGamepadButton("Menu", 9);
2214
- input.mapGamepadButton("Back", 8);
2215
- input.mapPointerClick("Click", 1);
2216
- input.mapPointerClick("Click2", 2);
2217
- input.mapPointerClick("ClickMiddle", 4);
2218
- return input;
2219
- }
2220
- // to-do: support analog values.
2221
- mapGamepadAxis(less, more, ...axes) {
2222
- for (const axis of axes) {
2223
- this.#gamepad.bitByAxis[axis] = [
2224
- this.#mapButton(less),
2225
- this.#mapButton(more)
2226
- ];
2227
- }
2228
- }
2229
- mapGamepadButton(btn, ...indices) {
2230
- for (const index of indices)
2231
- this.#gamepad.bitByButton[index] = this.#mapButton(btn);
2232
- }
2233
- /** @arg codes union of KeyboardEvent.code. */
2234
- mapKeyboardCode(btn, ...codes) {
2235
- for (const code of codes)
2236
- this.#keyboard.bitByCode[code] = this.#mapButton(btn);
2237
- }
2238
- mapPointerClick(btn, ...clicks) {
2239
- for (const click of clicks)
2240
- this.#pointer.bitByButton[click] = this.#mapButton(btn);
2241
- }
2242
- get on() {
2243
- const on = [];
2244
- for (const btn in this.#bitByButton) if (this.isOn(btn)) on.push(btn);
2245
- return on.sort();
2246
- }
2247
- set onEvent(cb) {
2248
- this.#gamepad.onEvent = cb;
2249
- this.#keyboard.onEvent = cb;
2250
- this.#pointer.onEvent = cb;
2251
- this.#wheel.onEvent = cb;
2252
- }
2253
- /** doesn't consider handled. */
2254
- get point() {
2255
- return this.#pointerState;
2256
- }
2257
- get pointer() {
2258
- return this.#pointer;
2259
- }
2260
- register(op) {
2261
- globalThis[`${op}EventListener`]("blur", this.reset);
2262
- this.#contextMenu.register(op);
2263
- this.#gamepad.register(op);
2264
- this.#keyboard.register(op);
2265
- this.#pointer.register(op);
2266
- this.#wheel.register(op);
2267
- return this;
2268
- }
2269
- reset = () => {
2270
- this.#bits = 0;
2271
- this.#prevBits = 0;
2272
- this.handled = false;
2273
- this.#heldMillis = 0;
2274
- this.#combo.length = 0;
2275
- this.#gamepad.reset();
2276
- this.#keyboard.reset();
2277
- this.#pointer.reset();
2278
- this.#pointerState = void 0;
2279
- this.#wheel.reset();
2280
- this.#wheelState = void 0;
2281
- };
2282
- /** true if bits has changed. */
2283
- get started() {
2284
- return !this.handled && this.#bits !== this.#prevBits;
2285
- }
2286
- /**
2287
- * call on new frame before altering cam. dispatches always occur before an
2288
- * update.
2289
- * @arg millis duration since last update.
2290
- */
2291
- update(millis) {
2292
- this.handled = false;
2293
- this.#gamepad.update();
2294
- this.#pointer.update();
2295
- this.#prevBits = this.#bits;
2296
- this.#bits = this.#gamepad.bits | this.#keyboard.bits | (this.#pointer.primary?.bits ?? 0);
2297
- this.invalid = this.#bits !== this.#prevBits || this.#pointer.invalid || !!this.#wheel.deltaClient;
2298
- this.gestured ||= !!this.#bits;
2299
- if (millis > this.comboMaxIntervalMillis && this.#bits !== this.#prevBits || this.#heldMillis + millis > this.comboMaxIntervalMillis && !this.#bits)
2300
- this.#combo.length = 0;
2301
- if (this.#bits === this.#prevBits)
2302
- this.#heldMillis = this.#heldMillis + millis;
2303
- else this.#heldMillis = millis;
2304
- if (this.#bits && this.#bits !== this.#prevBits) {
2305
- if (this.#prevBits) this.#combo.length = 0;
2306
- this.#combo.push(this.#bits);
2307
- }
2308
- if (this.#pointer.primary) {
2309
- const pinchClient = this.#pointer.pinchClient;
2310
- const dragOn = this.#pointer.primary.drag && !Object.values(this.#pointer.secondary).length;
2311
- const secondary = [];
2312
- for (const pt of Object.values(this.#pointer.secondary)) {
2313
- secondary.push({
2314
- type: pt.type,
2315
- click: pt.clickClient ? {
2316
- client: pt.clickClient,
2317
- local: this.#cam.clientToXYLocal(pt.clickClient),
2318
- ...this.#cam.clientToXY(pt.clickClient)
2319
- } : void 0,
2320
- ...this.#cam.clientToXY(pt.xyClient),
2321
- client: pt.xyClient,
2322
- local: this.#cam.clientToXYLocal(pt.xyClient)
2323
- });
2324
- }
2325
- const centerClient = this.#pointer.centerClient;
2326
- const center = {
2327
- client: centerClient,
2328
- local: this.#cam.clientToXYLocal(centerClient),
2329
- ...this.#cam.clientToXY(centerClient)
2330
- };
2331
- this.#pointerState = {
2332
- center,
2333
- click: this.#pointer.primary.clickClient ? {
2334
- client: this.#pointer.primary.clickClient,
2335
- local: this.#cam.clientToXYLocal(
2336
- this.#pointer.primary.clickClient
2337
- ),
2338
- ...this.#cam.clientToXY(this.#pointer.primary.clickClient)
2339
- } : void 0,
2340
- drag: {
2341
- on: dragOn,
2342
- start: !this.#pointerState?.drag.on && dragOn,
2343
- end: !!this.#pointerState?.drag.on && !dragOn
2344
- },
2345
- invalid: this.#pointer.invalid,
2346
- pinch: pinchClient ? { client: pinchClient, xy: this.#cam.clientToXY(pinchClient) } : void 0,
2347
- secondary,
2348
- type: this.#pointer.primary.type,
2349
- ...this.#cam.clientToXY(this.#pointer.primary.xyClient),
2350
- client: this.#pointer.primary.xyClient,
2351
- local: this.#cam.clientToXYLocal(this.#pointer.primary.xyClient)
2352
- };
2353
- } else this.#pointerState = void 0;
2354
- this.#wheelState = this.#wheel.deltaClient ? {
2355
- delta: {
2356
- client: this.#wheel.deltaClient,
2357
- xy: this.#cam.clientToXY(this.#wheel.deltaClient)
2358
- }
2359
- } : void 0;
2360
- this.#keyboard.postupdate();
2361
- this.#pointer.postupdate();
2362
- this.#wheel.postupdate();
2363
- }
2364
- [Symbol.dispose]() {
2365
- this.register("remove");
2366
- }
2367
- /** doesn't consider handled. */
2368
- get wheel() {
2369
- return this.#wheelState;
2370
- }
2371
- /** get bits for buttons. */
2372
- #mapBits(btns) {
2373
- let bits = 0;
2374
- for (const btn of btns) bits |= this.#bitByButton[btn] ?? 0;
2375
- return bits;
2376
- }
2377
- /** assign button to bit. */
2378
- #mapButton(btn) {
2379
- const bit = this.#bitByButton[btn] ??= 1 << Object.keys(this.#bitByButton).length;
2380
- this.#buttonByBit[bit] = btn;
2381
- return bit;
2382
- }
2383
- };
2384
-
2385
- // src/utils/debug.ts
2386
- var debug = Debug(
2387
- globalThis.location?.href
2388
- );
2389
- function Debug(url) {
2390
- if (!url) return;
2391
- const csv = [...new URL(url).searchParams].find(
2392
- ([k]) => k.toLowerCase() === "debug"
2393
- )?.[1];
2394
- if (csv == null) return;
2395
- const map = Object.fromEntries(
2396
- csv.split(",").filter(Boolean).map((kv) => kv.split("="))
2397
- // split each pair.
2398
- );
2399
- const target = {};
2400
- for (const k in map) target[k.toLowerCase()] = map[k] || "true";
2401
- const voidKeyset = {
2402
- cam: void 0,
2403
- input: void 0,
2404
- mem: void 0,
2405
- render: void 0
2406
- };
2407
- return new Proxy(target, {
2408
- get(target2, k) {
2409
- if (typeof k !== "string") return target2[k];
2410
- k = k.toLowerCase();
2411
- return !csv || "all" in map || k in voidKeyset && "void" in map ? target2[k] || "true" : target2[k];
2412
- }
2413
- });
2414
- }
2415
-
2416
- // src/mem/pool.ts
2417
- var Pool = class {
2418
- /** the next free block is always at size. */
2419
- #blocks;
2420
- #opts;
2421
- #size = 0;
2422
- #u8;
2423
- #view;
2424
- constructor(opts) {
2425
- if (opts.allocBytes <= 0) throw Error("byte allocation must be > 0");
2426
- if (opts.pageBlocks <= 0) throw Error("page blocks must be > 0");
2427
- this.#opts = { ...opts, minPages: opts.minPages ?? 1 };
2428
- const initSize = this.#opts.minPages * opts.pageBlocks;
2429
- this.#blocks = new Array(initSize);
2430
- this.#u8 = new Uint8Array();
2431
- this.#resize(initSize, "Init");
2432
- }
2433
- alloc() {
2434
- if (this.#size >= this.#currentCapacity)
2435
- this.#resize(this.#currentCapacity + this.#opts.pageBlocks, "Call");
2436
- const block = this.#blocks[this.#size];
2437
- block.i = this.#size * this.#opts.allocBytes;
2438
- this.#size++;
2439
- return block;
2440
- }
2441
- clear() {
2442
- this.#size = 0;
2443
- const minCapacity = this.#opts.minPages * this.#opts.pageBlocks;
2444
- if (this.#currentCapacity > minCapacity) this.#resize(minCapacity, "Call");
2445
- }
2446
- free(...blocks) {
2447
- for (const block of blocks) this.#freeBlock(block);
2448
- }
2449
- get size() {
2450
- return this.#size;
2451
- }
2452
- get view() {
2453
- return this.#view;
2454
- }
2455
- toDebugString() {
2456
- let str = "";
2457
- for (let i = 0; i < this.#u8.buffer.byteLength; i++) {
2458
- if (i && !(i % this.#opts.allocBytes)) str += " ";
2459
- str += this.#u8[i].toString(16).padStart(2, "0");
2460
- }
2461
- return str;
2462
- }
2463
- get #currentCapacity() {
2464
- return this.#u8.buffer.byteLength / this.#opts.allocBytes;
2465
- }
2466
- #freeBlock(block) {
2467
- if (!this.#size) throw Error("pool underflow");
2468
- this.#size--;
2469
- const start = this.#size * this.#opts.allocBytes;
2470
- this.#u8.copyWithin(block.i, start, start + this.#opts.allocBytes);
2471
- this.#blocks[this.#size].i = block.i;
2472
- [this.#blocks[block.i], this.#blocks[this.#size]] = [
2473
- this.#blocks[this.#size],
2474
- this.#blocks[block.i]
2475
- ];
2476
- const free = Math.floor(
2477
- (this.#currentCapacity - this.#size) / this.#opts.pageBlocks
2478
- );
2479
- if (free && this.#currentCapacity / this.#opts.pageBlocks - free >= this.#opts.minPages)
2480
- this.#resize(this.#currentCapacity - free * this.#opts.pageBlocks, "Call");
2481
- }
2482
- #resize(capacity, origin) {
2483
- if (origin === "Call" && debug?.mem)
2484
- console.debug(
2485
- `[mem] ${capacity < this.#currentCapacity ? "shrinking" : "growing"} pool to ${capacity}`
2486
- );
2487
- this.#blocks.length = capacity;
2488
- for (let i = this.#currentCapacity; i < capacity; i++)
2489
- this.#blocks[i] = this.#opts.alloc(this);
2490
- const buffer = new ArrayBuffer(capacity * this.#opts.allocBytes);
2491
- const u8 = new Uint8Array(buffer);
2492
- u8.set(this.#u8.subarray(0, capacity * this.#opts.allocBytes));
2493
- this.#u8 = u8;
2494
- this.#view = new DataView(buffer);
2495
- }
2496
- };
2497
-
2498
- // src/utils/color-util.ts
2499
- function rgbaHex(rgba) {
2500
- return `#${rgba.toString(16).padStart(8, "0")}`;
2501
- }
2502
-
2503
- // src/utils/dom-util.ts
2504
- function initMetaViewport() {
2505
- if (document.querySelector('meta[name="viewport"]')) return;
2506
- const meta = document.createElement("meta");
2507
- meta.name = "viewport";
2508
- meta.content = "width=device-width, maximum-scale=1, minimum-scale=1, user-scalable=no";
2509
- document.head.appendChild(meta);
2510
- }
2511
- function initBody(canvas, rgba) {
2512
- if (canvas.parentNode !== document.body) return;
2513
- document.body.style.margin = "0";
2514
- document.body.style.width = "100dvw";
2515
- document.body.style.height = "100dvh";
2516
- document.body.style.overflow = "hidden";
2517
- document.body.style.background = rgbaHex(rgba);
2518
- }
2519
-
2520
- // src/utils/canvas-util.ts
2521
- function initCanvas(canvas, mode) {
2522
- canvas ??= document.createElement("canvas");
2523
- canvas.width = 0;
2524
- canvas.style.cursor = "none";
2525
- canvas.style.display = "block";
2526
- canvas.style.outline = "none";
2527
- canvas.style.cursor = "none";
2528
- if (mode === "Int") canvas.style.imageRendering = "pixelated";
2529
- canvas.style.touchAction = "none";
2530
- canvas.tabIndex = 0;
2531
- canvas.focus();
2532
- if (!canvas.parentNode) document.body.append(canvas);
2533
- return canvas;
2534
- }
2535
-
2536
- // src/utils/fetch-util.ts
2537
- async function loadImage(img) {
2538
- const promise = new Promise((fulfil, reject) => {
2539
- img.onload = () => fulfil(img);
2540
- img.onerror = () => reject(Error(`image load error for ${img.src}`));
2541
- });
2542
- return img.complete ? img : await promise;
2543
- }
2544
-
2545
- // src/graphics/gl.ts
2546
- function Shader(gl, vertGLSL, fragGLSL, textures) {
2547
- const program = loadProgram(gl, vertGLSL, fragGLSL);
2548
- gl.useProgram(program);
2549
- return {
2550
- buffer: gl.createBuffer(),
2551
- program,
2552
- textures,
2553
- uniform: GLUniformMap(gl, program),
2554
- vao: gl.createVertexArray()
2555
- };
2556
- }
2557
- function GLUniformMap(gl, pgm) {
2558
- const len = pgm ? gl.getProgramParameter(pgm, gl.ACTIVE_UNIFORMS) : 0;
2559
- const map = debug?.render ? new Proxy(
2560
- {},
2561
- {
2562
- get(target, k) {
2563
- if (target[k] == null) throw Error(`no shader uniform "${k}"`);
2564
- return target[k];
2565
- }
2566
- }
2567
- ) : {};
2568
- for (let i = 0; i < len; ++i) {
2569
- const uniform = gl.getActiveUniform(pgm, i);
2570
- if (!uniform) throw Error(`no shader uniform at index ${i}`);
2571
- const location = gl.getUniformLocation(pgm, uniform.name);
2572
- if (!location) throw Error(`no shader uniform "${uniform.name}"`);
2573
- const name = uniform.name.replace("[0]", "");
2574
- map[name] = location;
2575
- }
2576
- return map;
2577
- }
2578
- function loadProgram(gl, vertGLSL, fragGLSL) {
2579
- const pgm = gl.createProgram();
2580
- if (!pgm) return null;
2581
- const vert = compileShader(gl, "VERTEX_SHADER", vertGLSL);
2582
- const frag = compileShader(gl, "FRAGMENT_SHADER", fragGLSL);
2583
- if (!vert || !frag) return null;
2584
- gl.attachShader(pgm, vert);
2585
- gl.attachShader(pgm, frag);
2586
- gl.linkProgram(pgm);
2587
- if (debug?.render && !gl.getProgramParameter(pgm, gl.LINK_STATUS)) {
2588
- const log = gl.getProgramInfoLog(pgm)?.slice(0, -1);
2589
- throw Error(`shader link failure; ${log}`);
2590
- }
2591
- gl.detachShader(pgm, frag);
2592
- gl.detachShader(pgm, vert);
2593
- gl.deleteShader(frag);
2594
- gl.deleteShader(vert);
2595
- return pgm;
2596
- }
2597
- function compileShader(gl, type, glsl) {
2598
- const shader = gl.createShader(gl[type]);
2599
- if (!shader) return shader;
2600
- gl.shaderSource(shader, glsl.trim());
2601
- gl.compileShader(shader);
2602
- if (debug?.render && !gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
2603
- const log = gl.getShaderInfoLog(shader)?.slice(0, -1);
2604
- throw Error(`shader compile failure; ${log}`);
2605
- }
2606
- return shader;
2607
- }
2608
-
2609
- // src/graphics/sprite-frag.glsl.ts
2610
- var spriteFragGLSL = `#version 300 es
2611
- #pragma debug(${debug?.render ? "on" : "off"})
2612
- #pragma optimize(${debug?.render ? "off" : "on"})
1
+ var o={published:"20251021",version:"0.1.0-7"};var _=o;var Q={id:"mem-prop-5x6",name:"mem 5x6",cellWidth:5,cellHeight:6,leading:1,lineHeight:7,baseline:1,kerning:{" 0":0," 1":0," 2":0," 3":0," 4":0," 5":0," 6":0," 7":0," 8":0," 9":0,"##":-1,"#_":0,"',":0,"'.":0,"'/":0,"'J":0,"'S":0,"'_":0,"'j":0,"'s":0,"(+":0,"(-":0,"(<":0,"(f":0,"({":0,"(~":0,")_":0,"*,":0,"*.":0,"*/":0,"*S":0,"*_":0,"*j":0,"*s":0,"+)":0,"+,":0,"+.":0,"+/":0,"+>":0,"+?":0,"+I":0,"+S":0,"+T":0,"+Z":0,"+]":0,"+_":0,"+`":0,"+j":0,"+s":0,"+}":0,",'":0,",*":0,",+":0,",-":0,",<":0,",?":0,",T":0,",Y":0,",Z":0,',"':0,",\\":0,",^":0,",`":0,",f":0,",t":0,",z":0,",{":0,",~":0,"-)":0,"-,":0,"--":0,"-.":0,"-/":0,"->":0,"-?":0,"-I":0,"-S":0,"-T":0,"-Z":0,"-]":0,"-_":0,"-`":0,"-j":0,"-s":0,"-}":0,".'":0,".*":0,".+":0,".-":0,".<":0,".?":0,".T":0,".Y":0,".Z":0,'."':0,".\\":0,".^":0,".`":0,".f":0,".t":0,".z":0,".{":0,".~":0,"/,":0,"/.":0,"//":0,"/J":0,"/S":0,"/_":0,"/j":0,"/s":0,"0 ":0,"1 ":0,"1T":0,"1Y":0,"1Z":0,"1f":0,"1t":0,"1z":0,"2 ":0,"3 ":0,"4 ":0,"5 ":0,"6 ":0,"7 ":0,"8 ":0,"9 ":0,":?":0,":T":0,":Z":0,":`":0,";?":0,";T":0,";Z":0,"<+":0,"<-":0,"<<":0,"<f":0,"<{":0,"<~":0,"==":0,"=_":0,">)":0,">,":0,">.":0,">/":0,">>":0,">?":0,">I":0,">S":0,">T":0,">Z":0,">]":0,">_":0,">`":0,">j":0,">s":0,">}":0,"?,":0,"?.":0,"?/":0,"?S":0,"?_":0,"?j":0,"?s":0,"@_":0,"C+":0,"C-":0,"C<":0,Cf:0,"C{":0,"C~":0,D_:0,"E+":0,"E-":0,"E<":0,Ef:0,"E{":0,"E~":0,"F&":0,"F+":0,"F,":0,"F-":0,"F.":0,"F/":0,"F:":0,"F;":0,"F<":0,FJ:0,FS:0,F_:0,Fa:0,Fe:0,Ff:0,Fg:0,Fj:0,Fq:0,Fs:0,"F{":0,"F~":0,"I+":0,"I-":0,"I<":0,If:0,"I{":0,"I~":0,"L'":0,"L*":0,"L+":0,"L-":0,L4:0,L7:0,"L<":0,"L?":0,LT:0,LY:0,LZ:0,'L"':0,"L\\":0,"L^":0,"L`":0,Lf:0,Lt:0,Lz:0,"L{":0,"L~":0,"P,":0,"P.":0,"P/":0,PS:0,P_:0,Pj:0,Ps:0,"S&":0,"S+":0,"S,":0,"S-":0,"S.":0,"S/":0,"S:":0,"S;":0,"S<":0,SJ:0,SS:0,S_:0,Sa:0,Se:0,Sf:0,Sg:0,Sj:0,Sq:0,Ss:0,"S{":0,"S~":0,"T&":0,"T+":0,"T,":0,"T-":0,"T.":0,"T/":0,"T:":0,"T;":0,"T<":0,TJ:0,TS:0,T_:0,Ta:0,Te:0,Tf:0,Tg:0,Tj:0,Tq:0,Ts:0,"T{":0,"T~":0,V_:0,"Y,":0,"Y.":0,"Y/":0,YS:0,Y_:0,Yj:0,Ys:0,"Z'":0,"Z*":0,"Z+":0,"Z-":0,Z4:0,Z7:0,"Z<":0,"Z?":0,ZT:0,ZY:0,ZZ:0,'Z"':0,"Z\\":0,"Z^":0,"Z`":0,Zf:0,Zt:0,Zz:0,"Z{":0,"Z~":0,"[+":0,"[-":0,"[<":0,"[f":0,"[{":0,"[~":0,'",':0,'".':0,'"/':0,'"J':0,'"S':0,'"_':0,'"j':0,'"s':0,"\\'":0,"\\*":0,"\\+":0,"\\-":0,"\\<":0,"\\?":0,"\\T":0,"\\Y":0,"\\Z":0,'\\"':0,"\\\\":0,"\\^":0,"\\`":0,"\\f":0,"\\t":0,"\\z":0,"\\{":0,"\\~":0,"^,":0,"^.":0,"^/":0,"^J":0,"^S":0,"^_":0,"^j":0,"^s":0,"_#":0,"_%":0,"_'":0,"_(":0,"_*":0,"_+":0,"_-":0,"_<":0,"_=":0,"_?":0,"_@":0,_T:0,_V:0,_Y:0,_Z:0,'_"':0,"_\\":0,"_^":0,__:0,"_`":0,_a:0,_e:0,_f:0,_t:0,_v:0,_z:0,"_{":0,"_~":0,"`,":0,"`.":0,"`/":0,"`J":0,"`S":0,"`_":0,"`j":0,"`s":0,"f,":0,"f.":0,"f/":0,fS:0,f_:0,fj:0,fs:0,"q#":0,q$:0,"q%":0,"q&":0,"q'":0,"q(":0,"q*":0,"q+":0,"q-":0,q0:0,q1:0,q2:0,q3:0,q4:0,q5:0,q6:0,q7:0,q8:0,q9:0,"q<":0,"q=":0,"q?":0,"q@":0,qA:0,qB:0,qC:0,qD:0,qE:0,qF:0,qG:0,qH:0,qI:0,qJ:0,qK:0,qL:0,qM:0,qN:0,qO:0,qP:0,qQ:0,qR:0,qS:0,qT:0,qU:0,qV:0,qW:0,qX:0,qY:0,qZ:0,"q[":0,'q"':0,"q\\":0,"q]":0,"q^":0,"q`":0,qa:0,qb:0,qc:0,qd:0,qe:0,qf:0,qh:0,qk:0,qm:0,qn:0,qo:0,qq:0,qr:0,qs:0,qt:0,qu:0,qv:0,qw:0,qx:0,qz:0,"q{":0,"q}":0,"q~":0,"r,":0,"r.":0,"r/":0,rS:0,r_:0,rj:-1,rs:0,"s,":0,"s.":0,"s/":0,sJ:0,sS:0,s_:0,sj:0,ss:0,"z'":0,"z*":0,"z+":0,"z-":0,z4:0,z7:0,"z<":0,"z?":0,zT:0,zY:0,zZ:0,'z"':0,"z\\":0,"z^":0,"z`":0,zf:0,zt:0,zz:0,"z{":0,"z~":0,"{+":0,"{-":0,"{<":0,"{f":0,"{{":0,"{~":0,"})":0,"},":0,"}.":0,"}/":0,"}>":0,"}?":0,"}I":0,"}S":0,"}T":0,"}Z":0,"}]":0,"}_":0,"}`":0,"}j":0,"}s":0,"}}":0,"~'":0,"~?":0,"~T":0,"~Z":0,'~"':0,"~\\":0,"~^":0,"~_":0,"~`":0,"~t":0,"~z":0},defaultKerning:1,defaultWhitespaceKerning:-1,endOfLineKerning:0,charWidth:{" ":4,"!":1,"#":5,"&":4,"'":1,"(":2,")":2,",":1,".":1,":":1,";":1,"@":5,M:5,W:5,"[":2,"\n":0,"]":2,"`":2,i:1,l:1,m:5,q:4,w:5,"|":1},defaultCharWidth:3};var C=Q;var h={Top:0,UIA:1,UIB:2,UIC:3,UID:4,UIE:5,UIF:6,UIG:7,A:8,B:9,C:10,D:11,E:12,F:13,Bottom:14,Hidden:15};function B(i,e){return Math.max(h.Top,Math.min(h.Bottom,i+e))}function x(i,e){let t={w:e.w??1,h:e.h??1};if(!i.w||!i.h||!t.w||!t.h)return!1;let r={x:i.x??0,y:i.y??0};return r.x<e.x+t.w&&r.x+i.w>e.x&&r.y<e.y+t.h&&r.y+i.h>e.y}function ee(i,e){i.w=e.w,i.h=e.h}function g(i,e){return i.w===e.w&&i.h===e.h}function te(i,e){return{x:i.x+e.x,y:i.y+e.y}}function ie(i,e){i.x=e.x,i.y=e.y}function re(i,e){return _e($(i,e))}function f(i,e){return i.x===e.x&&i.y===e.y}function _e(i){return Math.hypot(i.x,i.y)}function ne(i,e){return{x:Math.max(i.x,e.x),y:Math.max(i.y,e.y)}}function se(i,e){return{x:Math.min(i.x,e.x),y:Math.min(i.y,e.y)}}function $(i,e){return{x:i.x-e.x,y:i.y-e.y}}var b=class{#e;#t;#i=!0;constructor(e,t){this.#e={w:e.sprites.alloc(),nw:e.sprites.alloc(),n:e.sprites.alloc(),ne:e.sprites.alloc(),e:e.sprites.alloc(),se:e.sprites.alloc(),s:e.sprites.alloc(),sw:e.sprites.alloc(),origin:e.sprites.alloc()},this.#e.w.tag=t.w?.tag??t.e?.tag??t.n.tag,this.#e.n.tag=t.n.tag,this.#e.e.tag=t.e?.tag??this.#e.w.tag,this.#e.s.tag=t.s?.tag??this.#e.n.tag,this.#e.nw.tag=t.nw?.tag??t.se?.tag??t.n.tag,this.#e.ne.tag=t.ne?.tag??t.sw?.tag??t.nw?.tag??t.n.tag,this.#e.se.tag=t.se?.tag??this.#e.nw.tag,this.#e.sw.tag=t.sw?.tag??this.#e.ne.tag,this.#e.origin.tag=t.origin.tag,this.#e.w.z=this.#e.nw.z=this.#e.n.z=this.#e.ne.z=this.#e.e.z=this.#e.se.z=this.#e.s.z=this.#e.sw.z=this.#e.origin.z=t.z??0,this.#e.w.stretch=t.w?.stretch??t.e?.stretch??!1,this.#e.n.stretch=t.n.stretch??t.s?.stretch??!1,this.#e.e.stretch=t.e?.stretch??this.#e.w.stretch,this.#e.s.stretch=t.s?.stretch??this.#e.n.stretch,this.#e.nw.stretch=t.nw?.stretch??t.se?.stretch??!1,this.#e.ne.stretch=t.ne?.stretch??t.sw?.stretch??!1,this.#e.se.stretch=t.se?.stretch??this.#e.nw.stretch,this.#e.sw.stretch=t.sw?.stretch??this.#e.ne.stretch,this.#e.origin.stretch=t.origin.stretch??!1,this.#e.w.flipX=t.w?.flip?.x??!t.e?.flip?.x,this.#e.w.flipY=t.w?.flip?.y??!!t.e?.flip?.y,this.#e.n.flipX=t.n.flip?.x??!!t.s?.flip?.x,this.#e.n.flipY=t.n.flip?.y??!t.s?.flip?.y,this.#e.e.flipX=t.e?.flip?.x??!this.#e.w.flipX,this.#e.e.flipY=t.e?.flip?.y??this.#e.w.flipY,this.#e.s.flipX=t.s?.flip?.x??this.#e.n.flipX,this.#e.s.flipY=t.s?.flip?.y??!this.#e.n.flipY,this.#e.origin.flipX=!!t.origin.flip?.x,this.#e.origin.flipY=!!t.origin.flip?.y,this.#e.n.h=t.border?.n??t.border?.s??this.#e.n.h,this.#e.w.w=t.border?.w??t.border?.e??this.#e.n.h,this.#e.e.w=t.border?.e??this.#e.w.w,this.#e.s.h=t.border?.s??this.#e.n.h,this.#e.nw.w=this.#e.w.w,this.#e.nw.h=this.#e.n.h,this.#e.ne.w=this.#e.e.w,this.#e.ne.h=this.#e.n.h,this.#e.se.w=this.#e.e.w,this.#e.se.h=this.#e.s.h,this.#e.sw.w=this.#e.w.w,this.#e.sw.h=this.#e.s.h,this.#t={w:t.margin?.w??0,h:t.margin?.h??0};let r=t.wh?.w==null?this.#e.w.w+this.#e.n.w+this.#e.e.w:t.wh.w;this.#e.n.w=r-1,this.wh={w:r,h:t.wh?.h==null?this.#e.n.h+this.#e.e.h+this.#e.s.h:t.wh.h},this.#e.nw.x=(t.x??0)-1,this.xy={x:t.x??0,y:t.y??0}}free(e){e.sprites.free(this.#e.w,this.#e.nw,this.#e.n,this.#e.ne,this.#e.e,this.#e.se,this.#e.s,this.#e.sw,this.#e.origin)}update(){if(this.#i)return this.#i=!1,!0}get wh(){return{w:this.#e.w.w+this.#e.n.w+this.#e.e.w+this.#t.w,h:this.#e.n.h+this.#e.w.h+this.#e.s.h+this.#t.h}}set wh(e){g(e,this.wh)||(this.#e.w.h=e.h-this.#e.n.h-this.#e.s.h-this.#t.h,this.#e.n.w=e.w-this.#e.w.w-this.#e.e.w-this.#t.w,this.#e.s.w=this.#e.n.w,this.#e.e.h=this.#e.w.h,this.#e.origin.w=this.#e.n.w,this.#e.origin.h=this.#e.e.h,this.#r(),this.#i=!0)}get xy(){return{x:this.#e.nw.x-this.#t.w/2,y:this.#e.nw.y-this.#t.h/2}}set xy(e){f(e,this.xy)||(this.#e.nw.x=e.x+this.#t.w/2,this.#e.nw.y=e.y+this.#t.h/2,this.#e.w.x=this.#e.nw.x,this.#e.w.y=this.#e.nw.y+this.#e.nw.h,this.#e.n.x=this.#e.nw.x+this.#e.nw.w,this.#e.n.y=this.#e.nw.y,this.#e.origin.x=this.#e.n.x,this.#e.origin.y=this.#e.nw.y+this.#e.ne.h,this.#r(),this.#i=!0)}#r(){this.#e.ne.x=this.#e.n.x+this.#e.n.w,this.#e.ne.y=this.#e.nw.y,this.#e.e.x=this.#e.ne.x,this.#e.e.y=this.#e.nw.y+this.#e.ne.h,this.#e.se.x=this.#e.e.x,this.#e.se.y=this.#e.e.y+this.#e.e.h,this.#e.s.x=this.#e.n.x,this.#e.s.y=this.#e.se.y,this.#e.sw.x=this.#e.nw.x,this.#e.sw.y=this.#e.se.y}};function oe(i,e){let t=e.codePointAt(0);return(t==null||t>255)&&(t=63),`${i.id}--${t.toString(16).padStart(2,"0")}`}function ae(i,e,t){return t==null?i.endOfLineKerning:i.kerning[e+t]!=null?i.kerning[e+t]:/^\s?$/.test(e)||/^\s?$/.test(t)?i.defaultWhitespaceKerning:i.defaultKerning}function j(i,e){return i.charWidth[e]??i.defaultCharWidth}function le(i){let e=[],t=i.scale??1,r=i.start??{x:0,y:0},n=i.maxW??1/0,s={x:r.x,y:r.y},a=0;for(;e.length<i.str.length;){let d=e.length,m=i.str[d],u;m===`
2
+ `?u=Be(i.font,s,r.x,t):/^\s*$/.test(m)?u=Ye(i.font,s,n,de(i.font,m,i.str[d+1],t),r.x,t):(u=he(i.font,s,n,i.str,d,r.x,t),s.x>0&&u.cursor.y===w(i.font,r.x,s.y,t).y&&n-s.x+u.cursor.x<=n&&(s=w(i.font,r.x,s.y,t),u=he(i.font,s,n,i.str,d,r.x,t))),e.push(...u.chars),s.x=u.cursor.x,s.y=u.cursor.y,a=Math.max(a,u.cursor.x-r.x)}return{chars:e,cursor:s,wh:{w:a,h:w(i.font,r.x,s.y,t).y-r.y}}}function he(i,e,t,r,n,s,a){let d=[],{x:m,y:u}=e;for(;;n++){let p=r[n];if(!p||/^\s*$/.test(p))break;let S=de(i,p,r[n+1],a);m>s&&m+S>s+t&&({x:m,y:u}=w(i,s,u,a)),d.push({x:m,y:u,w:j(i,p),h:i.cellHeight}),m+=S}return{chars:d,cursor:{x:m,y:u}}}function w(i,e,t,r){return{x:e,y:t+i.lineHeight*r}}function Be(i,e,t,r){return{chars:[void 0],cursor:w(i,t,e.y,r)}}function Ye(i,e,t,r,n,s){let a=e.x>0&&e.x+r>=t?w(i,n,e.y,s):{x:e.x+r,y:e.y};return{chars:[void 0],cursor:a}}function de(i,e,t,r){return r*(j(i,e)+ae(i,e,t))}var y=class{#e=1/0;#t="Outdated";#i=h.UIA;#r=1;#s=[];#n="";#o={w:0,h:0};#a={x:0,y:0};free(e){e.sprites.free(...this.#s)}layout(e){if(this.#t!=="Outdated")return!1;let t=0,r=le({font:C,maxW:this.#e,scale:this.#r,start:this.#a,str:this.#n});this.#o={w:r.wh.w,h:r.wh.h};for(let[n,s]of r.chars.entries()){if(s==null)continue;let a=this.#s[t]??=e.sprites.alloc();a.x=s.x,a.y=s.y,a.tag=oe(C,this.#n[n]),a.stretch=!0,a.w*=this.#r,a.h*=this.#r,a.z=this.#i,t++}for(;this.#s.length>t;)e.sprites.free(this.#s.pop());return this.#t="Updated",!0}get maxW(){return this.#e}set maxW(e){e!==this.#e&&(this.#e=e,this.#t="Outdated")}get scale(){return this.#r}set scale(e){e!==this.#r&&(this.#r=e,this.#t="Outdated")}get text(){return this.#n}set text(e){e!==this.#n&&(this.#n=e,this.#t="Outdated")}update(e){if(this.#t!=="Rendered")return this.#t==="Outdated"&&this.layout(e),this.#t="Rendered",!0}get scaledLeading(){return C.leading*this.#r}get wh(){return this.#o}get xy(){return this.#a}set xy(e){f(e,this.#a)||(this.#a.x=e.x,this.#a.y=e.y,this.#t="Outdated")}get z(){return this.#i}set z(e){e!==this.#i&&(this.#i=e,this.#t="Outdated")}};var Y=class{#e;#t=!0;#i;#r;#s=!1;#n=!1;#o=new y;#a={x:0,y:0};constructor(e,t){let r=t.button.z??h.UID;this.#e=new b(e,{...t.button,x:t.x,y:t.y,z:r,wh:{w:t.w,h:t.h}}),this.#i={sprite:e.sprites.alloc(),z:t.pressed.z??B(r,2)},this.#r={sprite:e.sprites.alloc(),z:t.selected.z??B(this.#i.z,-1)},this.#i.sprite.tag=t.pressed.tag,this.#i.sprite.x=t.x??0,this.#i.sprite.y=t.y??0,this.#i.sprite.w=t.w??this.#e.wh.w,this.#i.sprite.h=t.h??this.#e.wh.h,this.#i.sprite.z=h.Hidden,this.#r.sprite.tag=t.selected.tag,this.#r.sprite.x=t.x??0,this.#r.sprite.y=t.y??0,this.#r.sprite.w=t.w??this.#e.wh.w,this.#r.sprite.h=t.h??this.#e.wh.h,this.#r.sprite.z=h.Hidden,this.#o.text=t.text?.text??"",this.#o.scale=t.text?.scale??1,this.#o.layout(e),this.#l(e),this.#o.maxW=t.w??this.#e.wh.w,this.#o.z=t.text?.z??B(r,-1),this.#n=t.toggle??!1}get selected(){return this.#r.z!==h.Hidden}free(e){this.#e.free(e),this.#o.free(e),e.sprites.free(this.#r.sprite,this.#i.sprite)}get on(){return this.#i.sprite.z!==h.Hidden}set on(e){this.#i.sprite.z=e?this.#i.z:h.Hidden}get onStart(){return this.on&&this.#s}set text(e){this.#o.text=e}update(e){let t=this.#t;this.#e.update()&&(t=!0),this.#o.update(e)&&(t=!0);let r=!e.input.handled&&!!e.zoo.cursor?.hits(e,this.#r.sprite,"UI"),s=r&&e.input.isOnStart("Click")||e.zoo.cursor?.keyboard&&e.input.isOnStart("A")?this.#n?!this.on:!0:this.#n?this.on:e.input.isOn("Click")||!!e.zoo.cursor?.keyboard&&e.input.isOn("A");return this.#s=this.on!==s,this.#s&&(this.on=s,t=!0),r&&(e.input.point?.click||e.input.point?.type==="Mouse")?(t||=this.#r.sprite.z!==this.#r.z,this.#r.sprite.z=this.#r.z):(t||=this.#r.sprite.z!==h.Hidden,this.#r.sprite.z=h.Hidden),e.input.handled||=r,this.#t=!1,t}setXY(e,t){f(t,this.#a)||(this.#a.x=t.x,this.#a.y=t.y,this.#e.xy=t,this.#l(e),this.#i.sprite.xy=t,this.#r.sprite.xy=t,this.#t=!0)}#l(e){this.#o.layout(e),this.#o.xy={x:this.#e.xy.x+this.#e.wh.w/2-this.#o.wh.w/2,y:this.#e.xy.y+this.#e.wh.h/2-(this.#o.wh.h-this.#o.scaledLeading)/2}}};var v=class{keyboard=!1;#e;#t;#i;constructor(e,t,r){this.#i=t,this.#t=r??this.#i,this.#e=e.sprites.alloc(),this.#e.tag=t,this.#e.z=h.Hidden}free(e){e.sprites.free(this.#e)}hitbox(e,t){let r=t==="Level",n=this.#e.hitbox;if(!n)throw Error("cursor has no hitbox");return{x:(r?e.cam.x:0)+n.x,y:(r?e.cam.y:0)+n.y,w:n.w,h:n.h}}hits(e,t,r){return this.visible&&x(this.hitbox(e,r),t)}update(e){if(e.input.point?.invalid)return this.#e.tag=e.input.point.click?this.#t:this.#i,this.#e.xy=e.input.point.local,this.#e.z=e.input.point?.type==="Mouse"?h.Top:h.Hidden,!0;if(this.keyboard&&e.input.isAnyOn("L","R","U","D"))return e.input.isOn("L")&&(this.#e.x-=1),e.input.isOn("R")&&(this.#e.x+=1),e.input.isOn("U")&&(this.#e.y-=1),e.input.isOn("D")&&(this.#e.y+=1),this.#e.z=h.Top,!0}get visible(){return this.#e.z!==h.Hidden}};var A=class{#e;#t=!0;#i={w:0,h:0};#r={x:0,y:0};#s;#n;constructor(e,t,r){this.#n=e.sprites.alloc(),this.#n.tag=t,this.#s=r}get fill(){return this.#e}set fill(e){this.#e!==e&&(this.#e=e,this.#t=!0)}free(e){e.sprites.free(this.#n)}get h(){return this.#n.h}set h(e){this.#n.h!==e&&(this.#n.h=e,this.#t=!0)}get margin(){return this.#i}set margin(e){g(e,this.#i)||(ee(this.#i,e),this.#t=!0)}get modulo(){return this.#r}set modulo(e){f(e,this.#r)||(ie(this.#r,e),this.#t=!0)}get pivot(){return this.#s}set pivot(e){this.#s!==e&&(this.#s=e,this.#t=!0)}update(e){if(!this.#t&&!e.cam.invalid)return;let t=e.cam.follow({w:this.#n.w,h:this.#n.h},this.#n.z,this.#s,{fill:this.#e,modulo:this.#r,margin:this.#i});return this.#n.x=t.x,this.#n.y=t.y,this.#t=!1,!0}get w(){return this.#n.w}set w(e){this.#n.w!==e&&(this.#n.w=e,this.#t=!0)}get z(){return this.#n.z}set z(e){this.#n.z=e}};var l=Ae(globalThis.location?.href);function Ae(i){if(!i)return;let e=[...new URL(i).searchParams].find(([s])=>s.toLowerCase()==="debug")?.[1];if(e==null)return;let t=Object.fromEntries(e.split(",").filter(Boolean).map(s=>s.split("="))),r={};for(let s in t)r[s.toLowerCase()]=t[s]||"true";let n={cam:void 0,input:void 0,mem:void 0,render:void 0};return new Proxy(r,{get(s,a){if(typeof a!="string"||(a=a.toLowerCase(),s[a]))return s[a];if(!e||"all"in t||a in n&&"void"in t)return"true"}})}var M=class{#e;#t=new Set;#i=!1;add(...e){for(let t of e)this.#t.add(t),t instanceof v&&(this.#e=t)}clear(){this.#e=void 0,this.#t.clear()}get cursor(){return this.#e}get invalid(){return this.#i}remove(...e){for(let t of e)this.#t.delete(t),t===this.#e&&(this.#e=void 0)}update(e){this.#i=!1;for(let t of this.#t)t.update?.(e)&&(!this.#i&&l?.invalid&&console.debug("ent update invalid",t),this.#i=!0)}};function me(i){return{anim:i.anim,celXYWH:Me(i),tags:Object.keys(i.anim)}}function Me(i){let e=[],t=0;for(let r of Object.values(i.anim))e.push(...Xe(r,i.celXY,t)),t+=r.cels*2;return e}function Xe(i,e,t){let r=[];for(let n=0;n<16;n++){let s=t+2*(n%i.cels);r.push(e[s],e[s+1],i.w,i.h)}return r}var X=class{#e=0;#t=1;#i=!0;#r=1;#s={w:1/0,h:1/0};#n="Int";#o=1;#a=1;#l={w:1,h:1};#h=0;#u=0;#d=0;center(e){this.x=Math.floor(e.x-this.w/2),this.y=Math.floor(e.y-this.h/2)}clientToXY(e){let t=this.clientToXYLocal(e);return{x:this.#h+t.x,y:this.#u+t.y}}clientToXYLocal(e){return{x:e.x/this.#l.w*this.#a,y:e.y/this.#l.h*this.#t}}follow(e,t,r,n){let s=n?.margin?.w??0,a=t>h.UIG?Math.trunc(this.x):0;switch(r){case"SW":case"W":case"NW":a+=s;break;case"SE":case"E":case"NE":a+=this.w-(e.w+s);break;case"N":case"S":case"Origin":a+=Math.trunc(this.w/2)-Math.trunc(e.w/2);break}a-=a%((n?.modulo?.x??a)||1);let d=n?.margin?.h??0,m=t>h.UIG?Math.trunc(this.y):0;switch(r){case"N":case"NE":case"NW":m+=d;break;case"SE":case"S":case"SW":m+=this.h-(e.h+d);break;case"E":case"W":case"Origin":m+=Math.trunc(this.h/2)-Math.trunc(e.h/2);break}m-=m%((n?.modulo?.y??m)||1);let u=n?.fill==="X"||n?.fill==="XY"?this.w-2*s:e.w,p=n?.fill==="Y"||n?.fill==="XY"?this.h-2*d:e.h;return{x:a,y:m,w:u,h:p}}get h(){return this.#t}isVisible(e){return x(this,e)}get invalid(){return this.#i}get minScale(){return this.#r}set minScale(e){this.#o!==e&&(this.#o=e,this.#m())}get minWH(){return this.#s}set minWH(e){this.#s.w===e.w&&this.#s.h===e.h||(this.#s.w=e.w,this.#s.h=e.h,this.#m())}get mode(){return this.#n}set mode(e){this.#n!==e&&(this.#n=e,this.#m())}get portrait(){return this.h>this.w}postupdate(){this.#i=!1}get scale(){return this.#o}toString(){return`Cam{(${this.x} ${this.y}) ${this.w}\xD7${this.h}}`}update(e){if(!e.parentElement)throw Error("canvas has no parent");let{clientWidth:t,clientHeight:r}=e.parentElement;this.#i||=this.#l.w!==t||this.#l.h!==r||this.#e!==devicePixelRatio,this.#i&&(this.#e=devicePixelRatio,this.#l.w=t,this.#l.h=r,this.#m(),e.width=this.#a,e.height=this.#t,e.style.width=`${this.#a*this.#o/devicePixelRatio}px`,e.style.height=`${this.#t*this.#o/devicePixelRatio}px`)}get w(){return this.#a}get whClient(){return this.#l}get x(){return this.#h}set x(e){this.#i||=this.x!==e,this.#h=e}get y(){return this.#u}set y(e){this.#i||=this.y!==e,this.#u=e}get zoomOut(){return this.#d}set zoomOut(e){e=Math.max(0,e),this.#d!==e&&(this.#d=e,this.#m())}#m(){!this.#i&&l?.invalid&&console.debug("cam invalid"),this.#i=!0;let e={w:this.#l.w*devicePixelRatio,h:this.#l.h*devicePixelRatio},t=Math.max(this.#r,Math.min(e.w/this.#s.w,e.h/this.#s.h)-(this.#n==="Int"?Math.trunc(this.#d):this.#d));this.#o=this.#n==="Int"?Math.trunc(t):t,this.#a=Math.ceil(e.w/this.#o),this.#t=Math.ceil(e.h/this.#o)}};function ue(i,e){return(i%e+e)%e}var c=12,Zt=1/64,K={w:4095,h:4095},Z=class{i;#e;constructor(e,t){this.#e=e,this.i=t}above(e){return(this.z===e.z?(e.zend?e.y+e.h:e.y)-(this.zend?this.y+this.h:this.y):this.z-e.z)<0}get cel(){return this.#e.view.getUint8(this.i+10)&31}set cel(e){let t=this.#e.view.getUint8(this.i+10);this.#e.view.setUint8(this.i+10,t&-32|e&31)}clips(e){return x(this,e)}get flipX(){return!!(this.#e.view.getUint8(this.i+6)&64)}set flipX(e){let t=this.#e.view.getUint8(this.i+6);this.#e.view.setUint8(this.i+6,t&-65|-e&64)}get flipY(){return!!(this.#e.view.getUint8(this.i+6)&32)}set flipY(e){let t=this.#e.view.getUint8(this.i+6);this.#e.view.setUint8(this.i+6,t&-33|-e&32)}get h(){return this.#e.view.getUint16(this.i+8,!0)>>>4}set h(e){let t=this.#e.view.getUint16(this.i+8,!0);this.#e.view.setUint16(this.i+8,t&-65521|(e&4095)<<4,!0)}get id(){return this.#e.view.getUint16(this.i+10,!0)>>>5&2047}set id(e){let t=this.#e.view.getUint16(this.i+10,!0);this.#e.view.setUint16(this.i+10,t&-65505|(e&2047)<<5,!0)}get stretch(){return!!(this.#e.view.getUint8(this.i+6)&128)}set stretch(e){let t=this.#e.view.getUint8(this.i+6);this.#e.view.setUint8(this.i+6,t&-129|-e&128)}get w(){return this.#e.view.getUint16(this.i+7,!0)&4095}set w(e){let t=this.#e.view.getUint16(this.i+7,!0);this.#e.view.setUint16(this.i+7,t&-4096|e&4095,!0)}get x(){return(this.#e.view.getUint32(this.i+0,!0)<<8>>8)/64}set x(e){let t=this.#e.view.getUint32(this.i+0,!0);this.#e.view.setUint32(this.i+0,t&-16777216|e*64&16777215,!0)}get xy(){return{x:this.x,y:this.y}}set xy(e){this.x=e.x,this.y=e.y}get y(){return(this.#e.view.getUint32(this.i+3,!0)<<8>>8)/64}set y(e){let t=this.#e.view.getUint32(this.i+3,!0);this.#e.view.setUint32(this.i+3,t&-16777216|e*64&16777215,!0)}get z(){return this.#e.view.getUint8(this.i+6)&15}set z(e){let t=this.#e.view.getUint8(this.i+6);this.#e.view.setUint8(this.i+6,t&-16|e&15)}get zend(){return!!(this.#e.view.getUint8(this.i+6)&16)}set zend(e){let t=this.#e.view.getUint8(this.i+6);this.#e.view.setUint8(this.i+6,t&-17|-e&16)}},T=class i extends Z{#e;#t;#i;#r;constructor(e,t,r,n){super(e,t),this.#e=r,this.#r=n}get anim(){return this.#e.anim[this.tag]}get flipX(){return super.flipX}set flipX(e){this.flipX!==e&&(super.flipX=e,this.#t=void 0,this.#i=void 0)}get flipY(){return super.flipY}set flipY(e){this.flipY!==e&&(super.flipY=e,this.#t=void 0,this.#i=void 0)}get h(){return super.h}set h(e){this.h!==e&&(super.h=e,this.#t=void 0,this.#i=void 0)}get hitbox(){if(this.#t)return this.#t;let{hitbox:e}=this.anim;if(e)return this.#t??={x:this.x+(this.flipX?this.w-e.w-e.x:e.x),y:this.y+(this.flipY?this.h-e.h-e.y:e.y),w:e.w,h:e.h}}hits(e){let t=this.hitbox;if(!t)return!1;let r=e instanceof i?e.hurtbox:e;return!!r&&x(t,r)}get hurtbox(){if(this.#i)return this.#i;let{hurtbox:e}=this.anim;if(e)return this.#i??={x:this.x+(this.flipX?this.w-e.w-e.x:e.x),y:this.y+(this.flipY?this.h-e.h-e.y:e.y),w:e.w,h:e.h}}get id(){return super.id}set id(e){this.id!==e&&(super.id=e,this.#t=void 0,this.#i=void 0)}get looped(){return ue(this.#s-this.cel,32)>=this.anim.cels}reset(){this.cel=this.#s}get tag(){return this.#e.tags[this.id]}set tag(e){let t=this.#e.anim[e];this.w=t.w,this.h=t.h,this.id=t.id,this.reset()}toString(){return`Sprite{${this.tag} (${this.x} ${this.y} ${this.z}) ${this.w}\xD7${this.h}}`}get w(){return super.w}set w(e){this.w!==e&&(super.w=e,this.#t=void 0,this.#i=void 0)}get x(){return super.x}set x(e){this.x!==e&&(super.x=e,this.#t=void 0,this.#i=void 0)}get y(){return super.y}set y(e){this.y!==e&&(super.y=e,this.#t=void 0,this.#i=void 0)}get#s(){return this.#r.age/62.5%(this.anim.cels*2)}};var P=class{enable=!1;#e;constructor(e){this.#e=e}register(e){let t=this.#e[`${e}EventListener`].bind(this.#e);return t("contextmenu",this.#t),t("touchstart",this.#t,{passive:!1}),this}[Symbol.dispose](){this.register("remove")}#t=e=>{!e.isTrusted||e.metaKey||e.altKey||e.ctrlKey||this.enable||e.preventDefault()}};var z=class{bits=0;bitByAxis={};bitByButton={};onEvent=()=>{};#e;constructor(e){this.#e=e}get connected(){return isSecureContext&&navigator.getGamepads().filter(Boolean).length>0}register(e){let t=this.#e[`${e}EventListener`].bind(this.#e);return t("gamepadconnected",this.onEvent),t("gamepaddisconnected",this.onEvent),this}reset(){this.bits=0}[Symbol.dispose](){this.register("remove")}update(){if(isSecureContext)for(let e of navigator.getGamepads()){for(let[t,r]of e?.axes.entries()??[]){let n=this.bitByAxis[t];if(!n)continue;let s=r<0?n[0]:r===0?0:n[1];this.bits|=Math.abs(r)>=.5?s:0}for(let[t,r]of e?.buttons.entries()??[]){let n=this.bitByButton[t];n!=null&&(this.bits|=r.pressed?n:0)}}}};var W=class{bitByCode={};invalid=!1;onEvent=()=>{};#e={};#t;constructor(e){this.#t=e}get bits(){let e=0;for(let t in this.bitByCode)e|=this.#e[t]?this.bitByCode[t]:0;return e}postupdate(){this.invalid=!1}register(e){let t=this.#t[`${e}EventListener`].bind(this.#t);for(let r of["keydown","keyup"])t(r,this.#i);return this}reset(){this.invalid=!1,this.#e={}}[Symbol.dispose](){this.register("remove")}#i=e=>{!e.isTrusted||this.bitByCode[e.code]==null||e.type==="keydown"&&(e.metaKey||e.altKey||e.ctrlKey)||(this.invalid=!0,this.#e[e.code]=e.type==="keydown",e.preventDefault(),this.onEvent())}};var Pe={mouse:"Mouse",pen:"Pen",touch:"Touch"},ze=["pointercancel","pointerdown","pointermove","pointerup"],k=class{bitByButton={};dragMinClient=5;invalid=!1;onEvent=()=>{};primary;secondary={};#e;#t;constructor(e){this.#t=e}get boundsClient(){if(!this.primary?.bits&&!Object.keys(this.secondary).length)return;let e={x:1/0,y:1/0},t={x:-1/0,y:-1/0};for(let r of[this.primary,...Object.values(this.secondary)])r?.bits&&(e=se(e,r.xyClient),t=ne(t,r.xyClient));return{x:e.x,y:e.y,w:t.x-e.x,h:t.y-e.y}}get centerClient(){let e=this.boundsClient;return e?te(e,{x:e.w/2,y:e.h/2}):this.primary?.xyClient}get locked(){return this.#t.ownerDocument.pointerLockElement===this.#t}get pinchClient(){if(!this.#e)return;let e=this.#s;return e?$(e,this.#e):void 0}postupdate(){this.invalid=!1}register(e){let t=this.#t[`${e}EventListener`].bind(this.#t);for(let r of ze)t(r,this.#r);return this}reset(){this.invalid=!1,this.primary=void 0;for(let e in this.secondary)delete this.secondary[e];this.#e=void 0}update(){((this.primary?.bits?1:0)+Object.values(this.secondary).length<2||!this.#e)&&(this.#e=this.#s)}[Symbol.dispose](){this.register("remove")}#i(e){let t=0;for(let r=1;r<=e;r<<=1)(r&e)===r&&(t|=this.bitByButton[r]??0);return t}#r=e=>{if(!e.isTrusted)return;this.invalid=!0;let t=e.metaKey||e.altKey||e.ctrlKey?0:this.#i(e.buttons);t&&e.preventDefault();let r=this.locked;if(e.type==="pointerdown"&&!r)try{this.#t.setPointerCapture(e.pointerId)}catch{}let n=e.isPrimary?this.primary:this.secondary[e.pointerId],s;if(r){let S=1/devicePixelRatio;s={x:Math.min(Math.max(0,(n?.xyClient.x??e.offsetX)+e.movementX*S),this.#t.clientWidth),y:Math.min(Math.max(0,(n?.xyClient.y??e.offsetY)+e.movementY*S),this.#t.clientHeight)}}else s={x:e.offsetX,y:e.offsetY};let a=e.type,d=Pe[e.pointerType],m;e.type==="pointerdown"?m={x:s.x,y:s.y}:e.type==="pointermove"&&(m=n?.clickClient);let u=!!t&&(n?.drag||!!m&&re(m,s)>=this.dragMinClient),p={clickClient:m,bits:t,drag:u,ev:a,id:e.pointerId,primary:e.isPrimary,type:d,xyClient:s};e.isPrimary?this.primary=p:t?this.secondary[e.pointerId]=p:delete this.secondary[e.pointerId],this.onEvent()};get#s(){if((this.primary?.bits?1:0)+Object.values(this.secondary).length<2)return;let e=this.boundsClient;return e?{x:e.w,y:e.h}:void 0}};var H=class{deltaClient;onEvent=()=>{};#e;constructor(e){this.#e=e}postupdate(){this.deltaClient=void 0}register(e){return this.#e[`${e}EventListener`].bind(this.#e)("wheel",this.#t,{passive:!0}),this}reset(){this.deltaClient=void 0}[Symbol.dispose](){this.register("remove")}#t=e=>{!e.isTrusted||e.metaKey||e.altKey||e.ctrlKey||(this.deltaClient={x:e.deltaX,y:e.deltaY,z:e.deltaZ},this.onEvent())}};var O=class{comboMaxIntervalMillis=300;gestured=!1;handled=!1;invalid=!1;minHeldMillis=300;#e={};#t={};#i=0;#r;#s=[];#n;#o;#a=0;#l;#h;#u;#d=0;#m;#f;constructor(e,t){this.#r=e,this.#n=new P(t),this.#o=new z(globalThis),this.#l=new W(t.ownerDocument),this.#h=new k(t),this.#m=new H(t)}get anyOn(){return this.#i!==0}get combo(){let e=[];for(let t of this.#s){let r=[];for(let n=1;n<=t;n<<=1)(n&t)===n&&this.#t[n]&&r.push(this.#t[n]);r.sort(),e.push(r)}return e}get contextMenu(){return this.#n}get gamepad(){return this.#o.connected?{}:void 0}get held(){return!this.handled&&this.#a>=this.minHeldMillis}isAnyOn(...e){return!this.handled&&!!(this.#i&this.#c(e))}isAnyOnStart(...e){return this.started&&this.isAnyOn(...e)}isCombo(...e){return e.length===this.#s.length&&this.isComboEndsWith(...e)}isComboEndsWith(...e){for(let[t,r]of e.entries()){let n=this.#c(r);if(this.#s.at(-e.length+t)!==n)return!1}return!this.handled&&(this.#s.at(-1)===this.#i||!this.#i)}isComboEndsWithStart(...e){return this.isOnStart(...e.at(-1))&&this.isComboEndsWith(...e)}isComboStart(...e){return this.isOnStart(...e.at(-1))&&this.isCombo(...e)}isOff(...e){return!this.handled&&!this.isOn(...e)}isOffStart(...e){let t=this.#c(e);return(this.#d&t)===t&&this.started&&this.isOff(...e)}isOn(...e){let t=this.#c(e);return!this.handled&&(this.#i&t)===t}isOnStart(...e){return this.started&&this.isOn(...e)}get key(){return{invalid:this.#l.invalid}}mapDefault(){let e=this;return e.mapKeyboardCode("L","ArrowLeft"),e.mapKeyboardCode("R","ArrowRight"),e.mapKeyboardCode("U","ArrowUp"),e.mapKeyboardCode("D","ArrowDown"),e.mapKeyboardCode("C","KeyC"),e.mapKeyboardCode("A","KeyX"),e.mapKeyboardCode("B","KeyZ"),e.mapKeyboardCode("Menu","Enter"),e.mapKeyboardCode("Back","Escape"),e.mapGamepadAxis("L","R",0,2),e.mapGamepadAxis("U","D",1,3),e.mapGamepadButton("L",14),e.mapGamepadButton("R",15),e.mapGamepadButton("U",12),e.mapGamepadButton("D",13),e.mapGamepadButton("C",2),e.mapGamepadButton("B",0),e.mapGamepadButton("A",1),e.mapGamepadButton("Menu",9),e.mapGamepadButton("Back",8),e.mapPointerClick("Click",1),e.mapPointerClick("Click2",2),e.mapPointerClick("ClickMiddle",4),e}mapGamepadAxis(e,t,...r){for(let n of r)this.#o.bitByAxis[n]=[this.#p(e),this.#p(t)]}mapGamepadButton(e,...t){for(let r of t)this.#o.bitByButton[r]=this.#p(e)}mapKeyboardCode(e,...t){for(let r of t)this.#l.bitByCode[r]=this.#p(e)}mapPointerClick(e,...t){for(let r of t)this.#h.bitByButton[r]=this.#p(e)}get on(){let e=[];for(let t in this.#e)this.isOn(t)&&e.push(t);return e.sort()}set onEvent(e){this.#o.onEvent=e,this.#l.onEvent=e,this.#h.onEvent=e,this.#m.onEvent=e}get point(){return this.#u}get pointer(){return this.#h}register(e){return globalThis[`${e}EventListener`]("blur",this.reset),this.#n.register(e),this.#o.register(e),this.#l.register(e),this.#h.register(e),this.#m.register(e),this}reset=()=>{this.#i=0,this.#d=0,this.handled=!1,this.#a=0,this.#s.length=0,this.#o.reset(),this.#l.reset(),this.#h.reset(),this.#u=void 0,this.#m.reset(),this.#f=void 0};get started(){return!this.handled&&this.#i!==this.#d}update(e){if(this.handled=!1,this.#o.update(),this.#h.update(),this.#d=this.#i,this.#i=this.#o.bits|this.#l.bits|(this.#h.primary?.bits??0),this.invalid=this.#i!==this.#d||this.#h.invalid||!!this.#m.deltaClient,this.gestured||=!!this.#i,(e>this.comboMaxIntervalMillis&&this.#i!==this.#d||this.#a+e>this.comboMaxIntervalMillis&&!this.#i)&&(this.#s.length=0),this.#i===this.#d?this.#a=this.#a+e:this.#a=e,this.#i&&this.#i!==this.#d&&(this.#d&&(this.#s.length=0),this.#s.push(this.#i)),this.#h.primary){let t=this.#h.pinchClient,r=this.#h.primary.drag&&!Object.values(this.#h.secondary).length,n=[];for(let d of Object.values(this.#h.secondary))n.push({type:d.type,click:d.clickClient?{client:d.clickClient,local:this.#r.clientToXYLocal(d.clickClient),...this.#r.clientToXY(d.clickClient)}:void 0,...this.#r.clientToXY(d.xyClient),client:d.xyClient,local:this.#r.clientToXYLocal(d.xyClient)});let s=this.#h.centerClient,a={client:s,local:this.#r.clientToXYLocal(s),...this.#r.clientToXY(s)};this.#u={center:a,click:this.#h.primary.clickClient?{client:this.#h.primary.clickClient,local:this.#r.clientToXYLocal(this.#h.primary.clickClient),...this.#r.clientToXY(this.#h.primary.clickClient)}:void 0,drag:{on:r,start:!this.#u?.drag.on&&r,end:!!this.#u?.drag.on&&!r},invalid:this.#h.invalid,pinch:t?{client:t,xy:this.#r.clientToXY(t)}:void 0,secondary:n,type:this.#h.primary.type,...this.#r.clientToXY(this.#h.primary.xyClient),client:this.#h.primary.xyClient,local:this.#r.clientToXYLocal(this.#h.primary.xyClient)}}else this.#u=void 0;this.#f=this.#m.deltaClient?{delta:{client:this.#m.deltaClient,xy:this.#r.clientToXY(this.#m.deltaClient)}}:void 0,this.#l.postupdate(),this.#h.postupdate(),this.#m.postupdate()}[Symbol.dispose](){this.register("remove")}get wheel(){return this.#f}#c(e){let t=0;for(let r of e)t|=this.#e[r]??0;return t}#p(e){let t=this.#e[e]??=1<<Object.keys(this.#e).length;return this.#t[t]=e,t}};var E=class{#e;#t;#i=0;#r;#s;constructor(e){if(e.allocBytes<=0)throw Error("byte allocation must be > 0");if(e.pageBlocks<=0)throw Error("page blocks must be > 0");this.#t={...e,minPages:e.minPages??1};let t=this.#t.minPages*e.pageBlocks;this.#e=new Array(t),this.#r=new Uint8Array,this.#a(t,"Init")}alloc(){this.#i>=this.#n&&this.#a(this.#n+this.#t.pageBlocks,"Call");let e=this.#e[this.#i];return e.i=this.#i*this.#t.allocBytes,this.#i++,e}clear(){this.#i=0;let e=this.#t.minPages*this.#t.pageBlocks;this.#n>e&&this.#a(e,"Call")}free(...e){for(let t of e)this.#o(t)}get size(){return this.#i}get view(){return this.#s}toDebugString(){let e="";for(let t=0;t<this.#r.buffer.byteLength;t++)t&&!(t%this.#t.allocBytes)&&(e+=" "),e+=this.#r[t].toString(16).padStart(2,"0");return e}get#n(){return this.#r.buffer.byteLength/this.#t.allocBytes}#o(e){if(!this.#i)throw Error("pool underflow");this.#i--;let t=this.#i*this.#t.allocBytes;this.#r.copyWithin(e.i,t,t+this.#t.allocBytes),this.#e[this.#i].i=e.i,[this.#e[e.i],this.#e[this.#i]]=[this.#e[this.#i],this.#e[e.i]];let r=Math.floor((this.#n-this.#i)/this.#t.pageBlocks);r&&this.#n/this.#t.pageBlocks-r>=this.#t.minPages&&this.#a(this.#n-r*this.#t.pageBlocks,"Call")}#a(e,t){t==="Call"&&l?.mem&&console.debug(`[mem] ${e<this.#n?"shrinking":"growing"} pool to ${e}`),this.#e.length=e;for(let s=this.#n;s<e;s++)this.#e[s]=this.#t.alloc(this);let r=new ArrayBuffer(e*this.#t.allocBytes),n=new Uint8Array(r);n.set(this.#r.subarray(0,e*this.#t.allocBytes)),this.#r=n,this.#s=new DataView(r)}};function pe(i){return`#${i.toString(16).padStart(8,"0")}`}function ce(i,e){i.parentNode===document.body&&(document.body.style.margin="0",document.body.style.width="100dvw",document.body.style.height="100dvh",document.body.style.overflow="hidden",document.body.style.background=pe(e))}function fe(){if(document.querySelector('meta[name="viewport"]'))return;let i=document.createElement("meta");i.name="viewport",i.content="width=device-width, maximum-scale=1, minimum-scale=1, user-scalable=no",document.head.appendChild(i)}function ye(i,e){return i??=document.createElement("canvas"),i.width=0,i.style.cursor="none",i.style.display="block",i.style.outline="none",i.style.cursor="none",e==="Int"&&(i.style.imageRendering="pixelated"),i.style.touchAction="none",i.tabIndex=0,i.focus(),i.parentNode||document.body.append(i),i}async function xe(i){let e=new Promise((t,r)=>{i.onload=()=>t(i),i.onerror=()=>r(Error(`image load error for ${i.src}`))});return i.complete?i:await e}function be(i,e,t,r){let n=ke(i,e,t);return i.useProgram(n),{buffer:i.createBuffer(),program:n,textures:r,uniform:We(i,n),vao:i.createVertexArray()}}function We(i,e){let t=e?i.getProgramParameter(e,i.ACTIVE_UNIFORMS):0,r=l?.render?new Proxy({},{get(n,s){if(n[s]==null)throw Error(`no shader uniform "${s}"`);return n[s]}}):{};for(let n=0;n<t;++n){let s=i.getActiveUniform(e,n);if(!s)throw Error(`no shader uniform at index ${n}`);let a=i.getUniformLocation(e,s.name);if(!a)throw Error(`no shader uniform "${s.name}"`);let d=s.name.replace("[0]","");r[d]=a}return r}function ke(i,e,t){let r=i.createProgram();if(!r)return null;let n=ge(i,"VERTEX_SHADER",e),s=ge(i,"FRAGMENT_SHADER",t);if(!n||!s)return null;if(i.attachShader(r,n),i.attachShader(r,s),i.linkProgram(r),l?.render&&!i.getProgramParameter(r,i.LINK_STATUS)){let a=i.getProgramInfoLog(r)?.slice(0,-1);throw Error(`shader link failure; ${a}`)}return i.detachShader(r,s),i.detachShader(r,n),i.deleteShader(s),i.deleteShader(n),r}function ge(i,e,t){let r=i.createShader(i[e]);if(!r)return r;if(i.shaderSource(r,t.trim()),i.compileShader(r),l?.render&&!i.getShaderParameter(r,i.COMPILE_STATUS)){let n=i.getShaderInfoLog(r)?.slice(0,-1);throw Error(`shader compile failure; ${n}`)}return r}var we=`#version 300 es
3
+ #pragma debug(${l?.render?"on":"off"})
4
+ #pragma optimize(${l?.render?"off":"on"})
2613
5
 
2614
6
  precision highp int;
2615
7
  precision highp float;
@@ -2627,7 +19,7 @@ flat in ivec2 vDstWHFixed;
2627
19
  out vec4 oRGBA;
2628
20
 
2629
21
  void main() {
2630
- if (vZ == ${Layer.Hidden} || vDstWHFixed.x == 0 || vDstWHFixed.y == 0)
22
+ if (vZ == ${h.Hidden} || vDstWHFixed.x == 0 || vDstWHFixed.y == 0)
2631
23
  discard;
2632
24
 
2633
25
  vec2 px = vec2(vTexXYWH.xy) + (
@@ -2638,12 +30,9 @@ void main() {
2638
30
  oRGBA = texture(uTex, px / vec2(uTexWH));
2639
31
  if(oRGBA.a < .001) discard;
2640
32
  }
2641
- `;
2642
-
2643
- // src/graphics/sprite-vert.glsl.ts
2644
- var spriteVertGLSL = `#version 300 es
2645
- #pragma debug(${debug?.render ? "on" : "off"})
2646
- #pragma optimize(${debug?.render ? "off" : "on"})
33
+ `;var ve=`#version 300 es
34
+ #pragma debug(${l?.render?"on":"off"})
35
+ #pragma optimize(${l?.render?"off":"on"})
2647
36
 
2648
37
  // https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#essl300_minimum_requirements_webgl_2
2649
38
  precision highp int;
@@ -2690,11 +79,11 @@ void main() {
2690
79
  vec2 end = vec2(x + targetWH.x, y + targetWH.y);
2691
80
  // UI layers are always given in screen coordinates.
2692
81
  // to-do: how to handle non-int mode?
2693
- vec2 camXY = z < ${Layer.A} ? vec2(0, 0) : vec2(uCam.xy);
82
+ vec2 camXY = z < ${h.A} ? vec2(0, 0) : vec2(uCam.xy);
2694
83
  vec2 clip = ((-2. * camXY + 2. * end) / vec2(uCam.zw) - 1.) * vec2(1, -1);
2695
84
  gl_Position = vec4(clip, depth, 1);
2696
85
 
2697
- int frame = (((int(uAge / ${celMillis}) & 0x1f) - cel) + ${animCels}) & 0xf;
86
+ int frame = (((int(uAge / ${62.5}) & 0x1f) - cel) + ${16}) & 0xf;
2698
87
  uvec4 texXYWH = texelFetch(uCels, ivec2(0, id + frame), 0);
2699
88
  vTexXYWH = ivec4(texXYWH);
2700
89
  vZ = z;
@@ -2704,1141 +93,6 @@ void main() {
2704
93
 
2705
94
  vStretch = stretch ? 1u : 0u;
2706
95
  }
2707
- `;
2708
-
2709
- // src/graphics/renderer.ts
2710
- var uv = new Int8Array([1, 1, 0, 1, 1, 0, 0, 0]);
2711
- var Renderer = class {
2712
- /** when off, ents should avoid requesting renders. */
2713
- always = false;
2714
- invalid = false;
2715
- loseContext;
2716
- #canvas;
2717
- #clearRGBA = 0;
2718
- #ctx;
2719
- #preloadAtlas;
2720
- #preloadAtlasImage;
2721
- constructor(preloadAtlas, canvas) {
2722
- this.#preloadAtlas = preloadAtlas;
2723
- this.#canvas = canvas;
2724
- this.#ctx = this.#Context();
2725
- }
2726
- clear(rgba) {
2727
- if (!this.#ctx) return;
2728
- const { gl } = this.#ctx;
2729
- if (this.#clearRGBA !== rgba) {
2730
- this.#clearRGBA = rgba;
2731
- gl.clearColor(
2732
- (rgba >>> 24 & 255) / 255,
2733
- (rgba >>> 16 & 255) / 255,
2734
- (rgba >>> 8 & 255) / 255,
2735
- (rgba >>> 0 & 255) / 255
2736
- );
2737
- }
2738
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
2739
- }
2740
- draw(pool) {
2741
- if (!this.#preloadAtlasImage || !this.#ctx) return;
2742
- const { gl, spriteShader } = this.#ctx;
2743
- gl.bindBuffer(gl.ARRAY_BUFFER, spriteShader.buffer);
2744
- gl.bufferData(
2745
- gl.ARRAY_BUFFER,
2746
- pool.view,
2747
- gl.DYNAMIC_DRAW,
2748
- 0,
2749
- pool.size * drawableBytes
2750
- );
2751
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
2752
- gl.bindVertexArray(spriteShader.vao);
2753
- gl.drawArraysInstanced(
2754
- gl.TRIANGLE_STRIP,
2755
- 0,
2756
- uv.length / 2,
2757
- // d
2758
- pool.size
2759
- );
2760
- gl.bindVertexArray(null);
2761
- this.invalid = false;
2762
- }
2763
- load(preloadAtlas) {
2764
- this.#preloadAtlasImage = preloadAtlas;
2765
- this.#ctx = this.#Context();
2766
- }
2767
- predraw(cam, framer) {
2768
- if (!this.#ctx) return;
2769
- const { gl, spriteShader, viewport } = this.#ctx;
2770
- if (!whEq(viewport, cam)) {
2771
- gl.viewport(0, 0, cam.w, cam.h);
2772
- viewport.w = cam.w;
2773
- viewport.h = cam.h;
2774
- }
2775
- gl.useProgram(spriteShader.program);
2776
- gl.uniform4i(spriteShader.uniform.uCam, cam.x, cam.y, cam.w, cam.h);
2777
- gl.uniform1f(spriteShader.uniform.uAge, framer.age);
2778
- for (const [i, tex] of spriteShader.textures.entries()) {
2779
- gl.activeTexture(gl.TEXTURE0 + i);
2780
- gl.bindTexture(gl.TEXTURE_2D, tex);
2781
- }
2782
- }
2783
- register(op) {
2784
- this.#canvas[`${op}EventListener`]("webglcontextlost", this.#onContextLost);
2785
- this.#canvas[`${op}EventListener`](
2786
- "webglcontextrestored",
2787
- this.#onContextRestored
2788
- );
2789
- return this;
2790
- }
2791
- setDepth(enable) {
2792
- if (!this.#ctx) return;
2793
- if (enable) this.#ctx.gl.enable(this.#ctx.gl.DEPTH_TEST);
2794
- else this.#ctx.gl.disable(this.#ctx.gl.DEPTH_TEST);
2795
- }
2796
- [Symbol.dispose]() {
2797
- this.register("remove");
2798
- }
2799
- #Context() {
2800
- const gl = this.#ctx?.gl ?? GL2(this.#canvas);
2801
- if (!gl) return;
2802
- const shader = Shader(gl, spriteVertGLSL, spriteFragGLSL, [
2803
- gl.createTexture(),
2804
- gl.createTexture()
2805
- ]);
2806
- gl.enable(gl.BLEND);
2807
- gl.blendFuncSeparate(
2808
- gl.SRC_ALPHA,
2809
- gl.ONE_MINUS_SRC_ALPHA,
2810
- gl.ONE,
2811
- gl.ONE_MINUS_SRC_ALPHA
2812
- );
2813
- gl.depthRange(0, 1);
2814
- gl.clearDepth(1);
2815
- gl.depthFunc(gl.LESS);
2816
- gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, false);
2817
- gl.bindVertexArray(shader.vao);
2818
- gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
2819
- gl.bufferData(gl.ARRAY_BUFFER, uv, gl.STATIC_DRAW);
2820
- gl.enableVertexAttribArray(0);
2821
- gl.vertexAttribIPointer(0, 2, gl.BYTE, 0, 0);
2822
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
2823
- gl.bindBuffer(gl.ARRAY_BUFFER, shader.buffer);
2824
- gl.enableVertexAttribArray(1);
2825
- gl.vertexAttribIPointer(1, 1, gl.UNSIGNED_INT, drawableBytes, 0);
2826
- gl.vertexAttribDivisor(1, 1);
2827
- gl.enableVertexAttribArray(2);
2828
- gl.vertexAttribIPointer(2, 1, gl.UNSIGNED_INT, drawableBytes, 4);
2829
- gl.vertexAttribDivisor(2, 1);
2830
- gl.enableVertexAttribArray(3);
2831
- gl.vertexAttribIPointer(3, 1, gl.UNSIGNED_INT, drawableBytes, 8);
2832
- gl.vertexAttribDivisor(3, 1);
2833
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
2834
- gl.bindTexture(gl.TEXTURE_2D, shader.textures[0]);
2835
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
2836
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
2837
- if (this.#preloadAtlasImage)
2838
- gl.texImage2D(
2839
- gl.TEXTURE_2D,
2840
- 0,
2841
- gl.RGBA,
2842
- gl.RGBA,
2843
- gl.UNSIGNED_BYTE,
2844
- this.#preloadAtlasImage
2845
- );
2846
- gl.bindTexture(gl.TEXTURE_2D, null);
2847
- gl.bindTexture(gl.TEXTURE_2D, shader.textures[1]);
2848
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
2849
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
2850
- gl.texImage2D(
2851
- gl.TEXTURE_2D,
2852
- 0,
2853
- gl.RGBA16UI,
2854
- // source XYWH cannot be > 65535.
2855
- 1,
2856
- this.#preloadAtlas.celXYWH.length / 4,
2857
- // 4 u16s per row
2858
- 0,
2859
- gl.RGBA_INTEGER,
2860
- gl.UNSIGNED_SHORT,
2861
- new Uint16Array(this.#preloadAtlas.celXYWH)
2862
- );
2863
- gl.bindTexture(gl.TEXTURE_2D, null);
2864
- gl.bindVertexArray(null);
2865
- gl.uniform1i(shader.uniform.uTex, 0);
2866
- gl.uniform1i(shader.uniform.uCels, 1);
2867
- if (this.#preloadAtlasImage)
2868
- gl.uniform2ui(
2869
- shader.uniform.uTexWH,
2870
- this.#preloadAtlasImage.naturalWidth,
2871
- this.#preloadAtlasImage.naturalHeight
2872
- );
2873
- this.invalid = true;
2874
- this.loseContext = gl.getExtension("WEBGL_lose_context") ?? void 0;
2875
- return this.#ctx = { gl, spriteShader: shader, viewport: { w: 0, h: 0 } };
2876
- }
2877
- #onContextLost = (ev) => {
2878
- ev.preventDefault();
2879
- console.debug("[render] WebGL context lost");
2880
- this.#ctx = void 0;
2881
- };
2882
- #onContextRestored = () => {
2883
- console.debug("[render] WebGL context restored");
2884
- this.#ctx = this.#Context();
2885
- };
2886
- };
2887
- function GL2(canvas) {
2888
- const gl = canvas.getContext("webgl2", {
2889
- // to-do: expose.
2890
- antialias: false,
2891
- powerPreference: "low-power",
2892
- // avoid flicker caused by clearing the drawing buffer. see
2893
- // https://developer.chrome.com/blog/desynchronized/.
2894
- preserveDrawingBuffer: true,
2895
- ...!debug?.render && { desynchronized: true }
2896
- });
2897
- if (!gl) {
2898
- console.debug("[render] no GL context");
2899
- return;
2900
- }
2901
- if (debug?.render && !gl.getContextAttributes()?.desynchronized)
2902
- console.debug("[render] no WebGL DOM desynchronization");
2903
- return gl;
2904
- }
2905
-
2906
- // src/looper.ts
2907
- var Looper = class {
2908
- /** duration of frames observed. */
2909
- age = 0;
2910
- onFrame;
2911
- #req = 0;
2912
- #registered = false;
2913
- register(op) {
2914
- const fn = `${op}EventListener`;
2915
- document[fn]("visibilitychange", this.#onVisibility);
2916
- if (op === "remove") this.#cancel();
2917
- this.#registered = op === "add";
2918
- return this;
2919
- }
2920
- requestFrame() {
2921
- if (this.#req || document.hidden || !this.#registered) return;
2922
- this.#req = requestAnimationFrame(this.#onFrame);
2923
- }
2924
- [Symbol.dispose]() {
2925
- this.register("remove");
2926
- }
2927
- #cancel() {
2928
- if (this.#req) cancelAnimationFrame(this.#req);
2929
- this.#req = 0;
2930
- }
2931
- #onFrame = (now) => {
2932
- this.age = now;
2933
- this.#req = 0;
2934
- this.onFrame?.(now - (this.age || now));
2935
- };
2936
- #onVisibility = (ev) => {
2937
- if (!ev.isTrusted) return;
2938
- if (document.hidden) this.#cancel();
2939
- else this.requestFrame();
2940
- };
2941
- };
2942
-
2943
- // src/pixel-ratio-observer.ts
2944
- var PixelRatioObserver = class {
2945
- onChange = () => {
2946
- };
2947
- #mediaQuery;
2948
- register(op) {
2949
- this.#mediaQuery?.removeEventListener("change", this.#onChange);
2950
- if (op === "add") {
2951
- this.#mediaQuery = matchMedia(`not (resolution: ${devicePixelRatio}dppx)`);
2952
- this.#mediaQuery.addEventListener("change", this.#onChange);
2953
- } else this.#mediaQuery = void 0;
2954
- return this;
2955
- }
2956
- [Symbol.dispose]() {
2957
- this.register("remove");
2958
- }
2959
- #onChange = () => {
2960
- this.register("add");
2961
- this.onChange();
2962
- };
2963
- };
2964
-
2965
- // src/void.ts
2966
- var Void = class {
2967
- cam = new Cam();
2968
- canvas;
2969
- framer = new Looper();
2970
- input;
2971
- preload;
2972
- renderer;
2973
- sprites;
2974
- zoo = new Zoo();
2975
- #pixelRatioObserver = new PixelRatioObserver();
2976
- #preloadAtlasImage;
2977
- #resizeObserver = new ResizeObserver(() => this.onResize());
2978
- constructor(opts) {
2979
- initMetaViewport();
2980
- this.canvas = initCanvas(opts.canvas, opts.mode ?? "Int");
2981
- initBody(this.canvas, opts.backgroundRGBA ?? 255);
2982
- if (opts.minWH) this.cam.minWH = opts.minWH;
2983
- this.cam.mode = opts.mode ?? "Int";
2984
- this.cam.update(this.canvas);
2985
- this.input = new Input(this.cam, this.canvas);
2986
- if (opts.input !== "Custom") this.input.mapDefault();
2987
- this.input.onEvent = () => this.onEvent();
2988
- this.#pixelRatioObserver.onChange = () => this.onResize();
2989
- if (opts.preloadAtlas) this.#preloadAtlasImage = opts.preloadAtlas.image;
2990
- this.preload = opts.preloadAtlas ? parseAtlas(opts.preloadAtlas.json) : { anim: {}, celXYWH: [], tags: [] };
2991
- this.renderer = new Renderer(this.preload ?? {}, this.canvas);
2992
- this.sprites = new Pool({
2993
- alloc: (pool) => this.onAllocSprite(pool),
2994
- allocBytes: drawableBytes,
2995
- minPages: opts.sprites?.minPages ?? 3,
2996
- pageBlocks: opts.sprites?.pageBlocks ?? 1e3
2997
- });
2998
- this.framer.onFrame = (millis) => this.onFrame(millis);
2999
- }
3000
- onAllocSprite(pool) {
3001
- return new Sprite(pool, 0, this.preload, this.framer);
3002
- }
3003
- onEvent() {
3004
- this.framer.requestFrame();
3005
- }
3006
- /** update input, update canvas, update cam, update world, then render. */
3007
- onFrame(millis) {
3008
- if (document.hidden) return;
3009
- this.input.update(millis);
3010
- this.onLoop(millis);
3011
- this.cam.postupdate();
3012
- }
3013
- // biome-ignore lint/correctness/noUnusedFunctionParameters:;
3014
- onLoop(millis) {
3015
- }
3016
- onResize() {
3017
- this.framer.requestFrame();
3018
- }
3019
- async register(op) {
3020
- this.input.register(op);
3021
- this.renderer.register(op);
3022
- this.framer.register(op);
3023
- if (!this.canvas.parentElement) throw Error("no canvas parent");
3024
- if (op === "add") this.#resizeObserver.observe(this.canvas.parentElement);
3025
- else this.#resizeObserver.unobserve(this.canvas.parentElement);
3026
- this.#pixelRatioObserver.register(op);
3027
- this.framer.requestFrame();
3028
- if (this.#preloadAtlasImage) await loadImage(this.#preloadAtlasImage);
3029
- this.renderer.load(this.#preloadAtlasImage);
3030
- }
3031
- requestFrame() {
3032
- if (this.renderer.always || this.input.anyOn || this.input.gamepad)
3033
- this.framer.requestFrame();
3034
- }
3035
- async [Symbol.asyncDispose]() {
3036
- await this.register("remove");
3037
- }
3038
- };
3039
-
3040
- // src/index.ts
3041
- var version = voidVersion ? `${voidVersion.version}+${voidVersion.published}.${voidVersion.hash}` : "?";
3042
-
3043
- // src/demo/assets/preload-atlas.json
3044
- var preload_atlas_default = {
3045
- anim: {
3046
- "background--OrangeCheckerboard": { cels: 1, h: 2, id: 0, w: 2 },
3047
- "background--GreyCheckerboard": { cels: 1, h: 2, id: 1, w: 2 },
3048
- "background--Kiwi": { cels: 1, h: 2, id: 2, w: 2 },
3049
- "background--Strawberry": { cels: 1, h: 2, id: 3, w: 2 },
3050
- "background--Grape": { cels: 1, h: 2, id: 4, w: 2 },
3051
- "background--Blueberry": { cels: 1, h: 2, id: 5, w: 2 },
3052
- "background--Bubblegum": { cels: 1, h: 2, id: 6, w: 2 },
3053
- "background--Transparent": { cels: 1, h: 2, id: 7, w: 2 },
3054
- "background--Black": { cels: 1, h: 2, id: 8, w: 2 },
3055
- "backpacker--WalkRight": {
3056
- cels: 16,
3057
- h: 13,
3058
- hitbox: { x: 2, y: 0, w: 4, h: 4 },
3059
- id: 9,
3060
- w: 8
3061
- },
3062
- "backpacker--WalkDown": {
3063
- cels: 16,
3064
- h: 13,
3065
- hitbox: { x: 2, y: 0, w: 4, h: 4 },
3066
- id: 10,
3067
- w: 8
3068
- },
3069
- "backpacker--WalkUp": {
3070
- cels: 16,
3071
- h: 13,
3072
- hitbox: { x: 2, y: 0, w: 4, h: 4 },
3073
- id: 11,
3074
- w: 8
3075
- },
3076
- "cursor--Pointer": {
3077
- cels: 1,
3078
- h: 14,
3079
- hitbox: { x: 0, y: 0, w: 2, h: 2 },
3080
- hurtbox: { x: 0, y: 0, w: 2, h: 2 },
3081
- id: 12,
3082
- w: 8
3083
- },
3084
- "mem-prop-5x6--00": { cels: 1, h: 6, id: 13, w: 5 },
3085
- "mem-prop-5x6--01": { cels: 1, h: 6, id: 14, w: 5 },
3086
- "mem-prop-5x6--02": { cels: 1, h: 6, id: 15, w: 5 },
3087
- "mem-prop-5x6--03": { cels: 1, h: 6, id: 16, w: 5 },
3088
- "mem-prop-5x6--04": { cels: 1, h: 6, id: 17, w: 5 },
3089
- "mem-prop-5x6--05": { cels: 1, h: 6, id: 18, w: 5 },
3090
- "mem-prop-5x6--06": { cels: 1, h: 6, id: 19, w: 5 },
3091
- "mem-prop-5x6--07": { cels: 1, h: 6, id: 20, w: 5 },
3092
- "mem-prop-5x6--08": { cels: 1, h: 6, id: 21, w: 5 },
3093
- "mem-prop-5x6--09": { cels: 1, h: 6, id: 22, w: 5 },
3094
- "mem-prop-5x6--0a": { cels: 1, h: 6, id: 23, w: 5 },
3095
- "mem-prop-5x6--0b": { cels: 1, h: 6, id: 24, w: 5 },
3096
- "mem-prop-5x6--0c": { cels: 1, h: 6, id: 25, w: 5 },
3097
- "mem-prop-5x6--0d": { cels: 1, h: 6, id: 26, w: 5 },
3098
- "mem-prop-5x6--0e": { cels: 1, h: 6, id: 27, w: 5 },
3099
- "mem-prop-5x6--0f": { cels: 1, h: 6, id: 28, w: 5 },
3100
- "mem-prop-5x6--10": { cels: 1, h: 6, id: 29, w: 5 },
3101
- "mem-prop-5x6--11": { cels: 1, h: 6, id: 30, w: 5 },
3102
- "mem-prop-5x6--12": { cels: 1, h: 6, id: 31, w: 5 },
3103
- "mem-prop-5x6--13": { cels: 1, h: 6, id: 32, w: 5 },
3104
- "mem-prop-5x6--14": { cels: 1, h: 6, id: 33, w: 5 },
3105
- "mem-prop-5x6--15": { cels: 1, h: 6, id: 34, w: 5 },
3106
- "mem-prop-5x6--16": { cels: 1, h: 6, id: 35, w: 5 },
3107
- "mem-prop-5x6--17": { cels: 1, h: 6, id: 36, w: 5 },
3108
- "mem-prop-5x6--18": { cels: 1, h: 6, id: 37, w: 5 },
3109
- "mem-prop-5x6--19": { cels: 1, h: 6, id: 38, w: 5 },
3110
- "mem-prop-5x6--1a": { cels: 1, h: 6, id: 39, w: 5 },
3111
- "mem-prop-5x6--1b": { cels: 1, h: 6, id: 40, w: 5 },
3112
- "mem-prop-5x6--1c": { cels: 1, h: 6, id: 41, w: 5 },
3113
- "mem-prop-5x6--1d": { cels: 1, h: 6, id: 42, w: 5 },
3114
- "mem-prop-5x6--1e": { cels: 1, h: 6, id: 43, w: 5 },
3115
- "mem-prop-5x6--1f": { cels: 1, h: 6, id: 44, w: 5 },
3116
- "mem-prop-5x6--20": { cels: 1, h: 6, id: 45, w: 5 },
3117
- "mem-prop-5x6--21": { cels: 1, h: 6, id: 46, w: 5 },
3118
- "mem-prop-5x6--22": { cels: 1, h: 6, id: 47, w: 5 },
3119
- "mem-prop-5x6--23": { cels: 1, h: 6, id: 48, w: 5 },
3120
- "mem-prop-5x6--24": { cels: 1, h: 6, id: 49, w: 5 },
3121
- "mem-prop-5x6--25": { cels: 1, h: 6, id: 50, w: 5 },
3122
- "mem-prop-5x6--26": { cels: 1, h: 6, id: 51, w: 5 },
3123
- "mem-prop-5x6--27": { cels: 1, h: 6, id: 52, w: 5 },
3124
- "mem-prop-5x6--28": { cels: 1, h: 6, id: 53, w: 5 },
3125
- "mem-prop-5x6--29": { cels: 1, h: 6, id: 54, w: 5 },
3126
- "mem-prop-5x6--2a": { cels: 1, h: 6, id: 55, w: 5 },
3127
- "mem-prop-5x6--2b": { cels: 1, h: 6, id: 56, w: 5 },
3128
- "mem-prop-5x6--2c": { cels: 1, h: 6, id: 57, w: 5 },
3129
- "mem-prop-5x6--2d": { cels: 1, h: 6, id: 58, w: 5 },
3130
- "mem-prop-5x6--2e": { cels: 1, h: 6, id: 59, w: 5 },
3131
- "mem-prop-5x6--2f": { cels: 1, h: 6, id: 60, w: 5 },
3132
- "mem-prop-5x6--30": { cels: 1, h: 6, id: 61, w: 5 },
3133
- "mem-prop-5x6--31": { cels: 1, h: 6, id: 62, w: 5 },
3134
- "mem-prop-5x6--32": { cels: 1, h: 6, id: 63, w: 5 },
3135
- "mem-prop-5x6--33": { cels: 1, h: 6, id: 64, w: 5 },
3136
- "mem-prop-5x6--34": { cels: 1, h: 6, id: 65, w: 5 },
3137
- "mem-prop-5x6--35": { cels: 1, h: 6, id: 66, w: 5 },
3138
- "mem-prop-5x6--36": { cels: 1, h: 6, id: 67, w: 5 },
3139
- "mem-prop-5x6--37": { cels: 1, h: 6, id: 68, w: 5 },
3140
- "mem-prop-5x6--38": { cels: 1, h: 6, id: 69, w: 5 },
3141
- "mem-prop-5x6--39": { cels: 1, h: 6, id: 70, w: 5 },
3142
- "mem-prop-5x6--3a": { cels: 1, h: 6, id: 71, w: 5 },
3143
- "mem-prop-5x6--3b": { cels: 1, h: 6, id: 72, w: 5 },
3144
- "mem-prop-5x6--3c": { cels: 1, h: 6, id: 73, w: 5 },
3145
- "mem-prop-5x6--3d": { cels: 1, h: 6, id: 74, w: 5 },
3146
- "mem-prop-5x6--3e": { cels: 1, h: 6, id: 75, w: 5 },
3147
- "mem-prop-5x6--3f": { cels: 1, h: 6, id: 76, w: 5 },
3148
- "mem-prop-5x6--40": { cels: 1, h: 6, id: 77, w: 5 },
3149
- "mem-prop-5x6--41": { cels: 1, h: 6, id: 78, w: 5 },
3150
- "mem-prop-5x6--42": { cels: 1, h: 6, id: 79, w: 5 },
3151
- "mem-prop-5x6--43": { cels: 1, h: 6, id: 80, w: 5 },
3152
- "mem-prop-5x6--44": { cels: 1, h: 6, id: 81, w: 5 },
3153
- "mem-prop-5x6--45": { cels: 1, h: 6, id: 82, w: 5 },
3154
- "mem-prop-5x6--46": { cels: 1, h: 6, id: 83, w: 5 },
3155
- "mem-prop-5x6--47": { cels: 1, h: 6, id: 84, w: 5 },
3156
- "mem-prop-5x6--48": { cels: 1, h: 6, id: 85, w: 5 },
3157
- "mem-prop-5x6--49": { cels: 1, h: 6, id: 86, w: 5 },
3158
- "mem-prop-5x6--4a": { cels: 1, h: 6, id: 87, w: 5 },
3159
- "mem-prop-5x6--4b": { cels: 1, h: 6, id: 88, w: 5 },
3160
- "mem-prop-5x6--4c": { cels: 1, h: 6, id: 89, w: 5 },
3161
- "mem-prop-5x6--4d": { cels: 1, h: 6, id: 90, w: 5 },
3162
- "mem-prop-5x6--4e": { cels: 1, h: 6, id: 91, w: 5 },
3163
- "mem-prop-5x6--4f": { cels: 1, h: 6, id: 92, w: 5 },
3164
- "mem-prop-5x6--50": { cels: 1, h: 6, id: 93, w: 5 },
3165
- "mem-prop-5x6--51": { cels: 1, h: 6, id: 94, w: 5 },
3166
- "mem-prop-5x6--52": { cels: 1, h: 6, id: 95, w: 5 },
3167
- "mem-prop-5x6--53": { cels: 1, h: 6, id: 96, w: 5 },
3168
- "mem-prop-5x6--54": { cels: 1, h: 6, id: 97, w: 5 },
3169
- "mem-prop-5x6--55": { cels: 1, h: 6, id: 98, w: 5 },
3170
- "mem-prop-5x6--56": { cels: 1, h: 6, id: 99, w: 5 },
3171
- "mem-prop-5x6--57": { cels: 1, h: 6, id: 100, w: 5 },
3172
- "mem-prop-5x6--58": { cels: 1, h: 6, id: 101, w: 5 },
3173
- "mem-prop-5x6--59": { cels: 1, h: 6, id: 102, w: 5 },
3174
- "mem-prop-5x6--5a": { cels: 1, h: 6, id: 103, w: 5 },
3175
- "mem-prop-5x6--5b": { cels: 1, h: 6, id: 104, w: 5 },
3176
- "mem-prop-5x6--5c": { cels: 1, h: 6, id: 105, w: 5 },
3177
- "mem-prop-5x6--5d": { cels: 1, h: 6, id: 106, w: 5 },
3178
- "mem-prop-5x6--5e": { cels: 1, h: 6, id: 107, w: 5 },
3179
- "mem-prop-5x6--5f": { cels: 1, h: 6, id: 108, w: 5 },
3180
- "mem-prop-5x6--60": { cels: 1, h: 6, id: 109, w: 5 },
3181
- "mem-prop-5x6--61": { cels: 1, h: 6, id: 110, w: 5 },
3182
- "mem-prop-5x6--62": { cels: 1, h: 6, id: 111, w: 5 },
3183
- "mem-prop-5x6--63": { cels: 1, h: 6, id: 112, w: 5 },
3184
- "mem-prop-5x6--64": { cels: 1, h: 6, id: 113, w: 5 },
3185
- "mem-prop-5x6--65": { cels: 1, h: 6, id: 114, w: 5 },
3186
- "mem-prop-5x6--66": { cels: 1, h: 6, id: 115, w: 5 },
3187
- "mem-prop-5x6--67": { cels: 1, h: 6, id: 116, w: 5 },
3188
- "mem-prop-5x6--68": { cels: 1, h: 6, id: 117, w: 5 },
3189
- "mem-prop-5x6--69": { cels: 1, h: 6, id: 118, w: 5 },
3190
- "mem-prop-5x6--6a": { cels: 1, h: 6, id: 119, w: 5 },
3191
- "mem-prop-5x6--6b": { cels: 1, h: 6, id: 120, w: 5 },
3192
- "mem-prop-5x6--6c": { cels: 1, h: 6, id: 121, w: 5 },
3193
- "mem-prop-5x6--6d": { cels: 1, h: 6, id: 122, w: 5 },
3194
- "mem-prop-5x6--6e": { cels: 1, h: 6, id: 123, w: 5 },
3195
- "mem-prop-5x6--6f": { cels: 1, h: 6, id: 124, w: 5 },
3196
- "mem-prop-5x6--70": { cels: 1, h: 6, id: 125, w: 5 },
3197
- "mem-prop-5x6--71": { cels: 1, h: 6, id: 126, w: 5 },
3198
- "mem-prop-5x6--72": { cels: 1, h: 6, id: 127, w: 5 },
3199
- "mem-prop-5x6--73": { cels: 1, h: 6, id: 128, w: 5 },
3200
- "mem-prop-5x6--74": { cels: 1, h: 6, id: 129, w: 5 },
3201
- "mem-prop-5x6--75": { cels: 1, h: 6, id: 130, w: 5 },
3202
- "mem-prop-5x6--76": { cels: 1, h: 6, id: 131, w: 5 },
3203
- "mem-prop-5x6--77": { cels: 1, h: 6, id: 132, w: 5 },
3204
- "mem-prop-5x6--78": { cels: 1, h: 6, id: 133, w: 5 },
3205
- "mem-prop-5x6--79": { cels: 1, h: 6, id: 134, w: 5 },
3206
- "mem-prop-5x6--7a": { cels: 1, h: 6, id: 135, w: 5 },
3207
- "mem-prop-5x6--7b": { cels: 1, h: 6, id: 136, w: 5 },
3208
- "mem-prop-5x6--7c": { cels: 1, h: 6, id: 137, w: 5 },
3209
- "mem-prop-5x6--7d": { cels: 1, h: 6, id: 138, w: 5 },
3210
- "mem-prop-5x6--7e": { cels: 1, h: 6, id: 139, w: 5 },
3211
- "mem-prop-5x6--7f": { cels: 1, h: 6, id: 140, w: 5 },
3212
- "oidoid--Default": { cels: 1, h: 16, id: 141, w: 16 }
3213
- },
3214
- celXY: [
3215
- 22,
3216
- 37,
3217
- 21,
3218
- 27,
3219
- 21,
3220
- 29,
3221
- 21,
3222
- 31,
3223
- 20,
3224
- 33,
3225
- 22,
3226
- 33,
3227
- 20,
3228
- 35,
3229
- 22,
3230
- 35,
3231
- 20,
3232
- 37,
3233
- 24,
3234
- 26,
3235
- 24,
3236
- 26,
3237
- 8,
3238
- 16,
3239
- 8,
3240
- 16,
3241
- 0,
3242
- 16,
3243
- 0,
3244
- 16,
3245
- 16,
3246
- 14,
3247
- 16,
3248
- 14,
3249
- 72,
3250
- 13,
3251
- 72,
3252
- 13,
3253
- 32,
3254
- 26,
3255
- 32,
3256
- 26,
3257
- 0,
3258
- 16,
3259
- 0,
3260
- 16,
3261
- 64,
3262
- 13,
3263
- 64,
3264
- 13,
3265
- 56,
3266
- 13,
3267
- 56,
3268
- 13,
3269
- 48,
3270
- 13,
3271
- 48,
3272
- 13,
3273
- 40,
3274
- 13,
3275
- 40,
3276
- 13,
3277
- 32,
3278
- 13,
3279
- 32,
3280
- 13,
3281
- 56,
3282
- 13,
3283
- 56,
3284
- 13,
3285
- 24,
3286
- 13,
3287
- 24,
3288
- 13,
3289
- 72,
3290
- 0,
3291
- 72,
3292
- 0,
3293
- 64,
3294
- 0,
3295
- 64,
3296
- 0,
3297
- 24,
3298
- 0,
3299
- 24,
3300
- 0,
3301
- 56,
3302
- 0,
3303
- 56,
3304
- 0,
3305
- 48,
3306
- 0,
3307
- 48,
3308
- 0,
3309
- 48,
3310
- 0,
3311
- 48,
3312
- 0,
3313
- 24,
3314
- 0,
3315
- 24,
3316
- 0,
3317
- 40,
3318
- 0,
3319
- 40,
3320
- 0,
3321
- 32,
3322
- 0,
3323
- 32,
3324
- 0,
3325
- 32,
3326
- 0,
3327
- 32,
3328
- 0,
3329
- 16,
3330
- 0,
3331
- 45,
3332
- 56,
3333
- 45,
3334
- 56,
3335
- 45,
3336
- 56,
3337
- 45,
3338
- 56,
3339
- 45,
3340
- 56,
3341
- 45,
3342
- 56,
3343
- 45,
3344
- 56,
3345
- 45,
3346
- 56,
3347
- 45,
3348
- 56,
3349
- 45,
3350
- 56,
3351
- 45,
3352
- 56,
3353
- 45,
3354
- 56,
3355
- 45,
3356
- 56,
3357
- 45,
3358
- 56,
3359
- 45,
3360
- 56,
3361
- 45,
3362
- 56,
3363
- 45,
3364
- 56,
3365
- 45,
3366
- 56,
3367
- 45,
3368
- 56,
3369
- 45,
3370
- 56,
3371
- 45,
3372
- 56,
3373
- 45,
3374
- 56,
3375
- 45,
3376
- 56,
3377
- 45,
3378
- 56,
3379
- 45,
3380
- 56,
3381
- 45,
3382
- 56,
3383
- 45,
3384
- 56,
3385
- 45,
3386
- 56,
3387
- 45,
3388
- 56,
3389
- 45,
3390
- 56,
3391
- 45,
3392
- 56,
3393
- 45,
3394
- 56,
3395
- 45,
3396
- 56,
3397
- 40,
3398
- 56,
3399
- 10,
3400
- 53,
3401
- 5,
3402
- 53,
3403
- 0,
3404
- 53,
3405
- 35,
3406
- 51,
3407
- 30,
3408
- 51,
3409
- 25,
3410
- 51,
3411
- 20,
3412
- 51,
3413
- 15,
3414
- 51,
3415
- 35,
3416
- 45,
3417
- 70,
3418
- 50,
3419
- 65,
3420
- 50,
3421
- 60,
3422
- 50,
3423
- 55,
3424
- 50,
3425
- 50,
3426
- 50,
3427
- 45,
3428
- 50,
3429
- 40,
3430
- 50,
3431
- 10,
3432
- 47,
3433
- 5,
3434
- 47,
3435
- 0,
3436
- 47,
3437
- 70,
3438
- 62,
3439
- 50,
3440
- 56,
3441
- 65,
3442
- 62,
3443
- 60,
3444
- 62,
3445
- 55,
3446
- 62,
3447
- 50,
3448
- 62,
3449
- 45,
3450
- 62,
3451
- 40,
3452
- 62,
3453
- 10,
3454
- 59,
3455
- 5,
3456
- 59,
3457
- 0,
3458
- 59,
3459
- 35,
3460
- 57,
3461
- 70,
3462
- 32,
3463
- 30,
3464
- 57,
3465
- 25,
3466
- 57,
3467
- 20,
3468
- 57,
3469
- 15,
3470
- 57,
3471
- 75,
3472
- 56,
3473
- 70,
3474
- 56,
3475
- 65,
3476
- 56,
3477
- 60,
3478
- 56,
3479
- 75,
3480
- 50,
3481
- 55,
3482
- 56,
3483
- 10,
3484
- 35,
3485
- 75,
3486
- 32,
3487
- 15,
3488
- 33,
3489
- 0,
3490
- 35,
3491
- 5,
3492
- 35,
3493
- 40,
3494
- 38,
3495
- 45,
3496
- 38,
3497
- 65,
3498
- 32,
3499
- 60,
3500
- 32,
3501
- 55,
3502
- 32,
3503
- 50,
3504
- 32,
3505
- 45,
3506
- 32,
3507
- 40,
3508
- 26,
3509
- 50,
3510
- 26,
3511
- 55,
3512
- 26,
3513
- 60,
3514
- 26,
3515
- 65,
3516
- 26,
3517
- 70,
3518
- 26,
3519
- 75,
3520
- 26,
3521
- 16,
3522
- 27,
3523
- 0,
3524
- 29,
3525
- 5,
3526
- 29,
3527
- 10,
3528
- 29,
3529
- 40,
3530
- 32,
3531
- 45,
3532
- 26,
3533
- 10,
3534
- 41,
3535
- 30,
3536
- 45,
3537
- 25,
3538
- 45,
3539
- 20,
3540
- 45,
3541
- 15,
3542
- 45,
3543
- 75,
3544
- 44,
3545
- 70,
3546
- 44,
3547
- 65,
3548
- 44,
3549
- 60,
3550
- 44,
3551
- 55,
3552
- 44,
3553
- 50,
3554
- 44,
3555
- 45,
3556
- 44,
3557
- 40,
3558
- 44,
3559
- 50,
3560
- 38,
3561
- 5,
3562
- 41,
3563
- 0,
3564
- 41,
3565
- 35,
3566
- 39,
3567
- 30,
3568
- 39,
3569
- 25,
3570
- 39,
3571
- 20,
3572
- 39,
3573
- 15,
3574
- 39,
3575
- 75,
3576
- 38,
3577
- 70,
3578
- 38,
3579
- 65,
3580
- 38,
3581
- 60,
3582
- 38,
3583
- 55,
3584
- 38,
3585
- 45,
3586
- 56,
3587
- 0,
3588
- 0
3589
- ]
3590
- };
3591
-
3592
- // src/demo/ents/clock-ent.ts
3593
- var ClockEnt = class {
3594
- #time = new TextEnt();
3595
- constructor() {
3596
- this.#time.scale = 3;
3597
- this.#time.z = Layer.A;
3598
- }
3599
- free(v2) {
3600
- this.#time.free(v2);
3601
- }
3602
- update(v2) {
3603
- const now = /* @__PURE__ */ new Date();
3604
- this.#time.text = timeString(now);
3605
- if (this.#time.layout(v2) || v2.cam.invalid)
3606
- this.#time.xy = v2.cam.follow(
3607
- { w: this.#time.wh.w, h: this.#time.wh.h - this.#time.scaledLeading },
3608
- this.#time.z,
3609
- "N",
3610
- { margin: { h: 8 } }
3611
- );
3612
- return this.#time.update(v2);
3613
- }
3614
- };
3615
- function timeString(time) {
3616
- const hh = `${time.getHours() % 12 || 12}`.padStart(2, " ");
3617
- const mm = `${time.getMinutes()}`.padStart(2, "0");
3618
- const ss = `${time.getSeconds()}`.padStart(2, "0");
3619
- return `${hh}:${mm}:${ss}`;
3620
- }
3621
-
3622
- // src/demo/ents/render-toggle-ent.ts
3623
- var RenderToggleEnt = class {
3624
- #toggle;
3625
- constructor(v2) {
3626
- this.#toggle = new ButtonEnt(v2, {
3627
- button: {
3628
- w: { tag: "background--Strawberry" },
3629
- nw: { tag: "background--Transparent" },
3630
- n: { tag: "background--Bubblegum" },
3631
- e: { tag: "background--Blueberry" },
3632
- s: { tag: "background--Kiwi" },
3633
- origin: { tag: "background--Grape" },
3634
- border: { n: 1 },
3635
- margin: { w: 2, h: 2 }
3636
- },
3637
- selected: { tag: "background--OrangeCheckerboard" },
3638
- toggle: true,
3639
- text: { text: "render", scale: 2 },
3640
- w: 64,
3641
- h: 22,
3642
- x: 50,
3643
- y: 25,
3644
- pressed: { tag: "background--Bubblegum" }
3645
- });
3646
- }
3647
- get on() {
3648
- return this.#toggle.on;
3649
- }
3650
- free(v2) {
3651
- this.#toggle.free(v2);
3652
- }
3653
- /** always updates but never invalidates. */
3654
- update(v2) {
3655
- return this.#toggle.update(v2);
3656
- }
3657
- };
3658
-
3659
- // src/demo/ents/work-counter-ent.ts
3660
- var WorkCounterEnt = class {
3661
- #renders = 0;
3662
- #text = new TextEnt();
3663
- #updates = 0;
3664
- constructor() {
3665
- this.#text.z = Layer.A;
3666
- }
3667
- free(v2) {
3668
- this.#text.free(v2);
3669
- }
3670
- incrementRender() {
3671
- this.#renders++;
3672
- }
3673
- /** always updates but never invalidates. */
3674
- update(v2) {
3675
- this.#updates++;
3676
- this.#text.text = `${this.#updates} updates
3677
- ${this.#renders + 1} renders`;
3678
- this.#text.layout(v2);
3679
- this.#text.xy = v2.cam.follow(
3680
- { w: this.#text.wh.w, h: this.#text.wh.h - this.#text.scaledLeading },
3681
- this.#text.z,
3682
- "NE",
3683
- { margin: { w: 8, h: 8 } }
3684
- );
3685
- this.#text.update(v2);
3686
- }
3687
- };
3688
-
3689
- // src/demo/game.ts
3690
- var Game = class extends Void {
3691
- #filterSprites;
3692
- #interval = 0;
3693
- #renderToggle;
3694
- #timer = 0;
3695
- #workCounter;
3696
- constructor() {
3697
- super({
3698
- preloadAtlas: {
3699
- image: document.querySelector("#preload-atlas"),
3700
- json: preload_atlas_default
3701
- },
3702
- backgroundRGBA: 4294947327,
3703
- minWH: { w: 320, h: 240 }
3704
- });
3705
- this.#filterSprites = new Pool({
3706
- alloc: (pool) => new Sprite(pool, 0, this.preload, this.framer),
3707
- allocBytes: drawableBytes,
3708
- pageBlocks: 10
3709
- });
3710
- this.#renderToggle = new RenderToggleEnt(this);
3711
- this.#workCounter = new WorkCounterEnt();
3712
- this.#initZoo();
3713
- }
3714
- async register(op) {
3715
- await super.register(op);
3716
- if (op === "add") {
3717
- this.framer.requestFrame();
3718
- this.#startTimer();
3719
- } else {
3720
- this.#stopTimer();
3721
- }
3722
- }
3723
- onLoop(_millis) {
3724
- this.renderer.always = this.#renderToggle.on || !!debug?.invalid;
3725
- let render = this.#updateCam();
3726
- const updated = this.zoo.update(this);
3727
- if (debug?.input) this.#printInput();
3728
- render ||= updated || this.cam.invalid || this.renderer.invalid || this.renderer.always;
3729
- if (render) {
3730
- this.#workCounter.incrementRender();
3731
- this.renderer.clear(4294947327);
3732
- this.renderer.predraw(this.cam, this.framer);
3733
- this.renderer.setDepth(true);
3734
- this.renderer.draw(this.sprites);
3735
- this.renderer.setDepth(false);
3736
- this.renderer.draw(this.#filterSprites);
3737
- }
3738
- this.requestFrame();
3739
- }
3740
- #initZoo() {
3741
- const border = new NinePatchEnt(this, {
3742
- n: { tag: "background--Black" },
3743
- origin: { tag: "background--Transparent" },
3744
- border: { n: 1 },
3745
- z: Layer.UIA
3746
- // to-do: default 0 layer is dumb.
3747
- });
3748
- this.zoo.add(border);
3749
- const box = this.cam.follow({ w: 0, h: 0 }, Layer.UIA, "NW", { fill: "XY" });
3750
- border.xy = box;
3751
- border.wh = box;
3752
- const backpacker = this.sprites.alloc();
3753
- backpacker.tag = "backpacker--WalkRight";
3754
- backpacker.x = 7;
3755
- backpacker.y = 7;
3756
- backpacker.z = Layer.C;
3757
- backpacker.stretch = true;
3758
- backpacker.w *= 5;
3759
- backpacker.h *= 5;
3760
- const oidoid = new FollowCamEnt(this, "oidoid--Default", "SW");
3761
- oidoid.z = Layer.UIG;
3762
- oidoid.margin = { w: 4, h: 4 };
3763
- this.zoo.add(
3764
- new CursorEnt(this, "cursor--Pointer"),
3765
- this.#renderToggle,
3766
- new ClockEnt(),
3767
- this.#workCounter,
3768
- oidoid
3769
- );
3770
- const overlay = this.#filterSprites.alloc();
3771
- overlay.tag = "background--GreyCheckerboard";
3772
- overlay.w = drawableMaxWH.w;
3773
- overlay.h = drawableMaxWH.h;
3774
- overlay.z = Layer.UIA;
3775
- }
3776
- #printInput() {
3777
- if (this.input.started) {
3778
- const on = !!this.input.on.length;
3779
- if (on) console.debug(`[input] buttons on: ${this.input.on.join(" ")}.`);
3780
- else console.debug(`[input] buttons off.`);
3781
- const combo = this.input.combo;
3782
- if (combo.length > 1 && on)
3783
- console.debug(
3784
- `[input] combo: ${combo.map((set) => set.join("+")).join(" ")}.`
3785
- );
3786
- }
3787
- if (this.input.point?.invalid && this.input.point?.click && !this.input.point.pinch)
3788
- console.debug(
3789
- `[input] ${this.input.point.drag.on ? "drag" : "click"} xy: ${this.input.point.x} ${this.input.point.y}.`
3790
- );
3791
- if (this.input.point?.pinch)
3792
- console.debug(
3793
- `[input] pinch xy: ${this.input.point.pinch.xy.x} ${this.input.point.pinch.xy.y}.`
3794
- );
3795
- if (this.input.wheel)
3796
- console.debug(
3797
- `[input] wheel xy: ${this.input.wheel.delta.xy.x} ${this.input.wheel.delta.xy.y}.`
3798
- );
3799
- }
3800
- #startTimer() {
3801
- this.#timer = setTimeout(
3802
- () => {
3803
- this.framer.requestFrame();
3804
- this.#interval = setInterval(
3805
- () => this.framer.requestFrame(),
3806
- (debug?.seconds ? 1 : 60) * 1e3
3807
- );
3808
- },
3809
- renderDelayMillis(/* @__PURE__ */ new Date(), debug?.seconds)
3810
- );
3811
- }
3812
- #stopTimer() {
3813
- clearTimeout(this.#timer);
3814
- clearInterval(this.#interval);
3815
- }
3816
- #updateCam() {
3817
- let render = this.input.isAnyOn("L", "R", "U", "D");
3818
- if (this.input.isAnyOnStart("L", "R", "U", "D")) {
3819
- this.cam.x = Math.trunc(this.cam.x);
3820
- this.cam.y = Math.trunc(this.cam.y);
3821
- }
3822
- const d = 1 / 4;
3823
- if (this.input.isOn("L")) this.cam.x -= d;
3824
- if (this.input.isOn("R")) this.cam.x += d;
3825
- if (this.input.isOn("U")) this.cam.y -= d;
3826
- if (this.input.isOn("D")) this.cam.y += d;
3827
- if (this.input.wheel?.delta.xy.y) {
3828
- render = true;
3829
- this.cam.zoomOut -= this.input.wheel.delta.client.y * 0.01;
3830
- }
3831
- this.cam.update(this.canvas);
3832
- return render;
3833
- }
3834
- };
3835
- function renderDelayMillis(time, debugSecs) {
3836
- return ((debugSecs ? 0 : (59 - time.getSeconds() % 60) * 1e3) + 1e3 - time.getMilliseconds() % 1e3) % (debugSecs ? 1e3 : 6e4);
3837
- }
3838
-
3839
- // src/demo/index.ts
3840
- console.debug(`void v${version} \u2500\u2500\u2500oidoid>\xB0\u2500\u2500`);
3841
- var v = new Game();
3842
- await v.register("add");
3843
- if (debug) globalThis.v = v;
96
+ `;var Te=new Int8Array([1,1,0,1,1,0,0,0]),D=class{always=l?.render==="always";clears=0;invalid=!1;loseContext;#e;#t=0;#i=!0;#r;#s;#n;#o;constructor(e,t,r){this.#n=e,this.#e=t,this.#s=r}clear(e){if(!this.#r)return;let{gl:t}=this.#r;this.#t!==e&&(this.#t=e,t.clearColor((e>>>24&255)/255,(e>>>16&255)/255,(e>>>8&255)/255,(e>>>0&255)/255)),t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT),this.clears++}draw(e){if(!this.#o||!this.#r)return;let{gl:t,spriteShader:r}=this.#r;t.bindBuffer(t.ARRAY_BUFFER,r.buffer),t.bufferData(t.ARRAY_BUFFER,e.view,t.DYNAMIC_DRAW,0,e.size*c),t.bindBuffer(t.ARRAY_BUFFER,null),t.bindVertexArray(r.vao),t.drawArraysInstanced(t.TRIANGLE_STRIP,0,Te.length/2,e.size),t.bindVertexArray(null),this.invalid=!1}get hasContext(){return this.#r!=null}load(e){this.#o=e,this.#r=this._Context()}predraw(e){if(!this.#r)return;let{gl:t,spriteShader:r,viewport:n}=this.#r;g(n,e)||(t.viewport(0,0,e.w,e.h),n.w=e.w,n.h=e.h),t.useProgram(r.program),t.uniform4i(r.uniform.uCam,e.x,e.y,e.w,e.h),t.uniform1f(r.uniform.uAge,this.#s.age);for(let[s,a]of r.textures.entries())t.activeTexture(t.TEXTURE0+s),t.bindTexture(t.TEXTURE_2D,a)}register(e){return this.#e[`${e}EventListener`]("webglcontextlost",this.#a),this.#e[`${e}EventListener`]("webglcontextrestored",this.#l),this}setDepth(e){this.#i=e,this.#r&&(e?this.#r.gl.enable(this.#r.gl.DEPTH_TEST):this.#r.gl.disable(this.#r.gl.DEPTH_TEST))}[Symbol.dispose](){this.register("remove")}_Context(){let e=this.#r?.gl??He(this.#e);if(!e)return;let t=be(e,ve,we,[e.createTexture(),e.createTexture()]);return e.enable(e.BLEND),e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA),this.setDepth(this.#i),e.depthRange(0,1),e.clearDepth(1),e.depthFunc(e.LESS),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,!1),e.bindVertexArray(t.vao),e.bindBuffer(e.ARRAY_BUFFER,e.createBuffer()),e.bufferData(e.ARRAY_BUFFER,Te,e.STATIC_DRAW),e.enableVertexAttribArray(0),e.vertexAttribIPointer(0,2,e.BYTE,0,0),e.bindBuffer(e.ARRAY_BUFFER,null),e.bindBuffer(e.ARRAY_BUFFER,t.buffer),e.enableVertexAttribArray(1),e.vertexAttribIPointer(1,1,e.UNSIGNED_INT,c,0),e.vertexAttribDivisor(1,1),e.enableVertexAttribArray(2),e.vertexAttribIPointer(2,1,e.UNSIGNED_INT,c,4),e.vertexAttribDivisor(2,1),e.enableVertexAttribArray(3),e.vertexAttribIPointer(3,1,e.UNSIGNED_INT,c,8),e.vertexAttribDivisor(3,1),e.bindBuffer(e.ARRAY_BUFFER,null),e.bindTexture(e.TEXTURE_2D,t.textures[0]),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),this.#o&&e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.#o),e.bindTexture(e.TEXTURE_2D,null),e.bindTexture(e.TEXTURE_2D,t.textures[1]),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texImage2D(e.TEXTURE_2D,0,e.RGBA16UI,1,this.#n.celXYWH.length/4,0,e.RGBA_INTEGER,e.UNSIGNED_SHORT,new Uint16Array(this.#n.celXYWH)),e.bindTexture(e.TEXTURE_2D,null),e.bindVertexArray(null),e.uniform1i(t.uniform.uTex,0),e.uniform1i(t.uniform.uCels,1),this.#o&&e.uniform2ui(t.uniform.uTexWH,this.#o.naturalWidth,this.#o.naturalHeight),!this.invalid&&l?.invalid&&console.debug("renderer invalid"),this.invalid=!0,this.loseContext=e.getExtension("WEBGL_lose_context")??void 0,this.#r={gl:e,spriteShader:t,viewport:{w:0,h:0}}}#a=e=>{e.preventDefault(),console.debug("[render] WebGL context lost"),this.#r=void 0};#l=()=>{console.debug("[render] WebGL context restored"),this.#r=this._Context()}};function He(i){let e=i.getContext("webgl2",{antialias:!1,powerPreference:"low-power",preserveDrawingBuffer:!0,...!l?.render&&{desynchronized:!0}});if(!e){console.debug("[render] no GL context");return}return l?.render&&!e.getContextAttributes()?.desynchronized&&console.debug("[render] no WebGL DOM desynchronization"),e}var F=class{age=0;onFrame;#e=0;#t=!1;register(e){let t=`${e}EventListener`;return document[t]("visibilitychange",this.#s),e==="remove"&&this.#i(),this.#t=e==="add",this}requestFrame(){this.#e||document.hidden||!this.#t||(this.#e=requestAnimationFrame(this.#r))}[Symbol.dispose](){this.register("remove")}#i(){this.#e&&cancelAnimationFrame(this.#e),this.#e=0}#r=e=>{let t=e-(this.age||e);this.age=e,this.#e=0,this.onFrame?.(t)};#s=e=>{e.isTrusted&&(document.hidden?this.#i():this.requestFrame())}};var I=class{#e;#t;#i=0;#r;#s=0;constructor(e,t,r){this.#e=e,this.#t=t,this.#r=r}register(e){return e==="add"?this.#s=setTimeout(()=>{this.#r(),this.#i=setInterval(this.#r,this.#t)},this.#e()):(clearTimeout(this.#s),clearInterval(this.#i)),this}[Symbol.dispose](){this.register("remove")}};var U=class{cam=new X;canvas;input;preload;renderer;sprites;zoo=new M;looper=new F;#e;#t;#i=new ResizeObserver(()=>this.onResize());constructor(e){e.poll!=null&&(this.#e=new I(e.poll.delay??(()=>0),e.poll.period,()=>this.onPoll())),fe(),this.canvas=ye(e.canvas,e.mode??"Int"),ce(this.canvas,e.backgroundRGBA??255),e.minWH&&(this.cam.minWH=e.minWH),this.cam.mode=e.mode??"Int",this.cam.update(this.canvas),this.input=new O(this.cam,this.canvas),e.input!=="Custom"&&this.input.mapDefault(),this.input.onEvent=()=>this.onEvent(),e.preloadAtlas&&(this.#t=e.preloadAtlas.image),this.preload=e.preloadAtlas?me(e.preloadAtlas.json):{anim:{},celXYWH:[],tags:[]},this.renderer=new D(this.preload??{},this.canvas,this.looper),this.sprites=new E({alloc:t=>this.onAllocSprite(t),allocBytes:c,minPages:e.sprites?.minPages??3,pageBlocks:e.sprites?.pageBlocks??1e3}),this.looper.onFrame=t=>this.onFrame(t)}onAllocSprite(e){return new T(e,0,this.preload,this.looper)}onEvent(){this.requestFrame("Force")}onFrame(e){document.hidden||(this.input.update(e),this.requestFrame(),this.onLoop(e),this.cam.postupdate())}onLoop(e){}onPoll(){this.requestFrame("Force")}onResize(){this.requestFrame("Force")}async register(e){if(this.input.register(e),this.renderer.register(e),this.looper.register(e),!this.canvas.parentElement)throw Error("no canvas parent");e==="add"?this.#i.observe(this.canvas.parentElement):this.#i.unobserve(this.canvas.parentElement),e==="add"&&this.looper.requestFrame(),this.#e?.register(e),this.#t&&await xe(this.#t),this.renderer.load(this.#t)}requestFrame(e){(e||this.renderer.always||this.input.anyOn||this.input.gamepad)&&this.looper.requestFrame()}async[Symbol.asyncDispose](){await this.register("remove")}};var Ee=_?`${_.version}+${_.published}`:"?";var Se={anim:{"background--OrangeCheckerboard":{cels:1,h:2,id:0,w:2},"background--GreyCheckerboard":{cels:1,h:2,id:1,w:2},"background--Kiwi":{cels:1,h:2,id:2,w:2},"background--Strawberry":{cels:1,h:2,id:3,w:2},"background--Grape":{cels:1,h:2,id:4,w:2},"background--Blueberry":{cels:1,h:2,id:5,w:2},"background--Bubblegum":{cels:1,h:2,id:6,w:2},"background--Transparent":{cels:1,h:2,id:7,w:2},"background--Black":{cels:1,h:2,id:8,w:2},"backpacker--WalkRight":{cels:16,h:13,hitbox:{x:2,y:0,w:4,h:4},id:9,w:8},"backpacker--WalkDown":{cels:16,h:13,hitbox:{x:2,y:0,w:4,h:4},id:10,w:8},"backpacker--WalkUp":{cels:16,h:13,hitbox:{x:2,y:0,w:4,h:4},id:11,w:8},"cursor--Pointer":{cels:1,h:14,hitbox:{x:0,y:0,w:2,h:2},hurtbox:{x:0,y:0,w:2,h:2},id:12,w:8},"mem-prop-5x6--00":{cels:1,h:6,id:13,w:5},"mem-prop-5x6--01":{cels:1,h:6,id:14,w:5},"mem-prop-5x6--02":{cels:1,h:6,id:15,w:5},"mem-prop-5x6--03":{cels:1,h:6,id:16,w:5},"mem-prop-5x6--04":{cels:1,h:6,id:17,w:5},"mem-prop-5x6--05":{cels:1,h:6,id:18,w:5},"mem-prop-5x6--06":{cels:1,h:6,id:19,w:5},"mem-prop-5x6--07":{cels:1,h:6,id:20,w:5},"mem-prop-5x6--08":{cels:1,h:6,id:21,w:5},"mem-prop-5x6--09":{cels:1,h:6,id:22,w:5},"mem-prop-5x6--0a":{cels:1,h:6,id:23,w:5},"mem-prop-5x6--0b":{cels:1,h:6,id:24,w:5},"mem-prop-5x6--0c":{cels:1,h:6,id:25,w:5},"mem-prop-5x6--0d":{cels:1,h:6,id:26,w:5},"mem-prop-5x6--0e":{cels:1,h:6,id:27,w:5},"mem-prop-5x6--0f":{cels:1,h:6,id:28,w:5},"mem-prop-5x6--10":{cels:1,h:6,id:29,w:5},"mem-prop-5x6--11":{cels:1,h:6,id:30,w:5},"mem-prop-5x6--12":{cels:1,h:6,id:31,w:5},"mem-prop-5x6--13":{cels:1,h:6,id:32,w:5},"mem-prop-5x6--14":{cels:1,h:6,id:33,w:5},"mem-prop-5x6--15":{cels:1,h:6,id:34,w:5},"mem-prop-5x6--16":{cels:1,h:6,id:35,w:5},"mem-prop-5x6--17":{cels:1,h:6,id:36,w:5},"mem-prop-5x6--18":{cels:1,h:6,id:37,w:5},"mem-prop-5x6--19":{cels:1,h:6,id:38,w:5},"mem-prop-5x6--1a":{cels:1,h:6,id:39,w:5},"mem-prop-5x6--1b":{cels:1,h:6,id:40,w:5},"mem-prop-5x6--1c":{cels:1,h:6,id:41,w:5},"mem-prop-5x6--1d":{cels:1,h:6,id:42,w:5},"mem-prop-5x6--1e":{cels:1,h:6,id:43,w:5},"mem-prop-5x6--1f":{cels:1,h:6,id:44,w:5},"mem-prop-5x6--20":{cels:1,h:6,id:45,w:5},"mem-prop-5x6--21":{cels:1,h:6,id:46,w:5},"mem-prop-5x6--22":{cels:1,h:6,id:47,w:5},"mem-prop-5x6--23":{cels:1,h:6,id:48,w:5},"mem-prop-5x6--24":{cels:1,h:6,id:49,w:5},"mem-prop-5x6--25":{cels:1,h:6,id:50,w:5},"mem-prop-5x6--26":{cels:1,h:6,id:51,w:5},"mem-prop-5x6--27":{cels:1,h:6,id:52,w:5},"mem-prop-5x6--28":{cels:1,h:6,id:53,w:5},"mem-prop-5x6--29":{cels:1,h:6,id:54,w:5},"mem-prop-5x6--2a":{cels:1,h:6,id:55,w:5},"mem-prop-5x6--2b":{cels:1,h:6,id:56,w:5},"mem-prop-5x6--2c":{cels:1,h:6,id:57,w:5},"mem-prop-5x6--2d":{cels:1,h:6,id:58,w:5},"mem-prop-5x6--2e":{cels:1,h:6,id:59,w:5},"mem-prop-5x6--2f":{cels:1,h:6,id:60,w:5},"mem-prop-5x6--30":{cels:1,h:6,id:61,w:5},"mem-prop-5x6--31":{cels:1,h:6,id:62,w:5},"mem-prop-5x6--32":{cels:1,h:6,id:63,w:5},"mem-prop-5x6--33":{cels:1,h:6,id:64,w:5},"mem-prop-5x6--34":{cels:1,h:6,id:65,w:5},"mem-prop-5x6--35":{cels:1,h:6,id:66,w:5},"mem-prop-5x6--36":{cels:1,h:6,id:67,w:5},"mem-prop-5x6--37":{cels:1,h:6,id:68,w:5},"mem-prop-5x6--38":{cels:1,h:6,id:69,w:5},"mem-prop-5x6--39":{cels:1,h:6,id:70,w:5},"mem-prop-5x6--3a":{cels:1,h:6,id:71,w:5},"mem-prop-5x6--3b":{cels:1,h:6,id:72,w:5},"mem-prop-5x6--3c":{cels:1,h:6,id:73,w:5},"mem-prop-5x6--3d":{cels:1,h:6,id:74,w:5},"mem-prop-5x6--3e":{cels:1,h:6,id:75,w:5},"mem-prop-5x6--3f":{cels:1,h:6,id:76,w:5},"mem-prop-5x6--40":{cels:1,h:6,id:77,w:5},"mem-prop-5x6--41":{cels:1,h:6,id:78,w:5},"mem-prop-5x6--42":{cels:1,h:6,id:79,w:5},"mem-prop-5x6--43":{cels:1,h:6,id:80,w:5},"mem-prop-5x6--44":{cels:1,h:6,id:81,w:5},"mem-prop-5x6--45":{cels:1,h:6,id:82,w:5},"mem-prop-5x6--46":{cels:1,h:6,id:83,w:5},"mem-prop-5x6--47":{cels:1,h:6,id:84,w:5},"mem-prop-5x6--48":{cels:1,h:6,id:85,w:5},"mem-prop-5x6--49":{cels:1,h:6,id:86,w:5},"mem-prop-5x6--4a":{cels:1,h:6,id:87,w:5},"mem-prop-5x6--4b":{cels:1,h:6,id:88,w:5},"mem-prop-5x6--4c":{cels:1,h:6,id:89,w:5},"mem-prop-5x6--4d":{cels:1,h:6,id:90,w:5},"mem-prop-5x6--4e":{cels:1,h:6,id:91,w:5},"mem-prop-5x6--4f":{cels:1,h:6,id:92,w:5},"mem-prop-5x6--50":{cels:1,h:6,id:93,w:5},"mem-prop-5x6--51":{cels:1,h:6,id:94,w:5},"mem-prop-5x6--52":{cels:1,h:6,id:95,w:5},"mem-prop-5x6--53":{cels:1,h:6,id:96,w:5},"mem-prop-5x6--54":{cels:1,h:6,id:97,w:5},"mem-prop-5x6--55":{cels:1,h:6,id:98,w:5},"mem-prop-5x6--56":{cels:1,h:6,id:99,w:5},"mem-prop-5x6--57":{cels:1,h:6,id:100,w:5},"mem-prop-5x6--58":{cels:1,h:6,id:101,w:5},"mem-prop-5x6--59":{cels:1,h:6,id:102,w:5},"mem-prop-5x6--5a":{cels:1,h:6,id:103,w:5},"mem-prop-5x6--5b":{cels:1,h:6,id:104,w:5},"mem-prop-5x6--5c":{cels:1,h:6,id:105,w:5},"mem-prop-5x6--5d":{cels:1,h:6,id:106,w:5},"mem-prop-5x6--5e":{cels:1,h:6,id:107,w:5},"mem-prop-5x6--5f":{cels:1,h:6,id:108,w:5},"mem-prop-5x6--60":{cels:1,h:6,id:109,w:5},"mem-prop-5x6--61":{cels:1,h:6,id:110,w:5},"mem-prop-5x6--62":{cels:1,h:6,id:111,w:5},"mem-prop-5x6--63":{cels:1,h:6,id:112,w:5},"mem-prop-5x6--64":{cels:1,h:6,id:113,w:5},"mem-prop-5x6--65":{cels:1,h:6,id:114,w:5},"mem-prop-5x6--66":{cels:1,h:6,id:115,w:5},"mem-prop-5x6--67":{cels:1,h:6,id:116,w:5},"mem-prop-5x6--68":{cels:1,h:6,id:117,w:5},"mem-prop-5x6--69":{cels:1,h:6,id:118,w:5},"mem-prop-5x6--6a":{cels:1,h:6,id:119,w:5},"mem-prop-5x6--6b":{cels:1,h:6,id:120,w:5},"mem-prop-5x6--6c":{cels:1,h:6,id:121,w:5},"mem-prop-5x6--6d":{cels:1,h:6,id:122,w:5},"mem-prop-5x6--6e":{cels:1,h:6,id:123,w:5},"mem-prop-5x6--6f":{cels:1,h:6,id:124,w:5},"mem-prop-5x6--70":{cels:1,h:6,id:125,w:5},"mem-prop-5x6--71":{cels:1,h:6,id:126,w:5},"mem-prop-5x6--72":{cels:1,h:6,id:127,w:5},"mem-prop-5x6--73":{cels:1,h:6,id:128,w:5},"mem-prop-5x6--74":{cels:1,h:6,id:129,w:5},"mem-prop-5x6--75":{cels:1,h:6,id:130,w:5},"mem-prop-5x6--76":{cels:1,h:6,id:131,w:5},"mem-prop-5x6--77":{cels:1,h:6,id:132,w:5},"mem-prop-5x6--78":{cels:1,h:6,id:133,w:5},"mem-prop-5x6--79":{cels:1,h:6,id:134,w:5},"mem-prop-5x6--7a":{cels:1,h:6,id:135,w:5},"mem-prop-5x6--7b":{cels:1,h:6,id:136,w:5},"mem-prop-5x6--7c":{cels:1,h:6,id:137,w:5},"mem-prop-5x6--7d":{cels:1,h:6,id:138,w:5},"mem-prop-5x6--7e":{cels:1,h:6,id:139,w:5},"mem-prop-5x6--7f":{cels:1,h:6,id:140,w:5},"oidoid--Default":{cels:1,h:16,id:141,w:16}},celXY:[22,37,21,27,21,29,21,31,20,33,22,33,20,35,22,35,20,37,24,26,24,26,8,16,8,16,0,16,0,16,16,14,16,14,72,13,72,13,32,26,32,26,0,16,0,16,64,13,64,13,56,13,56,13,48,13,48,13,40,13,40,13,32,13,32,13,56,13,56,13,24,13,24,13,72,0,72,0,64,0,64,0,24,0,24,0,56,0,56,0,48,0,48,0,48,0,48,0,24,0,24,0,40,0,40,0,32,0,32,0,32,0,32,0,16,0,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,45,56,40,56,10,53,5,53,0,53,35,51,30,51,25,51,20,51,15,51,35,45,70,50,65,50,60,50,55,50,50,50,45,50,40,50,10,47,5,47,0,47,70,62,50,56,65,62,60,62,55,62,50,62,45,62,40,62,10,59,5,59,0,59,35,57,70,32,30,57,25,57,20,57,15,57,75,56,70,56,65,56,60,56,75,50,55,56,10,35,75,32,15,33,0,35,5,35,40,38,45,38,65,32,60,32,55,32,50,32,45,32,40,26,50,26,55,26,60,26,65,26,70,26,75,26,16,27,0,29,5,29,10,29,40,32,45,26,10,41,30,45,25,45,20,45,15,45,75,44,70,44,65,44,60,44,55,44,50,44,45,44,40,44,50,38,5,41,0,41,35,39,30,39,25,39,20,39,15,39,75,38,70,38,65,38,60,38,55,38,45,56,0,0]};var V=class{#e=new y;constructor(){this.#e.scale=3,this.#e.z=h.A}free(e){this.#e.free(e)}update(e){let t=new Date;return this.#e.text=De(t),(this.#e.layout(e)||e.cam.invalid)&&(this.#e.xy=e.cam.follow({w:this.#e.wh.w,h:this.#e.wh.h-this.#e.scaledLeading},this.#e.z,"N",{margin:{h:8}})),this.#e.update(e)}};function De(i){let e=`${i.getHours()%12||12}`.padStart(2," "),t=`${i.getMinutes()}`.padStart(2,"0"),r=`${i.getSeconds()}`.padStart(2,"0");return`${e}:${t}:${r}`}var q=class{#e;constructor(e){this.#e=new Y(e,{button:{w:{tag:"background--Strawberry"},nw:{tag:"background--Transparent"},n:{tag:"background--Bubblegum"},e:{tag:"background--Blueberry"},s:{tag:"background--Kiwi"},origin:{tag:"background--Grape"},border:{n:1},margin:{w:2,h:2}},selected:{tag:"background--OrangeCheckerboard"},toggle:!0,text:{text:"render",scale:2},w:64,h:22,x:50,y:25,pressed:{tag:"background--Bubblegum"}})}get on(){return this.#e.on}set on(e){this.#e.on=e}free(e){this.#e.free(e)}update(e){return this.#e.update(e)}};var G=class{#e=new y;#t=0;constructor(){this.#e.z=h.A}free(e){this.#e.free(e)}update(e){this.#t++,this.#e.text=`${this.#t} updates
97
+ ${e.renderer.clears+1} renders`,this.#e.layout(e),this.#e.xy=e.cam.follow({w:this.#e.wh.w,h:this.#e.wh.h-this.#e.scaledLeading},this.#e.z,"NE",{margin:{w:8,h:8}}),this.#e.update(e)}};var N=class extends U{#e;#t;#i;constructor(){super({preloadAtlas:{image:document.querySelector("#preload-atlas"),json:Se},backgroundRGBA:4294947327,minWH:{w:320,h:240},poll:{delay:()=>Fe(new Date,l?.seconds),period:(l?.seconds?1:60)*1e3}}),this.#e=new E({alloc:e=>new T(e,0,this.preload,this.looper),allocBytes:c,pageBlocks:10}),this.#t=new q(this),this.#t.on=this.renderer.always,this.#i=new G,this.#r()}onLoop(e){l?.input&&this.#s(),this.renderer.always=this.#t.on;let t=this.#n();this.zoo.update(this),t||=this.zoo.invalid||this.cam.invalid||this.renderer.invalid||this.renderer.always,t&&(this.renderer.clear(4294947327),this.renderer.predraw(this.cam),this.renderer.setDepth(!0),this.renderer.draw(this.sprites),this.renderer.setDepth(!1),this.renderer.draw(this.#e))}#r(){let e=new b(this,{n:{tag:"background--Black"},origin:{tag:"background--Transparent"},border:{n:1},z:h.UIA});this.zoo.add(e);let t=this.cam.follow({w:0,h:0},h.UIA,"NW",{fill:"XY"});e.xy=t,e.wh=t;let r=this.sprites.alloc();r.tag="backpacker--WalkRight",r.x=7,r.y=7,r.z=h.C,r.stretch=!0,r.w*=5,r.h*=5;let n=new A(this,"oidoid--Default","SW");n.z=h.UIG,n.margin={w:4,h:4},this.zoo.add(new v(this,"cursor--Pointer"),this.#t,new V,this.#i,n);let s=this.#e.alloc();s.tag="background--GreyCheckerboard",s.w=K.w,s.h=K.h,s.z=h.UIA}#s(){if(this.input.started){let e=!!this.input.on.length;console.debug(e?`[input] buttons on: ${this.input.on.join(" ")}.`:"[input] buttons off.");let t=this.input.combo;t.length>1&&e&&console.debug(`[input] combo: ${t.map(r=>r.join("+")).join(" ")}.`)}this.input.point?.invalid&&this.input.point?.click&&!this.input.point.pinch&&console.debug(`[input] ${this.input.point.drag.on?"drag":"click"} xy: ${this.input.point.x} ${this.input.point.y}.`),this.input.point?.pinch&&console.debug(`[input] pinch xy: ${this.input.point.pinch.xy.x} ${this.input.point.pinch.xy.y}.`),this.input.wheel&&console.debug(`[input] wheel xy: ${this.input.wheel.delta.xy.x} ${this.input.wheel.delta.xy.y}.`)}#n(){let e=this.input.isAnyOn("L","R","U","D");this.input.isAnyOnStart("L","R","U","D")&&(this.cam.x=Math.trunc(this.cam.x),this.cam.y=Math.trunc(this.cam.y));let t=1/4;return this.input.isOn("L")&&(this.cam.x-=t),this.input.isOn("R")&&(this.cam.x+=t),this.input.isOn("U")&&(this.cam.y-=t),this.input.isOn("D")&&(this.cam.y+=t),this.input.wheel?.delta.xy.y&&(e=!0,this.cam.zoomOut-=this.input.wheel.delta.client.y*.01),this.cam.update(this.canvas),e}};function Fe(i,e){return((e?0:(59-i.getSeconds()%60)*1e3)+1e3-i.getMilliseconds()%1e3)%(e?1e3:6e4)}console.debug(`void v${Ee} \u2500\u2500\u2500oidoid>\xB0\u2500\u2500`);var Ce=new N;await Ce.register("add");l&&(globalThis.v=Ce);
3844
98
  //# sourceMappingURL=index.js.map