@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,821 @@
1
+ import {
2
+ __export
3
+ } from "./chunk-AKLW2MUS.js";
4
+
5
+ // src/ecs/index.ts
6
+ var ecs_exports = {};
7
+ __export(ecs_exports, {
8
+ ComponentRegistry: () => ComponentRegistry,
9
+ ComponentStore: () => ComponentStore,
10
+ EntityRegistry: () => EntityRegistry,
11
+ SystemScheduler: () => SystemScheduler,
12
+ World: () => World,
13
+ registerBuiltInComponents: () => registerBuiltInComponents
14
+ });
15
+
16
+ // src/ecs/ComponentRegistry.ts
17
+ var ComponentRegistry = class {
18
+ schemas = /* @__PURE__ */ new Map();
19
+ /**
20
+ * Register a component type with its default data factory.
21
+ */
22
+ register(schema) {
23
+ this.schemas.set(schema.type, schema);
24
+ }
25
+ /**
26
+ * Get the schema for a component type.
27
+ */
28
+ getSchema(type) {
29
+ return this.schemas.get(type);
30
+ }
31
+ /**
32
+ * Create default data for a component type.
33
+ */
34
+ createDefault(type) {
35
+ const schema = this.schemas.get(type);
36
+ return schema ? schema.defaultData() : void 0;
37
+ }
38
+ /**
39
+ * Check if a component type is registered.
40
+ */
41
+ has(type) {
42
+ return this.schemas.has(type);
43
+ }
44
+ /**
45
+ * List all registered component types.
46
+ */
47
+ listTypes() {
48
+ return Array.from(this.schemas.keys());
49
+ }
50
+ /**
51
+ * Get count of registered types.
52
+ */
53
+ get count() {
54
+ return this.schemas.size;
55
+ }
56
+ };
57
+ function registerBuiltInComponents(registry) {
58
+ registry.register({
59
+ type: "transform",
60
+ defaultData: () => ({
61
+ position: [0, 0, 0],
62
+ rotation: { x: 0, y: 0, z: 0, w: 1 },
63
+ scale: { x: 1, y: 1, z: 1 }
64
+ }),
65
+ description: "Position, rotation, and scale in 3D space."
66
+ });
67
+ registry.register({
68
+ type: "renderable",
69
+ defaultData: () => ({ visible: true, meshType: "box", color: "#FFFFFF", opacity: 1 }),
70
+ description: "Visual rendering properties."
71
+ });
72
+ registry.register({
73
+ type: "collider",
74
+ defaultData: () => ({ type: "box", size: { x: 1, y: 1, z: 1 }, isTrigger: false }),
75
+ description: "Collision shape."
76
+ });
77
+ registry.register({
78
+ type: "rigidbody",
79
+ defaultData: () => ({
80
+ mass: 1,
81
+ velocity: { x: 0, y: 0, z: 0 },
82
+ useGravity: true,
83
+ isKinematic: false
84
+ }),
85
+ description: "Physics body properties."
86
+ });
87
+ registry.register({
88
+ type: "audio_source",
89
+ defaultData: () => ({ soundId: "", volume: 1, loop: false, spatialize: true }),
90
+ description: "Spatial audio source."
91
+ });
92
+ registry.register({
93
+ type: "ui_element",
94
+ defaultData: () => ({ type: "panel", interactive: false, text: "" }),
95
+ description: "UI element properties."
96
+ });
97
+ }
98
+
99
+ // src/ecs/ComponentStore.ts
100
+ var ComponentStore = class {
101
+ pools = /* @__PURE__ */ new Map();
102
+ // ---------------------------------------------------------------------------
103
+ // Pool Management
104
+ // ---------------------------------------------------------------------------
105
+ registerPool(type) {
106
+ const pool = { type, data: /* @__PURE__ */ new Map() };
107
+ this.pools.set(type, pool);
108
+ return pool;
109
+ }
110
+ getPool(type) {
111
+ return this.pools.get(type);
112
+ }
113
+ hasPool(type) {
114
+ return this.pools.has(type);
115
+ }
116
+ getPoolTypes() {
117
+ return [...this.pools.keys()];
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // Component Operations
121
+ // ---------------------------------------------------------------------------
122
+ add(type, entityId, data) {
123
+ let pool = this.pools.get(type);
124
+ if (!pool) {
125
+ pool = { type, data: /* @__PURE__ */ new Map() };
126
+ this.pools.set(type, pool);
127
+ }
128
+ if (pool.data.has(entityId)) return false;
129
+ pool.data.set(entityId, data);
130
+ return true;
131
+ }
132
+ remove(type, entityId) {
133
+ return this.pools.get(type)?.data.delete(entityId) ?? false;
134
+ }
135
+ get(type, entityId) {
136
+ return this.pools.get(type)?.data.get(entityId);
137
+ }
138
+ has(type, entityId) {
139
+ return this.pools.get(type)?.data.has(entityId) ?? false;
140
+ }
141
+ set(type, entityId, data) {
142
+ const pool = this.pools.get(type);
143
+ if (!pool) return false;
144
+ const existing = pool.data.get(entityId);
145
+ if (!existing) return false;
146
+ Object.assign(existing, data);
147
+ return true;
148
+ }
149
+ // ---------------------------------------------------------------------------
150
+ // Iteration
151
+ // ---------------------------------------------------------------------------
152
+ forEach(type, callback) {
153
+ const pool = this.pools.get(type);
154
+ if (!pool) return;
155
+ for (const [entityId, data] of pool.data) {
156
+ callback(entityId, data);
157
+ }
158
+ }
159
+ getEntitiesWithComponent(type) {
160
+ const pool = this.pools.get(type);
161
+ if (!pool) return [];
162
+ return [...pool.data.keys()];
163
+ }
164
+ getEntitiesWithAll(...types) {
165
+ if (types.length === 0) return [];
166
+ const first = this.pools.get(types[0]);
167
+ if (!first) return [];
168
+ const result = [];
169
+ for (const entityId of first.data.keys()) {
170
+ if (types.every((t) => this.has(t, entityId))) {
171
+ result.push(entityId);
172
+ }
173
+ }
174
+ return result;
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Bulk Operations
178
+ // ---------------------------------------------------------------------------
179
+ removeAllForEntity(entityId) {
180
+ let removed = 0;
181
+ for (const pool of this.pools.values()) {
182
+ if (pool.data.delete(entityId)) removed++;
183
+ }
184
+ return removed;
185
+ }
186
+ getComponentCount(type) {
187
+ return this.pools.get(type)?.data.size ?? 0;
188
+ }
189
+ getTotalComponentCount() {
190
+ let total = 0;
191
+ for (const pool of this.pools.values()) total += pool.data.size;
192
+ return total;
193
+ }
194
+ clear(type) {
195
+ if (type) {
196
+ this.pools.get(type)?.data.clear();
197
+ } else {
198
+ for (const pool of this.pools.values()) pool.data.clear();
199
+ }
200
+ }
201
+ };
202
+
203
+ // src/ecs/EntityRegistry.ts
204
+ var EntityRegistry = class {
205
+ entities = /* @__PURE__ */ new Map();
206
+ nextId = 1;
207
+ recycledIds = [];
208
+ tagIndex = /* @__PURE__ */ new Map();
209
+ nameIndex = /* @__PURE__ */ new Map();
210
+ // ---------------------------------------------------------------------------
211
+ // Entity Lifecycle
212
+ // ---------------------------------------------------------------------------
213
+ create(name = "", tags = []) {
214
+ const id = this.recycledIds.length > 0 ? this.recycledIds.pop() : this.nextId++;
215
+ const tagSet = new Set(tags);
216
+ const entity = {
217
+ id,
218
+ name: name || `entity_${id}`,
219
+ active: true,
220
+ tags: tagSet,
221
+ components: /* @__PURE__ */ new Set(),
222
+ parent: null,
223
+ children: [],
224
+ createdAt: Date.now()
225
+ };
226
+ this.entities.set(id, entity);
227
+ if (entity.name) this.nameIndex.set(entity.name, id);
228
+ for (const tag of tags) {
229
+ if (!this.tagIndex.has(tag)) this.tagIndex.set(tag, /* @__PURE__ */ new Set());
230
+ this.tagIndex.get(tag).add(id);
231
+ }
232
+ return entity;
233
+ }
234
+ destroy(id) {
235
+ const entity = this.entities.get(id);
236
+ if (!entity) return false;
237
+ if (entity.parent !== null) {
238
+ const parent = this.entities.get(entity.parent);
239
+ if (parent) parent.children = parent.children.filter((c) => c !== id);
240
+ }
241
+ for (const childId of [...entity.children]) {
242
+ this.destroy(childId);
243
+ }
244
+ this.nameIndex.delete(entity.name);
245
+ for (const tag of entity.tags) {
246
+ this.tagIndex.get(tag)?.delete(id);
247
+ }
248
+ this.entities.delete(id);
249
+ this.recycledIds.push(id);
250
+ return true;
251
+ }
252
+ // ---------------------------------------------------------------------------
253
+ // Queries
254
+ // ---------------------------------------------------------------------------
255
+ get(id) {
256
+ return this.entities.get(id);
257
+ }
258
+ getByName(name) {
259
+ const id = this.nameIndex.get(name);
260
+ return id !== void 0 ? this.entities.get(id) : void 0;
261
+ }
262
+ getByTag(tag) {
263
+ const ids = this.tagIndex.get(tag);
264
+ if (!ids) return [];
265
+ return [...ids].map((id) => this.entities.get(id)).filter((e) => e && e.active);
266
+ }
267
+ getByComponents(...componentTypes) {
268
+ const result = [];
269
+ for (const entity of this.entities.values()) {
270
+ if (!entity.active) continue;
271
+ if (componentTypes.every((t) => entity.components.has(t))) {
272
+ result.push(entity);
273
+ }
274
+ }
275
+ return result;
276
+ }
277
+ getAll() {
278
+ return [...this.entities.values()];
279
+ }
280
+ getActiveCount() {
281
+ let count = 0;
282
+ for (const e of this.entities.values()) if (e.active) count++;
283
+ return count;
284
+ }
285
+ getTotalCount() {
286
+ return this.entities.size;
287
+ }
288
+ // ---------------------------------------------------------------------------
289
+ // Tags
290
+ // ---------------------------------------------------------------------------
291
+ addTag(id, tag) {
292
+ const entity = this.entities.get(id);
293
+ if (!entity) return false;
294
+ entity.tags.add(tag);
295
+ if (!this.tagIndex.has(tag)) this.tagIndex.set(tag, /* @__PURE__ */ new Set());
296
+ this.tagIndex.get(tag).add(id);
297
+ return true;
298
+ }
299
+ removeTag(id, tag) {
300
+ const entity = this.entities.get(id);
301
+ if (!entity) return false;
302
+ entity.tags.delete(tag);
303
+ this.tagIndex.get(tag)?.delete(id);
304
+ return true;
305
+ }
306
+ hasTag(id, tag) {
307
+ return this.entities.get(id)?.tags.has(tag) ?? false;
308
+ }
309
+ // ---------------------------------------------------------------------------
310
+ // Hierarchy
311
+ // ---------------------------------------------------------------------------
312
+ setParent(childId, parentId) {
313
+ const child = this.entities.get(childId);
314
+ const parent = this.entities.get(parentId);
315
+ if (!child || !parent) return false;
316
+ if (child.parent !== null) {
317
+ const oldParent = this.entities.get(child.parent);
318
+ if (oldParent) oldParent.children = oldParent.children.filter((c) => c !== childId);
319
+ }
320
+ child.parent = parentId;
321
+ parent.children.push(childId);
322
+ return true;
323
+ }
324
+ getChildren(id) {
325
+ const entity = this.entities.get(id);
326
+ if (!entity) return [];
327
+ return entity.children.map((cid) => this.entities.get(cid)).filter(Boolean);
328
+ }
329
+ // ---------------------------------------------------------------------------
330
+ // Component Registration (bookkeeping only — actual data in ComponentStore)
331
+ // ---------------------------------------------------------------------------
332
+ registerComponent(entityId, componentType) {
333
+ const entity = this.entities.get(entityId);
334
+ if (!entity) return false;
335
+ entity.components.add(componentType);
336
+ return true;
337
+ }
338
+ unregisterComponent(entityId, componentType) {
339
+ const entity = this.entities.get(entityId);
340
+ if (!entity) return false;
341
+ return entity.components.delete(componentType);
342
+ }
343
+ hasComponent(entityId, componentType) {
344
+ return this.entities.get(entityId)?.components.has(componentType) ?? false;
345
+ }
346
+ // ---------------------------------------------------------------------------
347
+ // Activation
348
+ // ---------------------------------------------------------------------------
349
+ setActive(id, active) {
350
+ const entity = this.entities.get(id);
351
+ if (entity) entity.active = active;
352
+ }
353
+ };
354
+
355
+ // src/ecs/SystemScheduler.ts
356
+ var PHASE_ORDER = ["preUpdate", "fixedUpdate", "update", "postUpdate", "render"];
357
+ var SystemScheduler = class {
358
+ systems = /* @__PURE__ */ new Map();
359
+ executionOrder = [];
360
+ dirty = true;
361
+ fixedTimeStep = 1 / 60;
362
+ fixedAccumulator = 0;
363
+ phaseStats = /* @__PURE__ */ new Map();
364
+ // ---------------------------------------------------------------------------
365
+ // System Registration
366
+ // ---------------------------------------------------------------------------
367
+ register(name, execute, phase = "update", priority = 0, dependencies = [], group = "default") {
368
+ this.systems.set(name, {
369
+ name,
370
+ phase,
371
+ execute,
372
+ enabled: true,
373
+ priority,
374
+ dependencies,
375
+ group,
376
+ lastExecutionTime: 0,
377
+ executionCount: 0
378
+ });
379
+ this.dirty = true;
380
+ }
381
+ unregister(name) {
382
+ const result = this.systems.delete(name);
383
+ if (result) this.dirty = true;
384
+ return result;
385
+ }
386
+ enable(name) {
387
+ const sys = this.systems.get(name);
388
+ if (sys) sys.enabled = true;
389
+ }
390
+ disable(name) {
391
+ const sys = this.systems.get(name);
392
+ if (sys) sys.enabled = false;
393
+ }
394
+ isEnabled(name) {
395
+ return this.systems.get(name)?.enabled ?? false;
396
+ }
397
+ // ---------------------------------------------------------------------------
398
+ // Execution Order Resolution
399
+ // ---------------------------------------------------------------------------
400
+ resolveExecutionOrder() {
401
+ if (!this.dirty) return;
402
+ const sorted = [];
403
+ const visited = /* @__PURE__ */ new Set();
404
+ const visiting = /* @__PURE__ */ new Set();
405
+ const visit = (name) => {
406
+ if (visited.has(name)) return;
407
+ if (visiting.has(name)) return;
408
+ visiting.add(name);
409
+ const sys = this.systems.get(name);
410
+ if (sys) {
411
+ for (const dep of sys.dependencies) {
412
+ visit(dep);
413
+ }
414
+ }
415
+ visiting.delete(name);
416
+ visited.add(name);
417
+ sorted.push(name);
418
+ };
419
+ const byPhase = /* @__PURE__ */ new Map();
420
+ for (const [name, sys] of this.systems) {
421
+ if (!byPhase.has(sys.phase)) byPhase.set(sys.phase, []);
422
+ byPhase.get(sys.phase).push(name);
423
+ }
424
+ for (const phase of PHASE_ORDER) {
425
+ const phaseSystems = byPhase.get(phase) ?? [];
426
+ phaseSystems.sort((a, b) => {
427
+ const sa = this.systems.get(a), sb = this.systems.get(b);
428
+ return sa.priority - sb.priority;
429
+ });
430
+ for (const name of phaseSystems) visit(name);
431
+ }
432
+ this.executionOrder = sorted;
433
+ this.dirty = false;
434
+ }
435
+ // ---------------------------------------------------------------------------
436
+ // Update
437
+ // ---------------------------------------------------------------------------
438
+ update(dt) {
439
+ this.resolveExecutionOrder();
440
+ this.phaseStats.clear();
441
+ this.fixedAccumulator += dt;
442
+ for (const name of this.executionOrder) {
443
+ const sys = this.systems.get(name);
444
+ if (!sys || !sys.enabled) continue;
445
+ if (sys.phase === "fixedUpdate") {
446
+ while (this.fixedAccumulator >= this.fixedTimeStep) {
447
+ const start = performance.now();
448
+ sys.execute(this.fixedTimeStep);
449
+ sys.lastExecutionTime = performance.now() - start;
450
+ sys.executionCount++;
451
+ this.recordPhaseTime(sys.phase, sys.name, sys.lastExecutionTime);
452
+ this.fixedAccumulator -= this.fixedTimeStep;
453
+ }
454
+ } else {
455
+ const start = performance.now();
456
+ sys.execute(dt);
457
+ sys.lastExecutionTime = performance.now() - start;
458
+ sys.executionCount++;
459
+ this.recordPhaseTime(sys.phase, sys.name, sys.lastExecutionTime);
460
+ }
461
+ }
462
+ }
463
+ recordPhaseTime(phase, name, time) {
464
+ if (!this.phaseStats.has(phase)) {
465
+ this.phaseStats.set(phase, { phase, systemCount: 0, totalTime: 0, systems: [] });
466
+ }
467
+ const stats = this.phaseStats.get(phase);
468
+ stats.systemCount++;
469
+ stats.totalTime += time;
470
+ stats.systems.push({ name, time });
471
+ }
472
+ // ---------------------------------------------------------------------------
473
+ // Queries
474
+ // ---------------------------------------------------------------------------
475
+ getSystem(name) {
476
+ return this.systems.get(name);
477
+ }
478
+ getSystemCount() {
479
+ return this.systems.size;
480
+ }
481
+ get systemCount() {
482
+ return this.systems.size;
483
+ }
484
+ getExecutionOrder() {
485
+ this.resolveExecutionOrder();
486
+ return [...this.executionOrder];
487
+ }
488
+ getPhaseStats() {
489
+ return new Map(this.phaseStats);
490
+ }
491
+ getSystemsByPhase(phase) {
492
+ return [...this.systems.values()].filter((s) => s.phase === phase);
493
+ }
494
+ setFixedTimeStep(dt) {
495
+ this.fixedTimeStep = dt;
496
+ }
497
+ getFixedTimeStep() {
498
+ return this.fixedTimeStep;
499
+ }
500
+ };
501
+
502
+ // src/state/ReactiveState.ts
503
+ function reactive(target, onMutation) {
504
+ return new Proxy(target, {
505
+ get(obj, key) {
506
+ const value = Reflect.get(obj, key);
507
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
508
+ return reactive(value, onMutation);
509
+ }
510
+ return value;
511
+ },
512
+ set(obj, key, value) {
513
+ const oldValue = Reflect.get(obj, key);
514
+ const result = Reflect.set(obj, key, value);
515
+ if (oldValue !== value && onMutation) {
516
+ onMutation(obj, key, value, oldValue);
517
+ }
518
+ return result;
519
+ }
520
+ });
521
+ }
522
+
523
+ // src/state/UndoManager.ts
524
+ var UndoManager = class {
525
+ undoStack = [];
526
+ redoStack = [];
527
+ maxDurationMs = 5e3;
528
+ push(undoOp, redoOp) {
529
+ const now = Date.now();
530
+ this.undoStack.push({ undo: undoOp, redo: redoOp, timestamp: now });
531
+ this.redoStack = [];
532
+ this.prune(now);
533
+ }
534
+ prune(now) {
535
+ while (this.undoStack.length > 0 && now - this.undoStack[0].timestamp > this.maxDurationMs) {
536
+ this.undoStack.shift();
537
+ }
538
+ }
539
+ undo() {
540
+ const step = this.undoStack.pop();
541
+ if (!step) return null;
542
+ this.redoStack.push(step);
543
+ return step;
544
+ }
545
+ redo() {
546
+ const step = this.redoStack.pop();
547
+ if (!step) return null;
548
+ this.undoStack.push(step);
549
+ return step;
550
+ }
551
+ clear() {
552
+ this.undoStack = [];
553
+ this.redoStack = [];
554
+ }
555
+ };
556
+
557
+ // src/ecs/World.ts
558
+ var World = class {
559
+ nextEntity = 1;
560
+ entities = /* @__PURE__ */ new Set();
561
+ components = /* @__PURE__ */ new Map();
562
+ tags = /* @__PURE__ */ new Map();
563
+ undoManager = new UndoManager();
564
+ isUndoing = false;
565
+ /**
566
+ * Create a new entity.
567
+ */
568
+ createEntity() {
569
+ const id = this.nextEntity++;
570
+ this.entities.add(id);
571
+ if (!this.isUndoing) {
572
+ this.undoManager.push(
573
+ { type: "destroy", entity: id, components: /* @__PURE__ */ new Map(), tags: /* @__PURE__ */ new Set() },
574
+ // UNDO: Destroy
575
+ { type: "create", entity: id }
576
+ // REDO: Create
577
+ );
578
+ }
579
+ return id;
580
+ }
581
+ /**
582
+ * Destroy an entity and all its components.
583
+ */
584
+ destroyEntity(entity) {
585
+ const componentsToSave = /* @__PURE__ */ new Map();
586
+ for (const [type, store] of this.components) {
587
+ if (store.has(entity)) {
588
+ componentsToSave.set(type, store.get(entity));
589
+ }
590
+ }
591
+ const tagsToSave = new Set(this.tags.get(entity) || []);
592
+ if (!this.isUndoing) {
593
+ this.undoManager.push(
594
+ { type: "restore", entity, components: componentsToSave, tags: tagsToSave },
595
+ // UNDO: Restore
596
+ { type: "destroy", entity, components: componentsToSave, tags: tagsToSave }
597
+ // REDO: Destroy
598
+ );
599
+ }
600
+ this.entities.delete(entity);
601
+ this.tags.delete(entity);
602
+ for (const store of this.components.values()) {
603
+ store.delete(entity);
604
+ }
605
+ }
606
+ /**
607
+ * Check if an entity exists.
608
+ */
609
+ hasEntity(entity) {
610
+ return this.entities.has(entity);
611
+ }
612
+ /**
613
+ * Get entity count.
614
+ */
615
+ get entityCount() {
616
+ return this.entities.size;
617
+ }
618
+ /**
619
+ * Add a component to an entity.
620
+ * The component data will be wrapped in a reactive proxy.
621
+ */
622
+ addComponent(entity, type, data) {
623
+ if (!this.entities.has(entity)) return;
624
+ if (!this.components.has(type)) this.components.set(type, /* @__PURE__ */ new Map());
625
+ const reactiveData = reactive(data, (target, key, value, oldValue) => {
626
+ if (!this.isUndoing) {
627
+ this.undoManager.push(
628
+ {
629
+ type: "updateComponent",
630
+ entity,
631
+ componentType: type,
632
+ key,
633
+ value: oldValue,
634
+ oldValue: void 0
635
+ },
636
+ // UNDO
637
+ { type: "updateComponent", entity, componentType: type, key, value, oldValue: void 0 }
638
+ // REDO
639
+ );
640
+ }
641
+ });
642
+ this.components.get(type).set(entity, reactiveData);
643
+ if (!this.isUndoing) {
644
+ this.undoManager.push(
645
+ { type: "removeComponent", entity, componentType: type, data: reactiveData },
646
+ // UNDO
647
+ { type: "addComponent", entity, componentType: type, data: reactiveData }
648
+ // REDO
649
+ );
650
+ }
651
+ }
652
+ /**
653
+ * Remove a component from an entity.
654
+ */
655
+ removeComponent(entity, type) {
656
+ const data = this.components.get(type)?.get(entity);
657
+ if (data && !this.isUndoing) {
658
+ this.undoManager.push(
659
+ { type: "addComponent", entity, componentType: type, data },
660
+ // UNDO
661
+ { type: "removeComponent", entity, componentType: type, data }
662
+ // REDO
663
+ );
664
+ }
665
+ this.components.get(type)?.delete(entity);
666
+ }
667
+ /**
668
+ * Get a component from an entity.
669
+ */
670
+ getComponent(entity, type) {
671
+ return this.components.get(type)?.get(entity);
672
+ }
673
+ /**
674
+ * Check if an entity has a component.
675
+ */
676
+ hasComponent(entity, type) {
677
+ return this.components.get(type)?.has(entity) || false;
678
+ }
679
+ /**
680
+ * Get all component types for an entity.
681
+ */
682
+ getComponentTypes(entity) {
683
+ const types = [];
684
+ for (const [type, store] of this.components) {
685
+ if (store.has(entity)) {
686
+ types.push(type);
687
+ }
688
+ }
689
+ return types;
690
+ }
691
+ /**
692
+ * Add a tag to an entity.
693
+ */
694
+ addTag(entity, tag) {
695
+ if (!this.tags.has(entity)) this.tags.set(entity, /* @__PURE__ */ new Set());
696
+ this.tags.get(entity).add(tag);
697
+ }
698
+ /**
699
+ * Check if an entity has a tag.
700
+ */
701
+ hasTag(entity, tag) {
702
+ return this.tags.get(entity)?.has(tag) || false;
703
+ }
704
+ /**
705
+ * Query all entities that have ALL of the specified component types.
706
+ */
707
+ query(...componentTypes) {
708
+ const results = [];
709
+ for (const entity of this.entities) {
710
+ let match = true;
711
+ for (const type of componentTypes) {
712
+ if (!this.hasComponent(entity, type)) {
713
+ match = false;
714
+ break;
715
+ }
716
+ }
717
+ if (match) results.push(entity);
718
+ }
719
+ return results;
720
+ }
721
+ /**
722
+ * Query entities by tag.
723
+ */
724
+ queryByTag(tag) {
725
+ const results = [];
726
+ for (const entity of this.entities) {
727
+ if (this.hasTag(entity, tag)) results.push(entity);
728
+ }
729
+ return results;
730
+ }
731
+ /**
732
+ * Get all entities.
733
+ */
734
+ getAllEntities() {
735
+ return Array.from(this.entities);
736
+ }
737
+ /**
738
+ * Undo the last operation.
739
+ */
740
+ undo() {
741
+ const step = this.undoManager.undo();
742
+ if (!step) return;
743
+ this.isUndoing = true;
744
+ try {
745
+ this.applyOp(step.undo);
746
+ } finally {
747
+ this.isUndoing = false;
748
+ }
749
+ }
750
+ /**
751
+ * Redo the last undone operation.
752
+ */
753
+ redo() {
754
+ const step = this.undoManager.redo();
755
+ if (!step) return;
756
+ this.isUndoing = true;
757
+ try {
758
+ this.applyOp(step.redo);
759
+ } finally {
760
+ this.isUndoing = false;
761
+ }
762
+ }
763
+ applyOp(op) {
764
+ switch (op.type) {
765
+ case "create":
766
+ if (!this.entities.has(op.entity)) {
767
+ this.entities.add(op.entity);
768
+ if (op.entity >= this.nextEntity) {
769
+ this.nextEntity = op.entity + 1;
770
+ }
771
+ }
772
+ break;
773
+ case "destroy":
774
+ this.destroyEntity(op.entity);
775
+ break;
776
+ case "addComponent":
777
+ this.addComponent(op.entity, op.componentType, op.data);
778
+ break;
779
+ case "removeComponent":
780
+ this.removeComponent(op.entity, op.componentType);
781
+ break;
782
+ case "updateComponent":
783
+ const store = this.components.get(op.componentType);
784
+ if (store && store.has(op.entity)) {
785
+ const comp = store.get(op.entity);
786
+ comp[op.key] = op.value;
787
+ }
788
+ break;
789
+ case "addTag":
790
+ this.addTag(op.entity, op.tag);
791
+ break;
792
+ case "removeTag":
793
+ if (this.tags.has(op.entity)) {
794
+ this.tags.get(op.entity).delete(op.tag);
795
+ }
796
+ break;
797
+ case "restore":
798
+ if (!this.entities.has(op.entity)) {
799
+ this.entities.add(op.entity);
800
+ if (op.entity >= this.nextEntity) {
801
+ this.nextEntity = op.entity + 1;
802
+ }
803
+ }
804
+ op.components.forEach((data, type) => {
805
+ this.addComponent(op.entity, type, data);
806
+ });
807
+ op.tags.forEach((tag) => this.addTag(op.entity, tag));
808
+ break;
809
+ }
810
+ }
811
+ };
812
+
813
+ export {
814
+ ComponentRegistry,
815
+ registerBuiltInComponents,
816
+ ComponentStore,
817
+ EntityRegistry,
818
+ SystemScheduler,
819
+ World,
820
+ ecs_exports
821
+ };