@holoscript/engine 6.0.3 → 6.0.4

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 (192) hide show
  1. package/dist/AutoMesher-CK47F6AV.js +17 -0
  2. package/dist/GPUBuffers-2LHBCD7X.js +9 -0
  3. package/dist/WebGPUContext-TNEUYU2Y.js +11 -0
  4. package/dist/animation/index.cjs +38 -38
  5. package/dist/animation/index.d.cts +1 -1
  6. package/dist/animation/index.d.ts +1 -1
  7. package/dist/animation/index.js +1 -1
  8. package/dist/audio/index.cjs +16 -6
  9. package/dist/audio/index.d.cts +1 -1
  10. package/dist/audio/index.d.ts +1 -1
  11. package/dist/audio/index.js +1 -1
  12. package/dist/camera/index.cjs +23 -23
  13. package/dist/camera/index.d.cts +1 -1
  14. package/dist/camera/index.d.ts +1 -1
  15. package/dist/camera/index.js +1 -1
  16. package/dist/character/index.cjs +6 -4
  17. package/dist/character/index.js +1 -1
  18. package/dist/choreography/index.cjs +1194 -0
  19. package/dist/choreography/index.d.cts +687 -0
  20. package/dist/choreography/index.d.ts +687 -0
  21. package/dist/choreography/index.js +1156 -0
  22. package/dist/chunk-2CSNRI2N.js +217 -0
  23. package/dist/chunk-33T2WINR.js +266 -0
  24. package/dist/chunk-35R73OFM.js +1257 -0
  25. package/dist/chunk-4MMDSUNP.js +1256 -0
  26. package/dist/chunk-5V6HOU72.js +319 -0
  27. package/dist/chunk-6QOP6PYF.js +1038 -0
  28. package/dist/chunk-7KMJVHIL.js +8944 -0
  29. package/dist/chunk-7VPUC62U.js +1106 -0
  30. package/dist/chunk-A2Y6RCAT.js +1878 -0
  31. package/dist/chunk-AHM42MK6.js +8944 -0
  32. package/dist/chunk-BL7IDTHE.js +218 -0
  33. package/dist/chunk-CITOMSWL.js +10462 -0
  34. package/dist/chunk-CXDPKW2K.js +8944 -0
  35. package/dist/chunk-CXZPLD4S.js +223 -0
  36. package/dist/chunk-CZYJE7IH.js +5169 -0
  37. package/dist/chunk-D2OP7YC7.js +6325 -0
  38. package/dist/chunk-EDRVQHUU.js +1544 -0
  39. package/dist/chunk-EJSLOOW2.js +3589 -0
  40. package/dist/chunk-F53SFGW5.js +1878 -0
  41. package/dist/chunk-HCFPELPY.js +919 -0
  42. package/dist/chunk-HNEE36PY.js +93 -0
  43. package/dist/chunk-HYXNV36F.js +1256 -0
  44. package/dist/chunk-IB7KHVFY.js +821 -0
  45. package/dist/chunk-IBBO7YYG.js +690 -0
  46. package/dist/chunk-ILIBGINU.js +5470 -0
  47. package/dist/chunk-IS4MHLKN.js +5479 -0
  48. package/dist/chunk-JT2PFKWD.js +5479 -0
  49. package/dist/chunk-K4CUB4NY.js +1038 -0
  50. package/dist/chunk-KATDQXRJ.js +10462 -0
  51. package/dist/chunk-KBQE6ZFJ.js +8944 -0
  52. package/dist/chunk-KBVD5K7E.js +560 -0
  53. package/dist/chunk-KCDPVQRY.js +4088 -0
  54. package/dist/chunk-KN4QJPKN.js +8944 -0
  55. package/dist/chunk-KWJ3ROSI.js +8944 -0
  56. package/dist/chunk-L45VF6DD.js +919 -0
  57. package/dist/chunk-LY4T37YK.js +307 -0
  58. package/dist/chunk-MDN5WZXA.js +1544 -0
  59. package/dist/chunk-MGCDP6VU.js +928 -0
  60. package/dist/chunk-NCX7X6G2.js +8681 -0
  61. package/dist/chunk-OF54BPVD.js +913 -0
  62. package/dist/chunk-OWSN2Q3Q.js +690 -0
  63. package/dist/chunk-PRRB5TTA.js +406 -0
  64. package/dist/chunk-PXWVQF76.js +4086 -0
  65. package/dist/chunk-PYCOIDT2.js +812 -0
  66. package/dist/chunk-PZCSADOV.js +928 -0
  67. package/dist/chunk-Q2XBVS2K.js +1038 -0
  68. package/dist/chunk-QDZRXWN5.js +1776 -0
  69. package/dist/chunk-RNWOZ6WQ.js +913 -0
  70. package/dist/chunk-ROLFT4CJ.js +1693 -0
  71. package/dist/chunk-SLTJRZ2N.js +266 -0
  72. package/dist/chunk-SRUS5XSU.js +4088 -0
  73. package/dist/chunk-TKCA3WZ5.js +5409 -0
  74. package/dist/chunk-TNRMXYI2.js +1650 -0
  75. package/dist/chunk-TQB3GJGM.js +9763 -0
  76. package/dist/chunk-TUFGXG6K.js +510 -0
  77. package/dist/chunk-U6KMTGQJ.js +632 -0
  78. package/dist/chunk-VMGJQST6.js +8681 -0
  79. package/dist/chunk-X4F4TCG4.js +5470 -0
  80. package/dist/chunk-ZIFROE75.js +1544 -0
  81. package/dist/chunk-ZIJQYHSQ.js +1204 -0
  82. package/dist/combat/index.cjs +4 -4
  83. package/dist/combat/index.d.cts +1 -1
  84. package/dist/combat/index.d.ts +1 -1
  85. package/dist/combat/index.js +1 -1
  86. package/dist/ecs/index.cjs +1 -1
  87. package/dist/ecs/index.js +1 -1
  88. package/dist/environment/index.cjs +14 -14
  89. package/dist/environment/index.d.cts +1 -1
  90. package/dist/environment/index.d.ts +1 -1
  91. package/dist/environment/index.js +1 -1
  92. package/dist/gpu/index.cjs +4810 -0
  93. package/dist/gpu/index.js +3714 -0
  94. package/dist/hologram/index.cjs +27 -1
  95. package/dist/hologram/index.js +1 -1
  96. package/dist/index-B2PIsAmR.d.cts +2180 -0
  97. package/dist/index-B2PIsAmR.d.ts +2180 -0
  98. package/dist/index-BHySEPX7.d.cts +2921 -0
  99. package/dist/index-BJV21zuy.d.cts +341 -0
  100. package/dist/index-BJV21zuy.d.ts +341 -0
  101. package/dist/index-BQutTphC.d.cts +790 -0
  102. package/dist/index-ByIq2XrS.d.cts +3910 -0
  103. package/dist/index-BysHjDSO.d.cts +224 -0
  104. package/dist/index-BysHjDSO.d.ts +224 -0
  105. package/dist/index-CKwAJGck.d.ts +455 -0
  106. package/dist/index-CUl3QstQ.d.cts +3006 -0
  107. package/dist/index-CUl3QstQ.d.ts +3006 -0
  108. package/dist/index-CmYtNiI-.d.cts +953 -0
  109. package/dist/index-CmYtNiI-.d.ts +953 -0
  110. package/dist/index-CnRzWxi_.d.cts +522 -0
  111. package/dist/index-CnRzWxi_.d.ts +522 -0
  112. package/dist/index-CwRWbSC7.d.ts +2921 -0
  113. package/dist/index-CxKIBstO.d.ts +790 -0
  114. package/dist/index-DJ6-R8vh.d.cts +455 -0
  115. package/dist/index-DQKisbcI.d.cts +4968 -0
  116. package/dist/index-DQKisbcI.d.ts +4968 -0
  117. package/dist/index-DRT2zJez.d.ts +3910 -0
  118. package/dist/index-DfNLiAka.d.cts +192 -0
  119. package/dist/index-DfNLiAka.d.ts +192 -0
  120. package/dist/index-nMvkoRm8.d.cts +405 -0
  121. package/dist/index-nMvkoRm8.d.ts +405 -0
  122. package/dist/index-s9yOFU37.d.cts +604 -0
  123. package/dist/index-s9yOFU37.d.ts +604 -0
  124. package/dist/index.cjs +22966 -6960
  125. package/dist/index.d.cts +864 -20
  126. package/dist/index.d.ts +864 -20
  127. package/dist/index.js +3062 -48
  128. package/dist/input/index.cjs +1 -1
  129. package/dist/input/index.js +1 -1
  130. package/dist/orbital/index.cjs +3 -3
  131. package/dist/orbital/index.d.cts +1 -1
  132. package/dist/orbital/index.d.ts +1 -1
  133. package/dist/orbital/index.js +1 -1
  134. package/dist/particles/index.cjs +16 -16
  135. package/dist/particles/index.d.cts +1 -1
  136. package/dist/particles/index.d.ts +1 -1
  137. package/dist/particles/index.js +1 -1
  138. package/dist/physics/index.cjs +2377 -21
  139. package/dist/physics/index.d.cts +1 -1
  140. package/dist/physics/index.d.ts +1 -1
  141. package/dist/physics/index.js +35 -1
  142. package/dist/postfx/index.cjs +3491 -0
  143. package/dist/postfx/index.js +93 -0
  144. package/dist/procedural/index.cjs +1 -1
  145. package/dist/procedural/index.js +1 -1
  146. package/dist/puppeteer-5VF6KDVO.js +52197 -0
  147. package/dist/puppeteer-IZVZ3SG4.js +52197 -0
  148. package/dist/rendering/index.cjs +33 -32
  149. package/dist/rendering/index.d.cts +1 -1
  150. package/dist/rendering/index.d.ts +1 -1
  151. package/dist/rendering/index.js +8 -6
  152. package/dist/runtime/index.cjs +23 -13
  153. package/dist/runtime/index.d.cts +1 -1
  154. package/dist/runtime/index.d.ts +1 -1
  155. package/dist/runtime/index.js +8 -6
  156. package/dist/runtime/protocols/index.cjs +349 -0
  157. package/dist/runtime/protocols/index.js +15 -0
  158. package/dist/scene/index.cjs +8 -8
  159. package/dist/scene/index.d.cts +1 -1
  160. package/dist/scene/index.d.ts +1 -1
  161. package/dist/scene/index.js +1 -1
  162. package/dist/shader/index.cjs +3087 -0
  163. package/dist/shader/index.js +3044 -0
  164. package/dist/simulation/index.cjs +10680 -0
  165. package/dist/simulation/index.d.cts +3 -0
  166. package/dist/simulation/index.d.ts +3 -0
  167. package/dist/simulation/index.js +307 -0
  168. package/dist/spatial/index.cjs +2443 -0
  169. package/dist/spatial/index.d.cts +1545 -0
  170. package/dist/spatial/index.d.ts +1545 -0
  171. package/dist/spatial/index.js +2400 -0
  172. package/dist/terrain/index.cjs +1 -1
  173. package/dist/terrain/index.d.cts +1 -1
  174. package/dist/terrain/index.d.ts +1 -1
  175. package/dist/terrain/index.js +1 -1
  176. package/dist/transformers.node-4NKAPD5U.js +45620 -0
  177. package/dist/vm/index.cjs +7 -8
  178. package/dist/vm/index.d.cts +1 -1
  179. package/dist/vm/index.d.ts +1 -1
  180. package/dist/vm/index.js +1 -1
  181. package/dist/vm-bridge/index.cjs +2 -2
  182. package/dist/vm-bridge/index.d.cts +2 -2
  183. package/dist/vm-bridge/index.d.ts +2 -2
  184. package/dist/vm-bridge/index.js +1 -1
  185. package/dist/vr/index.cjs +6 -6
  186. package/dist/vr/index.js +1 -1
  187. package/dist/world/index.cjs +3 -3
  188. package/dist/world/index.d.cts +1 -1
  189. package/dist/world/index.d.ts +1 -1
  190. package/dist/world/index.js +1 -1
  191. package/package.json +53 -21
  192. package/LICENSE +0 -21
@@ -0,0 +1,632 @@
1
+ import {
2
+ __export
3
+ } from "./chunk-AKLW2MUS.js";
4
+
5
+ // src/input/index.ts
6
+ var input_exports = {};
7
+ __export(input_exports, {
8
+ GestureRecognizer: () => GestureRecognizer,
9
+ InputBindings: () => InputBindings,
10
+ InputManager: () => InputManager
11
+ });
12
+
13
+ // src/input/GestureRecognizer.ts
14
+ var _gestureSubId = 0;
15
+ var DEFAULT_CONFIG = {
16
+ tapMaxDuration: 300,
17
+ tapMaxDistance: 10,
18
+ doubleTapWindow: 400,
19
+ longPressMinDuration: 500,
20
+ swipeMinDistance: 50,
21
+ swipeMinVelocity: 0.3,
22
+ pinchMinScale: 0.05
23
+ };
24
+ var GestureRecognizer = class {
25
+ config;
26
+ activeTouches = /* @__PURE__ */ new Map();
27
+ touchStarts = /* @__PURE__ */ new Map();
28
+ // Original positions
29
+ subscribers = /* @__PURE__ */ new Map();
30
+ lastTapTime = 0;
31
+ lastTapPosition = { x: 0, y: 0 };
32
+ longPressTimer = null;
33
+ gestureHistory = [];
34
+ initialPinchDistance = 0;
35
+ constructor(config) {
36
+ this.config = { ...DEFAULT_CONFIG, ...config };
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Subscription
40
+ // ---------------------------------------------------------------------------
41
+ on(types, callback) {
42
+ const id = `gsub_${_gestureSubId++}`;
43
+ const typeArr = Array.isArray(types) ? types : [types];
44
+ this.subscribers.set(id, { types: typeArr, callback });
45
+ return id;
46
+ }
47
+ off(subscriptionId) {
48
+ this.subscribers.delete(subscriptionId);
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Touch Events
52
+ // ---------------------------------------------------------------------------
53
+ touchStart(id, x, y) {
54
+ const now = Date.now();
55
+ this.activeTouches.set(id, { id, x, y, timestamp: now });
56
+ this.touchStarts.set(id, { id, x, y, timestamp: now });
57
+ if (this.activeTouches.size === 1) {
58
+ this.longPressTimer = setTimeout(() => {
59
+ const touch = this.activeTouches.get(id);
60
+ if (touch) {
61
+ this.emit({
62
+ type: "longPress",
63
+ position: { x: touch.x, y: touch.y },
64
+ timestamp: Date.now()
65
+ });
66
+ }
67
+ }, this.config.longPressMinDuration);
68
+ }
69
+ if (this.activeTouches.size === 2) {
70
+ this.cancelLongPress();
71
+ const points = [...this.activeTouches.values()];
72
+ this.initialPinchDistance = this.distance(points[0], points[1]);
73
+ }
74
+ }
75
+ touchMove(id, x, y) {
76
+ const touch = this.activeTouches.get(id);
77
+ if (!touch) return;
78
+ const dx = x - touch.x;
79
+ const dy = y - touch.y;
80
+ if (Math.sqrt(dx * dx + dy * dy) > this.config.tapMaxDistance) {
81
+ this.cancelLongPress();
82
+ }
83
+ if (this.activeTouches.size === 1) {
84
+ this.emit({
85
+ type: "pan",
86
+ position: { x, y },
87
+ timestamp: Date.now(),
88
+ deltaX: x - touch.x,
89
+ deltaY: y - touch.y
90
+ });
91
+ }
92
+ if (this.activeTouches.size === 2) {
93
+ const oldX = touch.x, oldY = touch.y;
94
+ touch.x = x;
95
+ touch.y = y;
96
+ const points = [...this.activeTouches.values()];
97
+ const currentDist = this.distance(points[0], points[1]);
98
+ if (this.initialPinchDistance > 0) {
99
+ const scale = currentDist / this.initialPinchDistance;
100
+ if (Math.abs(scale - 1) >= this.config.pinchMinScale) {
101
+ this.emit({
102
+ type: "pinch",
103
+ position: {
104
+ x: (points[0].x + points[1].x) / 2,
105
+ y: (points[0].y + points[1].y) / 2
106
+ },
107
+ timestamp: Date.now(),
108
+ scale
109
+ });
110
+ }
111
+ }
112
+ touch.x = oldX;
113
+ touch.y = oldY;
114
+ }
115
+ touch.x = x;
116
+ touch.y = y;
117
+ }
118
+ touchEnd(id, x, y) {
119
+ const touch = this.activeTouches.get(id);
120
+ const startTouch = this.touchStarts.get(id);
121
+ if (!touch || !startTouch) return;
122
+ this.cancelLongPress();
123
+ const now = Date.now();
124
+ const duration = Math.max(1, now - startTouch.timestamp);
125
+ const totalDx = x - startTouch.x;
126
+ const totalDy = y - startTouch.y;
127
+ const totalDist = Math.sqrt(totalDx * totalDx + totalDy * totalDy);
128
+ this.activeTouches.delete(id);
129
+ this.touchStarts.delete(id);
130
+ if (totalDist >= this.config.swipeMinDistance) {
131
+ const velocity = totalDist / duration;
132
+ if (velocity >= this.config.swipeMinVelocity) {
133
+ this.emit({
134
+ type: "swipe",
135
+ position: { x, y },
136
+ timestamp: now,
137
+ direction: this.getSwipeDirection(totalDx, totalDy),
138
+ velocity,
139
+ distance: totalDist
140
+ });
141
+ return;
142
+ }
143
+ }
144
+ if (duration <= this.config.tapMaxDuration && totalDist <= this.config.tapMaxDistance) {
145
+ const timeSinceLastTap = now - this.lastTapTime;
146
+ const distFromLastTap = Math.sqrt(
147
+ (x - this.lastTapPosition.x) ** 2 + (y - this.lastTapPosition.y) ** 2
148
+ );
149
+ if (timeSinceLastTap <= this.config.doubleTapWindow && distFromLastTap <= this.config.tapMaxDistance * 2) {
150
+ this.emit({ type: "doubleTap", position: { x, y }, timestamp: now });
151
+ this.lastTapTime = 0;
152
+ } else {
153
+ this.emit({ type: "tap", position: { x, y }, timestamp: now });
154
+ this.lastTapTime = now;
155
+ this.lastTapPosition = { x, y };
156
+ }
157
+ }
158
+ }
159
+ // ---------------------------------------------------------------------------
160
+ // Helpers
161
+ // ---------------------------------------------------------------------------
162
+ emit(event) {
163
+ this.gestureHistory.push(event);
164
+ if (this.gestureHistory.length > 100) this.gestureHistory.shift();
165
+ for (const sub of this.subscribers.values()) {
166
+ if (sub.types.includes(event.type) || sub.types.includes("custom")) {
167
+ sub.callback(event);
168
+ }
169
+ }
170
+ }
171
+ cancelLongPress() {
172
+ if (this.longPressTimer) {
173
+ clearTimeout(this.longPressTimer);
174
+ this.longPressTimer = null;
175
+ }
176
+ }
177
+ getSwipeDirection(dx, dy) {
178
+ if (Math.abs(dx) > Math.abs(dy)) {
179
+ return dx > 0 ? "right" : "left";
180
+ }
181
+ return dy > 0 ? "down" : "up";
182
+ }
183
+ distance(a, b) {
184
+ return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
185
+ }
186
+ // ---------------------------------------------------------------------------
187
+ // Queries
188
+ // ---------------------------------------------------------------------------
189
+ getActiveTouchCount() {
190
+ return this.activeTouches.size;
191
+ }
192
+ getGestureHistory() {
193
+ return [...this.gestureHistory];
194
+ }
195
+ getRecentGestures(count) {
196
+ return this.gestureHistory.slice(-count);
197
+ }
198
+ clearHistory() {
199
+ this.gestureHistory = [];
200
+ }
201
+ getConfig() {
202
+ return { ...this.config };
203
+ }
204
+ setConfig(config) {
205
+ Object.assign(this.config, config);
206
+ }
207
+ };
208
+
209
+ // src/input/InputBindings.ts
210
+ var _bindingId = 0;
211
+ var _chordId = 0;
212
+ var InputBindings = class {
213
+ profiles = /* @__PURE__ */ new Map();
214
+ activeProfileId = null;
215
+ constructor() {
216
+ this.createProfile("default", "Default");
217
+ this.activeProfileId = "default";
218
+ const p = this.profiles.get("default");
219
+ p.bindings.push({
220
+ id: `bind_${_bindingId++}`,
221
+ action: "VoicePushToTalk",
222
+ source: "key",
223
+ code: "KeyV"
224
+ });
225
+ }
226
+ // ---------------------------------------------------------------------------
227
+ // Profile Management
228
+ // ---------------------------------------------------------------------------
229
+ createProfile(id, name) {
230
+ const profile = { id, name, bindings: [], composites: [], chords: [] };
231
+ this.profiles.set(id, profile);
232
+ return profile;
233
+ }
234
+ deleteProfile(id) {
235
+ if (this.activeProfileId === id) return false;
236
+ return this.profiles.delete(id);
237
+ }
238
+ setActiveProfile(id) {
239
+ if (!this.profiles.has(id)) return false;
240
+ this.activeProfileId = id;
241
+ return true;
242
+ }
243
+ getActiveProfile() {
244
+ if (!this.activeProfileId) return null;
245
+ return this.profiles.get(this.activeProfileId) ?? null;
246
+ }
247
+ getProfile(id) {
248
+ return this.profiles.get(id);
249
+ }
250
+ getProfileCount() {
251
+ return this.profiles.size;
252
+ }
253
+ // ---------------------------------------------------------------------------
254
+ // Binding Management
255
+ // ---------------------------------------------------------------------------
256
+ bind(action, source, code, modifiers, scale) {
257
+ const profile = this.getActiveProfile();
258
+ if (!profile) return null;
259
+ const binding = {
260
+ id: `bind_${_bindingId++}`,
261
+ action,
262
+ source,
263
+ code,
264
+ modifiers: modifiers ?? [],
265
+ scale: scale ?? 1
266
+ };
267
+ profile.bindings.push(binding);
268
+ return binding;
269
+ }
270
+ unbind(bindingId) {
271
+ const profile = this.getActiveProfile();
272
+ if (!profile) return false;
273
+ const idx = profile.bindings.findIndex((b) => b.id === bindingId);
274
+ if (idx < 0) return false;
275
+ profile.bindings.splice(idx, 1);
276
+ return true;
277
+ }
278
+ unbindAction(action) {
279
+ const profile = this.getActiveProfile();
280
+ if (!profile) return 0;
281
+ const before = profile.bindings.length;
282
+ profile.bindings = profile.bindings.filter((b) => b.action !== action);
283
+ return before - profile.bindings.length;
284
+ }
285
+ getBindingsForAction(action) {
286
+ const profile = this.getActiveProfile();
287
+ if (!profile) return [];
288
+ return profile.bindings.filter((b) => b.action === action);
289
+ }
290
+ // ---------------------------------------------------------------------------
291
+ // Composite Axes
292
+ // ---------------------------------------------------------------------------
293
+ addCompositeAxis(name, positive, negative) {
294
+ const profile = this.getActiveProfile();
295
+ if (!profile) return;
296
+ profile.composites.push({ name, positive, negative });
297
+ }
298
+ getCompositeAxes() {
299
+ return this.getActiveProfile()?.composites ?? [];
300
+ }
301
+ /**
302
+ * Resolve a composite axis value from key states.
303
+ */
304
+ resolveComposite(name, keyStates) {
305
+ const profile = this.getActiveProfile();
306
+ if (!profile) return 0;
307
+ const comp = profile.composites.find((c) => c.name === name);
308
+ if (!comp) return 0;
309
+ const pos = keyStates.get(comp.positive) ? 1 : 0;
310
+ const neg = keyStates.get(comp.negative) ? 1 : 0;
311
+ return pos - neg;
312
+ }
313
+ // ---------------------------------------------------------------------------
314
+ // Chord Bindings
315
+ // ---------------------------------------------------------------------------
316
+ addChord(action, keys, order = "any") {
317
+ const profile = this.getActiveProfile();
318
+ const chord = { id: `chord_${_chordId++}`, action, keys, order };
319
+ if (profile) profile.chords.push(chord);
320
+ return chord;
321
+ }
322
+ isChordActive(chordId, pressedKeys) {
323
+ const profile = this.getActiveProfile();
324
+ if (!profile) return false;
325
+ const chord = profile.chords.find((c) => c.id === chordId);
326
+ if (!chord) return false;
327
+ return chord.keys.every((k) => pressedKeys.has(k));
328
+ }
329
+ // ---------------------------------------------------------------------------
330
+ // Conflict Detection
331
+ // ---------------------------------------------------------------------------
332
+ detectConflicts() {
333
+ const profile = this.getActiveProfile();
334
+ if (!profile) return [];
335
+ const conflicts = [];
336
+ const bindingMap = /* @__PURE__ */ new Map();
337
+ for (const b of profile.bindings) {
338
+ const key = `${b.source}:${b.code}:${(b.modifiers ?? []).sort().join("+")}`;
339
+ if (!bindingMap.has(key)) bindingMap.set(key, []);
340
+ bindingMap.get(key).push(b.action);
341
+ }
342
+ for (const [binding, actions] of bindingMap) {
343
+ if (actions.length > 1) {
344
+ const unique = [...new Set(actions)];
345
+ for (let i = 0; i < unique.length; i++) {
346
+ for (let j = i + 1; j < unique.length; j++) {
347
+ conflicts.push({
348
+ action1: unique[i],
349
+ action2: unique[j],
350
+ binding,
351
+ severity: "warning"
352
+ });
353
+ }
354
+ }
355
+ }
356
+ }
357
+ return conflicts;
358
+ }
359
+ // ---------------------------------------------------------------------------
360
+ // Serialization
361
+ // ---------------------------------------------------------------------------
362
+ exportProfile(profileId) {
363
+ const profile = profileId ? this.profiles.get(profileId) : this.getActiveProfile();
364
+ if (!profile) return "{}";
365
+ return JSON.stringify(profile, null, 2);
366
+ }
367
+ importProfile(json) {
368
+ try {
369
+ const data = JSON.parse(json);
370
+ if (!data.id || !data.name) return null;
371
+ this.profiles.set(data.id, data);
372
+ return data;
373
+ } catch {
374
+ return null;
375
+ }
376
+ }
377
+ };
378
+
379
+ // src/input/InputManager.ts
380
+ var InputManager = class {
381
+ keys = /* @__PURE__ */ new Map();
382
+ prevKeys = /* @__PURE__ */ new Set();
383
+ mouse;
384
+ gamepads = /* @__PURE__ */ new Map();
385
+ actionMappings = /* @__PURE__ */ new Map();
386
+ // action -> [key bindings]
387
+ actions = /* @__PURE__ */ new Map();
388
+ defaultDeadZone = 0.15;
389
+ inputBuffer = [];
390
+ bufferDuration = 200;
391
+ // ms
392
+ constructor() {
393
+ this.mouse = {
394
+ x: 0,
395
+ y: 0,
396
+ deltaX: 0,
397
+ deltaY: 0,
398
+ scrollDelta: 0,
399
+ buttons: /* @__PURE__ */ new Map()
400
+ };
401
+ }
402
+ // ---------------------------------------------------------------------------
403
+ // Key Input
404
+ // ---------------------------------------------------------------------------
405
+ keyDown(key) {
406
+ const existing = this.keys.get(key);
407
+ if (!existing || !existing.pressed) {
408
+ this.keys.set(key, {
409
+ pressed: true,
410
+ justPressed: true,
411
+ justReleased: false,
412
+ heldDuration: 0
413
+ });
414
+ }
415
+ }
416
+ keyUp(key) {
417
+ const existing = this.keys.get(key);
418
+ if (existing) {
419
+ existing.pressed = false;
420
+ existing.justReleased = true;
421
+ } else {
422
+ this.keys.set(key, {
423
+ pressed: false,
424
+ justPressed: false,
425
+ justReleased: true,
426
+ heldDuration: 0
427
+ });
428
+ }
429
+ }
430
+ isKeyPressed(key) {
431
+ return this.keys.get(key)?.pressed ?? false;
432
+ }
433
+ isKeyJustPressed(key) {
434
+ return this.keys.get(key)?.justPressed ?? false;
435
+ }
436
+ isKeyJustReleased(key) {
437
+ return this.keys.get(key)?.justReleased ?? false;
438
+ }
439
+ getKeyHeldDuration(key) {
440
+ return this.keys.get(key)?.heldDuration ?? 0;
441
+ }
442
+ // ---------------------------------------------------------------------------
443
+ // Mouse Input
444
+ // ---------------------------------------------------------------------------
445
+ setMousePosition(x, y) {
446
+ this.mouse.deltaX = x - this.mouse.x;
447
+ this.mouse.deltaY = y - this.mouse.y;
448
+ this.mouse.x = x;
449
+ this.mouse.y = y;
450
+ }
451
+ mouseButtonDown(button) {
452
+ this.mouse.buttons.set(button, {
453
+ pressed: true,
454
+ justPressed: true,
455
+ justReleased: false,
456
+ heldDuration: 0
457
+ });
458
+ }
459
+ mouseButtonUp(button) {
460
+ const existing = this.mouse.buttons.get(button);
461
+ if (existing) {
462
+ existing.pressed = false;
463
+ existing.justReleased = true;
464
+ }
465
+ }
466
+ setScrollDelta(delta) {
467
+ this.mouse.scrollDelta = delta;
468
+ }
469
+ getMousePosition() {
470
+ return { x: this.mouse.x, y: this.mouse.y };
471
+ }
472
+ getMouseDelta() {
473
+ return { x: this.mouse.deltaX, y: this.mouse.deltaY };
474
+ }
475
+ isMouseButtonPressed(button) {
476
+ return this.mouse.buttons.get(button)?.pressed ?? false;
477
+ }
478
+ // ---------------------------------------------------------------------------
479
+ // Gamepad Input
480
+ // ---------------------------------------------------------------------------
481
+ connectGamepad(index, id, axisCount = 4) {
482
+ const axes = [];
483
+ for (let i = 0; i < axisCount; i++) {
484
+ axes.push({ value: 0, deadZone: this.defaultDeadZone });
485
+ }
486
+ this.gamepads.set(index, { connected: true, id, buttons: /* @__PURE__ */ new Map(), axes });
487
+ }
488
+ disconnectGamepad(index) {
489
+ const gp = this.gamepads.get(index);
490
+ if (gp) gp.connected = false;
491
+ }
492
+ setGamepadAxis(padIndex, axisIndex, value) {
493
+ const gp = this.gamepads.get(padIndex);
494
+ if (!gp || axisIndex >= gp.axes.length) return;
495
+ const axis = gp.axes[axisIndex];
496
+ axis.value = Math.abs(value) < axis.deadZone ? 0 : value;
497
+ }
498
+ getGamepadAxis(padIndex, axisIndex) {
499
+ const gp = this.gamepads.get(padIndex);
500
+ if (!gp || axisIndex >= gp.axes.length) return 0;
501
+ return gp.axes[axisIndex].value;
502
+ }
503
+ gamepadButtonDown(padIndex, button) {
504
+ const gp = this.gamepads.get(padIndex);
505
+ if (!gp) return;
506
+ gp.buttons.set(button, {
507
+ pressed: true,
508
+ justPressed: true,
509
+ justReleased: false,
510
+ heldDuration: 0
511
+ });
512
+ }
513
+ setDeadZone(value) {
514
+ this.defaultDeadZone = Math.max(0, Math.min(1, value));
515
+ }
516
+ // ---------------------------------------------------------------------------
517
+ // Action Mapping
518
+ // ---------------------------------------------------------------------------
519
+ mapAction(actionName, keys) {
520
+ this.actionMappings.set(actionName, keys);
521
+ if (!this.actions.has(actionName)) {
522
+ this.actions.set(actionName, {
523
+ name: actionName,
524
+ value: 0,
525
+ pressed: false,
526
+ justPressed: false,
527
+ justReleased: false
528
+ });
529
+ }
530
+ }
531
+ unmapAction(actionName) {
532
+ this.actionMappings.delete(actionName);
533
+ this.actions.delete(actionName);
534
+ }
535
+ getAction(actionName) {
536
+ return this.actions.get(actionName);
537
+ }
538
+ isActionPressed(actionName) {
539
+ return this.actions.get(actionName)?.pressed ?? false;
540
+ }
541
+ isActionJustPressed(actionName) {
542
+ return this.actions.get(actionName)?.justPressed ?? false;
543
+ }
544
+ // ---------------------------------------------------------------------------
545
+ // Input Buffer (fighting game style)
546
+ // ---------------------------------------------------------------------------
547
+ getBufferedAction(actionName, withinMs) {
548
+ const cutoff = Date.now() - (withinMs ?? this.bufferDuration);
549
+ return this.inputBuffer.some((e) => e.action === actionName && e.timestamp >= cutoff);
550
+ }
551
+ setBufferDuration(ms) {
552
+ this.bufferDuration = Math.max(0, ms);
553
+ }
554
+ // ---------------------------------------------------------------------------
555
+ // Update (call once per frame)
556
+ // ---------------------------------------------------------------------------
557
+ update(dt) {
558
+ const now = Date.now();
559
+ for (const [_key, state] of this.keys) {
560
+ if (state.pressed) state.heldDuration += dt;
561
+ state.justPressed = false;
562
+ state.justReleased = false;
563
+ }
564
+ this.mouse.deltaX = 0;
565
+ this.mouse.deltaY = 0;
566
+ this.mouse.scrollDelta = 0;
567
+ for (const state of this.mouse.buttons.values()) {
568
+ state.justPressed = false;
569
+ state.justReleased = false;
570
+ if (state.pressed) state.heldDuration += dt;
571
+ }
572
+ for (const gp of this.gamepads.values()) {
573
+ for (const state of gp.buttons.values()) {
574
+ state.justPressed = false;
575
+ state.justReleased = false;
576
+ if (state.pressed) state.heldDuration += dt;
577
+ }
578
+ }
579
+ for (const [actionName, bindings] of this.actionMappings) {
580
+ const action = this.actions.get(actionName);
581
+ if (!action) continue;
582
+ const wasPressed = action.pressed;
583
+ let isPressed = false;
584
+ for (const binding of bindings) {
585
+ if (this.keys.get(binding)?.pressed) {
586
+ isPressed = true;
587
+ break;
588
+ }
589
+ }
590
+ action.pressed = isPressed;
591
+ action.justPressed = isPressed && !wasPressed;
592
+ action.justReleased = !isPressed && wasPressed;
593
+ action.value = isPressed ? 1 : 0;
594
+ if (action.justPressed) {
595
+ this.inputBuffer.push({ action: actionName, timestamp: now });
596
+ }
597
+ }
598
+ const cutoff = now - this.bufferDuration * 2;
599
+ this.inputBuffer = this.inputBuffer.filter((e) => e.timestamp > cutoff);
600
+ }
601
+ // ---------------------------------------------------------------------------
602
+ // Snapshot
603
+ // ---------------------------------------------------------------------------
604
+ getSnapshot() {
605
+ return {
606
+ timestamp: Date.now(),
607
+ keys: new Map(this.keys),
608
+ mouse: { ...this.mouse, buttons: new Map(this.mouse.buttons) },
609
+ gamepads: new Map(this.gamepads),
610
+ actions: new Map(this.actions)
611
+ };
612
+ }
613
+ reset() {
614
+ this.keys.clear();
615
+ this.mouse = { x: 0, y: 0, deltaX: 0, deltaY: 0, scrollDelta: 0, buttons: /* @__PURE__ */ new Map() };
616
+ this.gamepads.clear();
617
+ this.inputBuffer = [];
618
+ for (const action of this.actions.values()) {
619
+ action.pressed = false;
620
+ action.justPressed = false;
621
+ action.justReleased = false;
622
+ action.value = 0;
623
+ }
624
+ }
625
+ };
626
+
627
+ export {
628
+ GestureRecognizer,
629
+ InputBindings,
630
+ InputManager,
631
+ input_exports
632
+ };