@holoscript/core 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/{chunk-KWYIVRIH.js → chunk-2XXE34KS.js} +2 -2
  2. package/dist/chunk-2XXE34KS.js.map +1 -0
  3. package/dist/{chunk-EU6CZMGJ.js → chunk-AFFVFO4D.js} +511 -118
  4. package/dist/chunk-AFFVFO4D.js.map +1 -0
  5. package/dist/chunk-DGUM43GV.js +10 -0
  6. package/dist/{chunk-4CV4JOE5.js.map → chunk-DGUM43GV.js.map} +1 -1
  7. package/dist/{chunk-VYIDLUCV.js → chunk-DOY73HDH.js} +4 -4
  8. package/dist/{chunk-VYIDLUCV.js.map → chunk-DOY73HDH.js.map} +1 -1
  9. package/dist/chunk-JEQ2X3Z6.cjs +12 -0
  10. package/dist/{chunk-CZLDE2OZ.cjs.map → chunk-JEQ2X3Z6.cjs.map} +1 -1
  11. package/dist/{chunk-3N67RLQP.cjs → chunk-L6VLNVKP.cjs} +511 -118
  12. package/dist/chunk-L6VLNVKP.cjs.map +1 -0
  13. package/dist/{chunk-VMZN4EVR.cjs → chunk-MFNO57XL.cjs} +2 -2
  14. package/dist/chunk-MFNO57XL.cjs.map +1 -0
  15. package/dist/{chunk-WFI4T3XB.cjs → chunk-R75MREOS.cjs} +6 -6
  16. package/dist/{chunk-WFI4T3XB.cjs.map → chunk-R75MREOS.cjs.map} +1 -1
  17. package/dist/{chunk-4OHVW4XR.cjs → chunk-T57ZL7KR.cjs} +299 -45
  18. package/dist/chunk-T57ZL7KR.cjs.map +1 -0
  19. package/dist/{chunk-MCP6D4LT.js → chunk-U72GEJZT.js} +299 -45
  20. package/dist/chunk-U72GEJZT.js.map +1 -0
  21. package/dist/debugger.cjs +6 -6
  22. package/dist/debugger.d.cts +1 -1
  23. package/dist/debugger.d.ts +1 -1
  24. package/dist/debugger.js +4 -4
  25. package/dist/index.cjs +1896 -1099
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +3145 -1534
  28. package/dist/index.d.ts +3145 -1534
  29. package/dist/index.js +1922 -1133
  30. package/dist/index.js.map +1 -1
  31. package/dist/parser.cjs +3 -3
  32. package/dist/parser.d.cts +34 -1
  33. package/dist/parser.d.ts +34 -1
  34. package/dist/parser.js +2 -2
  35. package/dist/runtime.cjs +3 -3
  36. package/dist/runtime.d.cts +47 -27
  37. package/dist/runtime.d.ts +47 -27
  38. package/dist/runtime.js +2 -2
  39. package/dist/type-checker.cjs +4 -4
  40. package/dist/type-checker.d.cts +3 -3
  41. package/dist/type-checker.d.ts +3 -3
  42. package/dist/type-checker.js +2 -2
  43. package/dist/{types-D6g4ACjP.d.cts → types-4h8cbtF_.d.cts} +80 -13
  44. package/dist/{types-D6g4ACjP.d.ts → types-4h8cbtF_.d.ts} +80 -13
  45. package/package.json +21 -20
  46. package/LICENSE +0 -21
  47. package/dist/chunk-3N67RLQP.cjs.map +0 -1
  48. package/dist/chunk-4CV4JOE5.js +0 -24
  49. package/dist/chunk-4OHVW4XR.cjs.map +0 -1
  50. package/dist/chunk-CZLDE2OZ.cjs +0 -28
  51. package/dist/chunk-EU6CZMGJ.js.map +0 -1
  52. package/dist/chunk-KWYIVRIH.js.map +0 -1
  53. package/dist/chunk-MCP6D4LT.js.map +0 -1
  54. package/dist/chunk-VMZN4EVR.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,858 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkVMZN4EVR_cjs = require('./chunk-VMZN4EVR.cjs');
4
- var chunkWFI4T3XB_cjs = require('./chunk-WFI4T3XB.cjs');
5
- var chunk4OHVW4XR_cjs = require('./chunk-4OHVW4XR.cjs');
6
- var chunk3N67RLQP_cjs = require('./chunk-3N67RLQP.cjs');
3
+ var chunkMFNO57XL_cjs = require('./chunk-MFNO57XL.cjs');
4
+ var chunkR75MREOS_cjs = require('./chunk-R75MREOS.cjs');
5
+ var chunkT57ZL7KR_cjs = require('./chunk-T57ZL7KR.cjs');
6
+ var chunkL6VLNVKP_cjs = require('./chunk-L6VLNVKP.cjs');
7
7
  var chunk3X2EGU7Z_cjs = require('./chunk-3X2EGU7Z.cjs');
8
- var chunkCZLDE2OZ_cjs = require('./chunk-CZLDE2OZ.cjs');
9
-
10
- // src/traits/MaterialTrait.ts
11
- var MaterialTrait_exports = {};
12
- chunkCZLDE2OZ_cjs.__export(MaterialTrait_exports, {
13
- MATERIAL_PRESETS: () => exports.MATERIAL_PRESETS,
14
- MaterialTrait: () => exports.MaterialTrait,
15
- createMaterialTrait: () => createMaterialTrait
16
- });
17
- function createMaterialTrait(config) {
18
- return new exports.MaterialTrait(config);
19
- }
20
- exports.MaterialTrait = void 0; exports.MATERIAL_PRESETS = void 0;
21
- var init_MaterialTrait = chunkCZLDE2OZ_cjs.__esm({
22
- "src/traits/MaterialTrait.ts"() {
23
- exports.MaterialTrait = class {
24
- constructor(config) {
25
- this.textureCache = /* @__PURE__ */ new Map();
26
- this.material = {
27
- ...{ type: "pbr" },
28
- ...config
29
- };
30
- }
31
- /**
32
- * Get material properties
33
- */
34
- getMaterial() {
35
- return { ...this.material };
36
- }
37
- /**
38
- * Update material property
39
- */
40
- setProperty(key, value) {
41
- this.material[key] = value;
42
- }
43
- /**
44
- * Get PBR properties
45
- */
46
- getPBRProperties() {
47
- return this.material.pbr;
48
- }
49
- /**
50
- * Update PBR material
51
- */
52
- updatePBR(pbr) {
53
- if (!this.material.pbr) {
54
- this.material.pbr = {
55
- baseColor: { r: 1, g: 1, b: 1 },
56
- metallic: 0,
57
- roughness: 0.5
58
- };
59
- }
60
- this.material.pbr = { ...this.material.pbr, ...pbr };
61
- }
62
- /**
63
- * Add texture map
64
- */
65
- addTexture(texture) {
66
- if (!this.material.textures) {
67
- this.material.textures = [];
68
- }
69
- this.material.textures.push(texture);
70
- }
71
- /**
72
- * Get all textures
73
- */
74
- getTextures() {
75
- return [...this.material.textures || []];
76
- }
77
- /**
78
- * Clear texture cache (for memory optimization)
79
- */
80
- clearTextureCache() {
81
- this.textureCache.clear();
82
- }
83
- /**
84
- * Get shader code if custom
85
- */
86
- getCustomShader() {
87
- return this.material.customShader;
88
- }
89
- /**
90
- * Set custom shader
91
- */
92
- setCustomShader(shader) {
93
- this.material.customShader = shader;
94
- }
95
- /**
96
- * Get optimization hints
97
- */
98
- getOptimization() {
99
- return this.material.optimization;
100
- }
101
- /**
102
- * Enable/disable texture streaming
103
- */
104
- setTextureStreaming(enabled) {
105
- if (!this.material.optimization) {
106
- this.material.optimization = {};
107
- }
108
- this.material.optimization.streamTextures = enabled;
109
- }
110
- /**
111
- * Set texture compression
112
- */
113
- setCompression(compression) {
114
- if (!this.material.optimization) {
115
- this.material.optimization = {};
116
- }
117
- this.material.optimization.compression = compression;
118
- }
119
- /**
120
- * Enable material instancing for performance
121
- */
122
- setInstanced(instanced) {
123
- if (!this.material.optimization) {
124
- this.material.optimization = {};
125
- }
126
- this.material.optimization.instanced = instanced;
127
- }
128
- /**
129
- * Dispose and cleanup
130
- */
131
- dispose() {
132
- this.textureCache.clear();
133
- }
134
- };
135
- exports.MATERIAL_PRESETS = {
136
- /** Shiny metal */
137
- chrome: () => ({
138
- type: "pbr",
139
- pbr: {
140
- baseColor: { r: 0.77, g: 0.77, b: 0.77 },
141
- metallic: 1,
142
- roughness: 0.1
143
- }
144
- }),
145
- /** Rough plastic */
146
- plastic: () => ({
147
- type: "pbr",
148
- pbr: {
149
- baseColor: { r: 1, g: 1, b: 1 },
150
- metallic: 0,
151
- roughness: 0.8
152
- }
153
- }),
154
- /** Wood texture */
155
- wood: () => ({
156
- type: "pbr",
157
- pbr: {
158
- baseColor: { r: 0.6, g: 0.4, b: 0.2 },
159
- metallic: 0,
160
- roughness: 0.4
161
- }
162
- }),
163
- /** Glass */
164
- glass: () => ({
165
- type: "transparent",
166
- blendMode: "blend",
167
- pbr: {
168
- baseColor: { r: 1, g: 1, b: 1, a: 0.3 },
169
- metallic: 0,
170
- roughness: 0,
171
- ior: 1.5,
172
- transmission: 0.9
173
- }
174
- }),
175
- /** Emissive (glowing) */
176
- emissive: () => ({
177
- type: "pbr",
178
- pbr: {
179
- baseColor: { r: 0, g: 1, b: 0 },
180
- metallic: 0,
181
- roughness: 1,
182
- emission: {
183
- color: { r: 0, g: 1, b: 0 },
184
- intensity: 2
185
- }
186
- }
187
- }),
188
- /** Skin material */
189
- skin: () => ({
190
- type: "pbr",
191
- pbr: {
192
- baseColor: { r: 1, g: 0.8, b: 0.7 },
193
- metallic: 0,
194
- roughness: 0.5,
195
- ambientOcclusion: 0.8
196
- }
197
- })
198
- };
199
- }
200
- });
201
-
202
- // src/traits/LightingTrait.ts
203
- var LightingTrait_exports = {};
204
- chunkCZLDE2OZ_cjs.__export(LightingTrait_exports, {
205
- LIGHTING_PRESETS: () => exports.LIGHTING_PRESETS,
206
- LightingTrait: () => exports.LightingTrait,
207
- createLightingTrait: () => createLightingTrait
208
- });
209
- function createLightingTrait(config) {
210
- return new exports.LightingTrait(config);
211
- }
212
- exports.LightingTrait = void 0; exports.LIGHTING_PRESETS = void 0;
213
- var init_LightingTrait = chunkCZLDE2OZ_cjs.__esm({
214
- "src/traits/LightingTrait.ts"() {
215
- exports.LightingTrait = class {
216
- constructor(config) {
217
- this.lights = /* @__PURE__ */ new Map();
218
- this.lightIdCounter = 0;
219
- this.globalIllumination = {
220
- enabled: true,
221
- intensity: 1,
222
- skyColor: { r: 0.5, g: 0.7, b: 1 },
223
- skyIntensity: 1,
224
- groundColor: { r: 0.4, g: 0.4, b: 0.4 },
225
- groundIntensity: 0.5,
226
- probes: true,
227
- indirectDiffuse: 1,
228
- indirectSpecular: 1,
229
- aoIntensity: 1,
230
- screenSpaceAO: true,
231
- ...config
232
- };
233
- }
234
- /**
235
- * Add a light to the scene
236
- */
237
- addLight(light) {
238
- const id = light.name || `light_${this.lightIdCounter++}`;
239
- this.lights.set(id, light);
240
- return id;
241
- }
242
- /**
243
- * Get light by ID
244
- */
245
- getLight(id) {
246
- return this.lights.get(id);
247
- }
248
- /**
249
- * Get all lights
250
- */
251
- getLights() {
252
- return Array.from(this.lights.values());
253
- }
254
- /**
255
- * Get lights by type
256
- */
257
- getLightsByType(type) {
258
- return Array.from(this.lights.values()).filter((l) => l.type === type);
259
- }
260
- /**
261
- * Update light properties
262
- */
263
- updateLight(id, updates) {
264
- const light = this.lights.get(id);
265
- if (!light) return false;
266
- this.lights.set(id, { ...light, ...updates });
267
- return true;
268
- }
269
- /**
270
- * Remove light
271
- */
272
- removeLight(id) {
273
- return this.lights.delete(id);
274
- }
275
- /**
276
- * Clear all lights
277
- */
278
- clearLights() {
279
- this.lights.clear();
280
- }
281
- /**
282
- * Get global illumination config
283
- */
284
- getGlobalIllumination() {
285
- return { ...this.globalIllumination };
286
- }
287
- /**
288
- * Update global illumination
289
- */
290
- updateGlobalIllumination(updates) {
291
- this.globalIllumination = {
292
- ...this.globalIllumination,
293
- ...updates
294
- };
295
- }
296
- /**
297
- * Enable/disable GI
298
- */
299
- setGIEnabled(enabled) {
300
- this.globalIllumination.enabled = enabled;
301
- }
302
- /**
303
- * Set ambient light colors (skybox mode)
304
- */
305
- setAmbientLight(skyColor, groundColor, intensity = 1) {
306
- this.globalIllumination.skyColor = skyColor;
307
- this.globalIllumination.groundColor = groundColor;
308
- this.globalIllumination.skyIntensity = intensity;
309
- this.globalIllumination.groundIntensity = intensity * 0.5;
310
- }
311
- /**
312
- * Enable/disable screen-space ambient occlusion
313
- */
314
- setScreenSpaceAO(enabled, intensity = 1) {
315
- this.globalIllumination.screenSpaceAO = enabled;
316
- this.globalIllumination.aoIntensity = intensity;
317
- }
318
- /**
319
- * Create directional light (sun)
320
- */
321
- createDirectionalLight(direction, color, intensity = 1, castShadows = true) {
322
- const light = {
323
- type: "directional",
324
- name: `sun_${this.lightIdCounter}`,
325
- direction,
326
- color,
327
- intensity,
328
- shadow: castShadows ? {
329
- type: "soft",
330
- resolution: 2048,
331
- cascades: 4,
332
- softness: 1
333
- } : void 0,
334
- volumetric: true,
335
- priority: 100
336
- };
337
- return this.addLight(light);
338
- }
339
- /**
340
- * Create point light
341
- */
342
- createPointLight(position, color, intensity, range, castShadows = false) {
343
- const light = {
344
- type: "point",
345
- name: `point_${this.lightIdCounter}`,
346
- position,
347
- color,
348
- intensity,
349
- range,
350
- shadow: castShadows ? {
351
- type: "soft",
352
- resolution: 512,
353
- softness: 0.5
354
- } : void 0,
355
- priority: 50
356
- };
357
- return this.addLight(light);
358
- }
359
- /**
360
- * Create spot light
361
- */
362
- createSpotLight(position, direction, color, intensity, range, spotAngle = 45, castShadows = true) {
363
- const light = {
364
- type: "spot",
365
- name: `spot_${this.lightIdCounter}`,
366
- position,
367
- direction,
368
- color,
369
- intensity,
370
- range,
371
- spotAngle,
372
- innerSpotAngle: spotAngle * 0.5,
373
- shadow: castShadows ? {
374
- type: "soft",
375
- resolution: 1024,
376
- softness: 0.8
377
- } : void 0,
378
- priority: 75
379
- };
380
- return this.addLight(light);
381
- }
382
- /**
383
- * Create area light for soft lighting
384
- */
385
- createAreaLight(position, color, intensity, width, height) {
386
- const light = {
387
- type: "area",
388
- name: `area_${this.lightIdCounter}`,
389
- position,
390
- color,
391
- intensity,
392
- range: Math.max(width, height) * 2,
393
- priority: 25
394
- };
395
- return this.addLight(light);
396
- }
397
- /**
398
- * Get shadow-casting lights
399
- */
400
- getShadowCastingLights() {
401
- return Array.from(this.lights.values()).filter((l) => l.shadow && l.shadow.type !== "none");
402
- }
403
- /**
404
- * Get light count by type
405
- */
406
- getLightCount() {
407
- const counts = {
408
- directional: 0,
409
- point: 0,
410
- spot: 0,
411
- area: 0,
412
- probe: 0
413
- };
414
- for (const light of this.lights.values()) {
415
- counts[light.type]++;
416
- }
417
- return counts;
418
- }
419
- /**
420
- * Estimate light impact for performance optimization
421
- */
422
- getPerformanceImpact() {
423
- const totalLights = this.lights.size;
424
- const shadowCasters = this.getShadowCastingLights().length;
425
- let estimatedGPUCost = "low";
426
- if (totalLights > 16 || shadowCasters > 4) {
427
- estimatedGPUCost = "high";
428
- } else if (totalLights > 8 || shadowCasters > 2) {
429
- estimatedGPUCost = "medium";
430
- }
431
- return {
432
- totalLights,
433
- shadowCasters,
434
- estimatedGPUCost
435
- };
436
- }
437
- /**
438
- * Get scene complexity info
439
- */
440
- getSceneInfo() {
441
- const counts = this.getLightCount();
442
- const impact = this.getPerformanceImpact();
443
- return `Lighting: ${counts.directional} dir, ${counts.point} point, ${counts.spot} spot | Shadows: ${impact.shadowCasters} | GPU: ${impact.estimatedGPUCost}`;
444
- }
445
- /**
446
- * Dispose and cleanup
447
- */
448
- dispose() {
449
- this.lights.clear();
450
- }
451
- };
452
- exports.LIGHTING_PRESETS = {
453
- /** Neutral studio lighting */
454
- studio: () => ({
455
- enabled: true,
456
- intensity: 1,
457
- skyColor: { r: 0.5, g: 0.5, b: 0.5 },
458
- skyIntensity: 0.5,
459
- groundColor: { r: 0.3, g: 0.3, b: 0.3 },
460
- groundIntensity: 0.3
461
- }),
462
- /** Bright outdoor lighting */
463
- outdoor: () => ({
464
- enabled: true,
465
- intensity: 1.2,
466
- skyColor: { r: 0.7, g: 0.85, b: 1 },
467
- skyIntensity: 1,
468
- groundColor: { r: 0.4, g: 0.4, b: 0.35 },
469
- groundIntensity: 0.6,
470
- indirectDiffuse: 1.2
471
- }),
472
- /** Dim interior lighting */
473
- interior: () => ({
474
- enabled: true,
475
- intensity: 0.6,
476
- skyColor: { r: 0.3, g: 0.3, b: 0.35 },
477
- skyIntensity: 0.4,
478
- groundColor: { r: 0.2, g: 0.2, b: 0.2 },
479
- groundIntensity: 0.2
480
- }),
481
- /** Night scene */
482
- night: () => ({
483
- enabled: true,
484
- intensity: 0.3,
485
- skyColor: { r: 0.01, g: 0.01, b: 0.02 },
486
- skyIntensity: 0.1,
487
- groundColor: { r: 0.02, g: 0.02, b: 0.02 },
488
- groundIntensity: 0.05,
489
- screenSpaceAO: false
490
- }),
491
- /** Sunset/golden hour */
492
- sunset: () => ({
493
- enabled: true,
494
- intensity: 1.1,
495
- skyColor: { r: 1, g: 0.7, b: 0.3 },
496
- skyIntensity: 1,
497
- groundColor: { r: 0.6, g: 0.4, b: 0.2 },
498
- groundIntensity: 0.8
499
- })
500
- };
501
- }
502
- });
503
-
504
- // src/traits/RenderingTrait.ts
505
- var RenderingTrait_exports = {};
506
- chunkCZLDE2OZ_cjs.__export(RenderingTrait_exports, {
507
- RenderingTrait: () => exports.RenderingTrait,
508
- createRenderingTrait: () => createRenderingTrait
509
- });
510
- function createRenderingTrait(config) {
511
- return new exports.RenderingTrait(config);
512
- }
513
- exports.RenderingTrait = void 0;
514
- var init_RenderingTrait = chunkCZLDE2OZ_cjs.__esm({
515
- "src/traits/RenderingTrait.ts"() {
516
- exports.RenderingTrait = class {
517
- constructor(config) {
518
- this.optimization = {
519
- lodStrategy: "automatic",
520
- culling: {
521
- mode: "back",
522
- frustum: true,
523
- occlusion: true
524
- },
525
- batching: {
526
- static: true,
527
- dynamic: true,
528
- instancing: true,
529
- maxInstanceCount: 1e3
530
- },
531
- textures: {
532
- streaming: true,
533
- compression: "auto",
534
- mipmaps: true,
535
- maxResolution: 2048
536
- },
537
- shaders: {
538
- simplifiedShaders: true,
539
- lodBias: 0
540
- },
541
- targetGPUTier: "high",
542
- adaptiveQuality: true,
543
- targetFrameRate: 60,
544
- ...config
545
- };
546
- }
547
- /**
548
- * Get rendering optimization config
549
- */
550
- getOptimization() {
551
- return JSON.parse(JSON.stringify(this.optimization));
552
- }
553
- /**
554
- * Update rendering configuration
555
- */
556
- updateOptimization(updates) {
557
- this.optimization = { ...this.optimization, ...updates };
558
- }
559
- /**
560
- * Setup LOD levels (3 levels is typical)
561
- */
562
- setupLODLevels(strategy = "automatic") {
563
- const levels = [
564
- {
565
- level: 0,
566
- screenRelativeSize: 0.5,
567
- polygonReduction: 1,
568
- textureScale: 1
569
- },
570
- {
571
- level: 1,
572
- screenRelativeSize: 0.25,
573
- polygonReduction: 0.6,
574
- disabledFeatures: ["specular"],
575
- textureScale: 0.5
576
- },
577
- {
578
- level: 2,
579
- screenRelativeSize: 0.1,
580
- polygonReduction: 0.3,
581
- disabledFeatures: ["specular", "normals"],
582
- textureScale: 0.25
583
- }
584
- ];
585
- this.optimization.lodStrategy = strategy;
586
- this.optimization.lodLevels = levels;
587
- }
588
- /**
589
- * Get LOD levels
590
- */
591
- getLODLevels() {
592
- return [...this.optimization.lodLevels || []];
593
- }
594
- /**
595
- * Configure culling
596
- */
597
- setCulling(config) {
598
- const defaultCulling = { mode: "back" };
599
- this.optimization.culling = {
600
- ...defaultCulling,
601
- ...this.optimization.culling,
602
- ...config
603
- };
604
- }
605
- /**
606
- * Enable frustum culling
607
- */
608
- setFrustumCulling(enabled) {
609
- if (!this.optimization.culling) {
610
- this.optimization.culling = { mode: "back" };
611
- }
612
- this.optimization.culling.frustum = enabled;
613
- }
614
- /**
615
- * Enable occlusion culling
616
- */
617
- setOcclusionCulling(enabled, distance) {
618
- if (!this.optimization.culling) {
619
- this.optimization.culling = { mode: "back" };
620
- }
621
- this.optimization.culling.occlusion = enabled;
622
- if (distance) {
623
- this.optimization.culling.occlusionDistance = distance;
624
- }
625
- }
626
- /**
627
- * Configure batching
628
- */
629
- setBatching(config) {
630
- this.optimization.batching = {
631
- ...this.optimization.batching,
632
- ...config
633
- };
634
- }
635
- /**
636
- * Enable GPU instancing
637
- */
638
- setInstancing(enabled, maxInstances) {
639
- if (!this.optimization.batching) {
640
- this.optimization.batching = {};
641
- }
642
- this.optimization.batching.instancing = enabled;
643
- if (maxInstances) {
644
- this.optimization.batching.maxInstanceCount = maxInstances;
645
- }
646
- }
647
- /**
648
- * Configure texture optimization
649
- */
650
- setTextureOptimization(config) {
651
- this.optimization.textures = {
652
- ...this.optimization.textures,
653
- ...config
654
- };
655
- }
656
- /**
657
- * Enable texture streaming
658
- */
659
- setTextureStreaming(enabled, budgetMB) {
660
- if (!this.optimization.textures) {
661
- this.optimization.textures = {};
662
- }
663
- this.optimization.textures.streaming = enabled;
664
- if (budgetMB) {
665
- this.optimization.textures.streamingBudget = budgetMB;
666
- }
667
- }
668
- /**
669
- * Set texture compression
670
- */
671
- setTextureCompression(compression) {
672
- if (!this.optimization.textures) {
673
- this.optimization.textures = {};
674
- }
675
- this.optimization.textures.compression = compression;
676
- }
677
- /**
678
- * Set max texture resolution
679
- */
680
- setMaxTextureResolution(resolution) {
681
- if (!this.optimization.textures) {
682
- this.optimization.textures = {};
683
- }
684
- this.optimization.textures.maxResolution = resolution;
685
- }
686
- /**
687
- * Configure shader optimization
688
- */
689
- setShaderOptimization(config) {
690
- this.optimization.shaders = {
691
- ...this.optimization.shaders,
692
- ...config
693
- };
694
- }
695
- /**
696
- * Set target GPU tier
697
- */
698
- setTargetGPUTier(tier) {
699
- this.optimization.targetGPUTier = tier;
700
- }
701
- /**
702
- * Enable adaptive quality (adjust based on frame rate)
703
- */
704
- setAdaptiveQuality(enabled, targetFrameRate) {
705
- this.optimization.adaptiveQuality = enabled;
706
- if (targetFrameRate) {
707
- this.optimization.targetFrameRate = targetFrameRate;
708
- }
709
- }
710
- /**
711
- * Set fixed timestep for VR/AR
712
- */
713
- setFixedTimestep(timestep) {
714
- this.optimization.fixedTimestep = timestep;
715
- }
716
- /**
717
- * Get rendering preset for quality level
718
- */
719
- getPresetForQuality(quality) {
720
- const presets = {
721
- low: {
722
- targetGPUTier: "low",
723
- lodStrategy: "automatic",
724
- culling: { mode: "back", frustum: true, occlusion: false },
725
- batching: { instancing: true, maxInstanceCount: 500 },
726
- textures: {
727
- compression: "astc",
728
- maxResolution: 512,
729
- streaming: true,
730
- streamingBudget: 128
731
- },
732
- adaptiveQuality: true,
733
- targetFrameRate: 30
734
- },
735
- medium: {
736
- targetGPUTier: "medium",
737
- lodStrategy: "automatic",
738
- culling: { mode: "back", frustum: true, occlusion: true },
739
- batching: { instancing: true, maxInstanceCount: 1e3 },
740
- textures: {
741
- compression: "basis",
742
- maxResolution: 1024,
743
- streaming: true,
744
- streamingBudget: 256
745
- },
746
- adaptiveQuality: true,
747
- targetFrameRate: 60
748
- },
749
- high: {
750
- targetGPUTier: "high",
751
- lodStrategy: "automatic",
752
- culling: { mode: "back", frustum: true, occlusion: true },
753
- batching: { instancing: true, maxInstanceCount: 2e3 },
754
- textures: {
755
- compression: "dxt",
756
- maxResolution: 2048,
757
- streaming: true,
758
- streamingBudget: 512
759
- },
760
- adaptiveQuality: false,
761
- targetFrameRate: 60
762
- },
763
- ultra: {
764
- targetGPUTier: "ultra",
765
- lodStrategy: "manual",
766
- culling: {
767
- mode: "back",
768
- frustum: true,
769
- occlusion: true,
770
- hierarchicalZ: true
771
- },
772
- batching: { instancing: true, maxInstanceCount: 5e3 },
773
- textures: {
774
- compression: "none",
775
- maxResolution: 4096,
776
- virtualTexturing: true,
777
- streaming: true,
778
- streamingBudget: 1024
779
- },
780
- adaptiveQuality: false,
781
- targetFrameRate: 120
782
- }
783
- };
784
- return { ...this.optimization, ...presets[quality] };
785
- }
786
- /**
787
- * Apply quality preset
788
- */
789
- applyQualityPreset(quality) {
790
- const preset = this.getPresetForQuality(quality);
791
- this.optimization = preset;
792
- }
793
- /**
794
- * Estimate GPU memory usage
795
- */
796
- estimateGPUMemory() {
797
- let textureMemory = 0;
798
- let vertexBuffers = 0;
799
- const maxRes = this.optimization.textures?.maxResolution || 2048;
800
- textureMemory = maxRes * maxRes * 4 / (1024 * 1024);
801
- const instanceCount = this.optimization.batching?.maxInstanceCount || 1e3;
802
- const verticesPerMesh = 1e4;
803
- vertexBuffers = verticesPerMesh * 36 * instanceCount / (1024 * 1024) * 0.1;
804
- return {
805
- textureMemory: Math.round(textureMemory),
806
- vertexBuffers: Math.max(1, Math.round(vertexBuffers)),
807
- // At least 1MB
808
- estimatedTotal: Math.round(textureMemory + Math.max(1, vertexBuffers))
809
- };
810
- }
811
- /**
812
- * Get rendering statistics/info
813
- */
814
- getInfo() {
815
- const tier = this.optimization.targetGPUTier;
816
- const lod = this.optimization.lodStrategy;
817
- const culling = this.optimization.culling?.mode;
818
- const instancing = this.optimization.batching?.instancing ? "yes" : "no";
819
- const memory = this.estimateGPUMemory();
820
- return `Rendering: tier=${tier} | LOD=${lod} | culling=${culling} | instancing=${instancing} | memory=${memory.estimatedTotal}MB`;
821
- }
822
- /**
823
- * Optimize for VR/AR (fixed timestep, fast culling)
824
- */
825
- optimizeForVRAR(targetFPS = 90) {
826
- this.optimization.fixedTimestep = 1 / targetFPS;
827
- this.optimization.targetFrameRate = targetFPS;
828
- this.setOcclusionCulling(true, 50);
829
- this.setInstancing(true, 5e3);
830
- this.setAdaptiveQuality(true, targetFPS);
831
- }
832
- /**
833
- * Optimize for mobile (lower resources)
834
- */
835
- optimizeForMobile() {
836
- this.applyQualityPreset("low");
837
- this.setTextureCompression("astc");
838
- this.setInstancing(true, 256);
839
- }
840
- /**
841
- * Optimize for desktop (higher resources)
842
- */
843
- optimizeForDesktop() {
844
- this.applyQualityPreset("ultra");
845
- this.setTextureCompression("none");
846
- this.setInstancing(true, 5e3);
847
- }
848
- /**
849
- * Dispose and cleanup
850
- */
851
- dispose() {
852
- }
853
- };
854
- }
855
- });
8
+ var chunkJEQ2X3Z6_cjs = require('./chunk-JEQ2X3Z6.cjs');
856
9
 
857
10
  // src/HoloScript2DParser.ts
858
11
  var UI_SECURITY_CONFIG = {
@@ -1089,9 +242,7 @@ var HOLOSCRIPT_SECURITY_CONFIG = {
1089
242
  "__proto__",
1090
243
  "fs",
1091
244
  "child_process",
1092
- "exec",
1093
245
  "spawn",
1094
- "fetch",
1095
246
  "xmlhttprequest"
1096
247
  ],
1097
248
  allowedUIElements: [
@@ -1127,7 +278,7 @@ var HoloScriptParser = class {
1127
278
  });
1128
279
  return [];
1129
280
  }
1130
- const rawTokens = this.tokenizeCommand(command.command.toLowerCase());
281
+ const rawTokens = this.tokenizeCommand(command.command);
1131
282
  const tokens = this.sanitizeTokens(rawTokens);
1132
283
  if (tokens.length === 0) return [];
1133
284
  if (tokens.length > HOLOSCRIPT_SECURITY_CONFIG.maxTokens) {
@@ -1137,7 +288,7 @@ var HoloScriptParser = class {
1137
288
  });
1138
289
  return [];
1139
290
  }
1140
- const commandType = tokens[0];
291
+ const commandType = tokens[0].toLowerCase();
1141
292
  if ((commandType === "create" || commandType === "add") && tokens.length > 1) {
1142
293
  const elementType = tokens[1];
1143
294
  if (HOLOSCRIPT_SECURITY_CONFIG.allowedUIElements.includes(elementType)) {
@@ -1157,6 +308,21 @@ var HoloScriptParser = class {
1157
308
  return this.parseDebugCommand(tokens.slice(1));
1158
309
  case "visualize":
1159
310
  return this.parseVisualizeCommand(tokens.slice(1));
311
+ case "composition":
312
+ return this.parseComposition(tokens.slice(1));
313
+ case "environment":
314
+ return this.parseEnvironment(tokens.slice(1));
315
+ case "template":
316
+ return this.parseTemplate(tokens.slice(1));
317
+ case "@state":
318
+ return this.parseStateDirective(tokens.slice(1));
319
+ case "every":
320
+ case "on_user_gesture":
321
+ return this.parseGlobalHandler(commandType, tokens.slice(1));
322
+ case "scale":
323
+ return this.parseScale(tokens.slice(1));
324
+ case "focus":
325
+ return this.parseFocus(tokens.slice(1));
1160
326
  default:
1161
327
  return this.parseGenericCommand(tokens);
1162
328
  }
@@ -1195,19 +361,43 @@ var HoloScriptParser = class {
1195
361
  if (tokens.length < 2) return [];
1196
362
  const shape = tokens[0];
1197
363
  const name = tokens[1];
364
+ let res = [];
1198
365
  switch (shape) {
1199
366
  case "orb":
1200
367
  case "sphere":
1201
- return [this.createOrbNode(name, position)];
368
+ res = [this.createOrbNode(name, position)];
369
+ const orbProps = this.parseProperties(tokens.slice(2));
370
+ res[0].properties = orbProps;
371
+ break;
1202
372
  case "function":
1203
- return [this.createFunctionNode(name, tokens.slice(2), position)];
373
+ res = [this.createFunctionNode(name, tokens.slice(2), position)];
374
+ break;
1204
375
  case "gate":
1205
- return [this.createGateNode(name, tokens.slice(2), position)];
376
+ res = [this.createGateNode(name, tokens.slice(2), position)];
377
+ break;
1206
378
  case "stream":
1207
- return [this.createStreamNode(name, tokens.slice(2), position)];
379
+ res = [this.createStreamNode(name, tokens.slice(2), position)];
380
+ break;
381
+ case "server":
382
+ res = [this.createServerNode(tokens.slice(1), position)];
383
+ break;
384
+ case "database":
385
+ res = [this.createDatabaseNode(tokens.slice(1), position)];
386
+ break;
387
+ case "fetch":
388
+ res = [this.createFetchNode(tokens.slice(1), position)];
389
+ break;
1208
390
  default:
1209
- return [this.createGenericNode(shape, name, position)];
391
+ res = [this.createGenericNode(shape, name, position)];
392
+ break;
393
+ }
394
+ if (res.length > 0) {
395
+ const directives = this.extractDirectives(tokens.slice(2));
396
+ if (directives.length > 0) {
397
+ res[0].directives = directives;
398
+ }
1210
399
  }
400
+ return res;
1211
401
  }
1212
402
  parseConnectCommand(tokens) {
1213
403
  if (tokens.length < 3) return [];
@@ -1316,6 +506,61 @@ var HoloScriptParser = class {
1316
506
  }
1317
507
  };
1318
508
  }
509
+ createServerNode(params, position) {
510
+ const portIndex = params.indexOf("port");
511
+ const port = portIndex !== -1 ? parseInt(params[portIndex + 1]) : 3e3;
512
+ const routesIndex = params.indexOf("routes");
513
+ const routes = routesIndex !== -1 ? params[routesIndex + 1].split(",") : [];
514
+ return {
515
+ type: "server",
516
+ port,
517
+ routes,
518
+ position: position || { x: 0, y: 0, z: 0 },
519
+ hologram: {
520
+ shape: "cube",
521
+ color: "#000000",
522
+ // Black box
523
+ size: 2,
524
+ glow: true,
525
+ interactive: false
526
+ }
527
+ };
528
+ }
529
+ createDatabaseNode(params, position) {
530
+ const queryIndex = params.indexOf("query");
531
+ const query = queryIndex !== -1 ? params.slice(queryIndex + 1).join(" ") : "";
532
+ return {
533
+ type: "database",
534
+ query,
535
+ position: position || { x: 0, y: 0, z: 0 },
536
+ hologram: {
537
+ shape: "cylinder",
538
+ color: "#ffd700",
539
+ // Gold
540
+ size: 1.5,
541
+ glow: true,
542
+ interactive: true
543
+ }
544
+ };
545
+ }
546
+ createFetchNode(params, position) {
547
+ const urlIndex = params.indexOf("url");
548
+ const url = urlIndex !== -1 ? params[urlIndex + 1] : "";
549
+ return {
550
+ type: "fetch",
551
+ url,
552
+ method: "GET",
553
+ position: position || { x: 0, y: 0, z: 0 },
554
+ hologram: {
555
+ shape: "orb",
556
+ color: "#00ff00",
557
+ // Green
558
+ size: 0.8,
559
+ glow: true,
560
+ interactive: true
561
+ }
562
+ };
563
+ }
1319
564
  parsePinchGesture(gesture) {
1320
565
  return [{
1321
566
  type: "create",
@@ -1346,7 +591,7 @@ var HoloScriptParser = class {
1346
591
  }];
1347
592
  }
1348
593
  tokenizeCommand(command) {
1349
- return command.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((token) => token.length > 0);
594
+ return command.replace(/[^\w\s.,:/=?&"'*()\[\]@%${}-]/g, " ").split(/\s+/).filter((token) => token.length > 0);
1350
595
  }
1351
596
  sanitizeTokens(tokens) {
1352
597
  return tokens.filter((token) => {
@@ -1388,6 +633,167 @@ var HoloScriptParser = class {
1388
633
  hologram: { shape: "orb", color: "#808080", size: 0.5, glow: false, interactive: true }
1389
634
  }];
1390
635
  }
636
+ parseComposition(tokens) {
637
+ const name = tokens[0] || "unnamed_composition";
638
+ return [{
639
+ type: "composition",
640
+ name,
641
+ children: [],
642
+ position: { x: 0, y: 0, z: 0 }
643
+ }];
644
+ }
645
+ parseEnvironment(tokens) {
646
+ const settings = {};
647
+ if (tokens.includes("fog")) settings.fog = true;
648
+ if (tokens.includes("audio")) settings.audio = tokens[tokens.indexOf("audio") + 1];
649
+ if (tokens.includes("theme")) settings.theme = tokens[tokens.indexOf("theme") + 1];
650
+ return [{
651
+ type: "environment",
652
+ settings
653
+ }];
654
+ }
655
+ parseTemplate(tokens) {
656
+ const name = tokens[0] || "template";
657
+ const parameters = tokens.slice(1).filter((t) => t !== "with" && t !== "params");
658
+ return [{
659
+ type: "template",
660
+ name,
661
+ parameters,
662
+ body: []
663
+ }];
664
+ }
665
+ parseGlobalHandler(type, tokens) {
666
+ return [{
667
+ type: "global_handler",
668
+ handlerType: type === "every" ? "every" : "on_gesture",
669
+ config: { value: tokens[0] },
670
+ action: tokens.slice(1).join(" ")
671
+ }];
672
+ }
673
+ parseScale(tokens) {
674
+ const magnitude = tokens[0] || "standard";
675
+ const multipliers = {
676
+ "galactic": 1e6,
677
+ "macro": 1e3,
678
+ "standard": 1,
679
+ "micro": 1e-3,
680
+ "atomic": 1e-6
681
+ };
682
+ return [{
683
+ type: "scale",
684
+ magnitude,
685
+ multiplier: multipliers[magnitude] || 1,
686
+ body: []
687
+ }];
688
+ }
689
+ parseFocus(tokens) {
690
+ return [{
691
+ type: "focus",
692
+ target: tokens[0] || "origin",
693
+ body: []
694
+ }];
695
+ }
696
+ // ============================================================================
697
+ // HS+ Directive Parsing
698
+ // ============================================================================
699
+ parseStateDirective(tokens) {
700
+ const body = {};
701
+ for (let i = 0; i < tokens.length; i += 2) {
702
+ if (tokens[i] && tokens[i + 1]) {
703
+ const key = tokens[i].replace(":", "");
704
+ const val = this.parseLiteral(tokens[i + 1]);
705
+ body[key] = val;
706
+ }
707
+ }
708
+ return [{
709
+ type: "state-declaration",
710
+ directives: [{ type: "state", body }]
711
+ }];
712
+ }
713
+ extractDirectives(tokens) {
714
+ const directives = [];
715
+ for (let i = 0; i < tokens.length; i++) {
716
+ const token = tokens[i];
717
+ if (token.startsWith("@")) {
718
+ const name = token.slice(1);
719
+ if (this.isTrait(name)) {
720
+ let config = {};
721
+ if (tokens[i + 1] === "{") {
722
+ const closingIndex = this.findClosingBrace(tokens, i + 1);
723
+ if (closingIndex !== -1) {
724
+ config = this.parseProperties(tokens.slice(i + 2, closingIndex));
725
+ i = closingIndex;
726
+ }
727
+ }
728
+ directives.push({
729
+ type: "trait",
730
+ name,
731
+ config
732
+ });
733
+ } else if (this.isLifecycleHook(name)) {
734
+ directives.push({
735
+ type: "lifecycle",
736
+ hook: name,
737
+ body: tokens[i + 1] || ""
738
+ // Assume next token is body for now
739
+ });
740
+ i++;
741
+ }
742
+ }
743
+ }
744
+ return directives;
745
+ }
746
+ isTrait(name) {
747
+ const traits = ["grabbable", "throwable", "pointable", "hoverable", "scalable", "rotatable", "stackable", "snappable", "breakable"];
748
+ return traits.includes(name);
749
+ }
750
+ isLifecycleHook(name) {
751
+ const hooks = ["on_mount", "on_unmount", "on_update", "on_data_update", "on_grab", "on_release", "on_click"];
752
+ return hooks.includes(name);
753
+ }
754
+ parseLiteral(val) {
755
+ if (val === "true") return true;
756
+ if (val === "false") return false;
757
+ if (val === "null") return null;
758
+ if (!isNaN(Number(val))) return Number(val);
759
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
760
+ return val.slice(1, -1);
761
+ }
762
+ return val;
763
+ }
764
+ parseProperties(tokens) {
765
+ const props = {};
766
+ for (let i = 0; i < tokens.length; i++) {
767
+ const token = tokens[i];
768
+ if (token === "{" || token === "}") continue;
769
+ if (token.startsWith("@")) break;
770
+ if (token.endsWith(":")) {
771
+ const key = token.slice(0, -1);
772
+ const val = tokens[i + 1];
773
+ if (val) {
774
+ props[key] = this.parseLiteral(val);
775
+ i++;
776
+ }
777
+ } else if (tokens[i + 1] === ":") {
778
+ const key = token;
779
+ const val = tokens[i + 2];
780
+ if (val) {
781
+ props[key] = this.parseLiteral(val);
782
+ i += 2;
783
+ }
784
+ }
785
+ }
786
+ return props;
787
+ }
788
+ findClosingBrace(tokens, startIndex) {
789
+ let depth = 0;
790
+ for (let i = startIndex; i < tokens.length; i++) {
791
+ if (tokens[i] === "{") depth++;
792
+ else if (tokens[i] === "}") depth--;
793
+ if (depth === 0) return i;
794
+ }
795
+ return -1;
796
+ }
1391
797
  getAST() {
1392
798
  return [...this.ast];
1393
799
  }
@@ -1417,8 +823,9 @@ var HoloScriptParser = class {
1417
823
  }
1418
824
  };
1419
825
 
1420
- // src/parser/HoloScriptPlusParser.ts
826
+ // src/constants.ts
1421
827
  var VR_TRAITS = [
828
+ // Core VR Interaction Traits
1422
829
  "grabbable",
1423
830
  "throwable",
1424
831
  "pointable",
@@ -1427,7 +834,56 @@ var VR_TRAITS = [
1427
834
  "rotatable",
1428
835
  "stackable",
1429
836
  "snappable",
1430
- "breakable"
837
+ "breakable",
838
+ "stretchable",
839
+ "moldable",
840
+ // Humanoid/Avatar Traits
841
+ "skeleton",
842
+ "body",
843
+ "face",
844
+ "expressive",
845
+ "hair",
846
+ "clothing",
847
+ "hands",
848
+ "character_voice",
849
+ "locomotion",
850
+ "poseable",
851
+ "morph",
852
+ // Networking & AI
853
+ "networked",
854
+ "proactive",
855
+ // Media Production Traits
856
+ "recordable",
857
+ "streamable",
858
+ "camera",
859
+ "video",
860
+ // Analytics & Research Traits
861
+ "trackable",
862
+ "survey",
863
+ "abtest",
864
+ "heatmap",
865
+ // Social & Viral Traits
866
+ "shareable",
867
+ "embeddable",
868
+ "qr",
869
+ "collaborative",
870
+ // Effects Traits
871
+ "particle",
872
+ "transition",
873
+ "filter",
874
+ "trail",
875
+ // Audio Traits
876
+ "spatial_audio",
877
+ "voice",
878
+ "reactive_audio",
879
+ // AI & Generative Traits
880
+ "narrator",
881
+ "responsive",
882
+ "procedural",
883
+ "captioned",
884
+ // Timeline & Choreography Traits
885
+ "timeline",
886
+ "choreography"
1431
887
  ];
1432
888
  var LIFECYCLE_HOOKS = [
1433
889
  // Standard lifecycle
@@ -1452,8 +908,152 @@ var LIFECYCLE_HOOKS = [
1452
908
  "on_trigger_hold",
1453
909
  "on_trigger_release",
1454
910
  "on_grip_hold",
1455
- "on_grip_release"
911
+ "on_grip_release",
912
+ // Stretchable/Moldable hooks
913
+ "on_stretch",
914
+ "on_sculpt",
915
+ // Humanoid/Avatar hooks
916
+ "on_pose_change",
917
+ "on_expression_change",
918
+ "on_gesture",
919
+ "on_speak",
920
+ "on_pose_save",
921
+ "on_morph_change",
922
+ // Media Production hooks
923
+ "on_record_start",
924
+ "on_record_stop",
925
+ "on_record_pause",
926
+ "on_stream_start",
927
+ "on_stream_stop",
928
+ "on_viewer_join",
929
+ "on_viewer_leave",
930
+ "on_chat_message",
931
+ "on_camera_switch",
932
+ "on_video_end",
933
+ "on_video_error",
934
+ // Analytics hooks
935
+ "on_track_event",
936
+ "on_survey_start",
937
+ "on_survey_complete",
938
+ "on_survey_skip",
939
+ "on_variant_assigned",
940
+ "on_conversion",
941
+ "on_hotspot_detected",
942
+ // Social hooks
943
+ "on_share",
944
+ "on_share_complete",
945
+ "on_embed",
946
+ "on_scan",
947
+ "on_user_join",
948
+ "on_user_leave",
949
+ "on_draw_stroke",
950
+ "on_object_lock",
951
+ "on_object_unlock",
952
+ // Effects hooks
953
+ "on_particle_spawn",
954
+ "on_particle_death",
955
+ "on_transition_start",
956
+ "on_transition_complete",
957
+ "on_filter_change",
958
+ // Audio hooks
959
+ "on_audio_start",
960
+ "on_audio_end",
961
+ "on_voice_command",
962
+ "on_speech_start",
963
+ "on_speech_end",
964
+ "on_beat",
965
+ "on_frequency_peak",
966
+ // AI hooks
967
+ "on_narration_start",
968
+ "on_narration_end",
969
+ "on_user_question",
970
+ "on_response_ready",
971
+ "on_emotion_change",
972
+ "on_generation_complete",
973
+ // Timeline hooks
974
+ "on_timeline_start",
975
+ "on_timeline_complete",
976
+ "on_keyframe_hit",
977
+ "on_keyframe_add",
978
+ "on_beat_sync",
979
+ "on_move_complete"
980
+ ];
981
+
982
+ // src/HoloScriptValidator.ts
983
+ var _HoloScriptValidator = class _HoloScriptValidator {
984
+ constructor() {
985
+ this.parser = new chunkT57ZL7KR_cjs.HoloScriptCodeParser();
986
+ }
987
+ /**
988
+ * Validates source code and returns a list of errors.
989
+ */
990
+ validate(code) {
991
+ const errors = [];
992
+ try {
993
+ this.parser.parse(code);
994
+ } catch (e) {
995
+ errors.push({
996
+ line: e.line || 1,
997
+ // Fallback if parser doesn't provide line
998
+ column: e.column || 1,
999
+ message: e.message || "Syntax Error",
1000
+ severity: "error"
1001
+ });
1002
+ return errors;
1003
+ }
1004
+ const lines = code.split("\n");
1005
+ lines.forEach((line, index) => {
1006
+ const lineNum = index + 1;
1007
+ const trimmed = line.trim();
1008
+ if (!trimmed || trimmed.startsWith("//")) return;
1009
+ if (trimmed.startsWith("@")) {
1010
+ const match = trimmed.match(/^@(\w+)/);
1011
+ if (match) {
1012
+ const directive = match[1];
1013
+ if (!_HoloScriptValidator.VALID_DIRECTIVES.includes(directive)) {
1014
+ errors.push({
1015
+ line: lineNum,
1016
+ column: line.indexOf("@") + 1,
1017
+ message: `Unknown directive '@${directive}'. Allowed: ${_HoloScriptValidator.VALID_DIRECTIVES.join(", ")}`,
1018
+ severity: "warning"
1019
+ // directives might be custom, so warning for now
1020
+ });
1021
+ }
1022
+ }
1023
+ }
1024
+ if (trimmed.endsWith("{")) {
1025
+ const firstWord = trimmed.split(" ")[0];
1026
+ if (line.match(/^[a-z]+\s+[\w#]+\s*\{$/)) {
1027
+ if (!_HoloScriptValidator.VALID_KEYWORDS.includes(firstWord) && !trimmed.startsWith("trait")) ;
1028
+ }
1029
+ }
1030
+ });
1031
+ return errors;
1032
+ }
1033
+ };
1034
+ // Whitelists
1035
+ _HoloScriptValidator.VALID_DIRECTIVES = [
1036
+ "trait",
1037
+ "state",
1038
+ "on_enter",
1039
+ "on_exit",
1040
+ "on_mount",
1041
+ "on_tick",
1042
+ "on_create",
1043
+ "bot_config",
1044
+ "lifecycle"
1456
1045
  ];
1046
+ _HoloScriptValidator.VALID_KEYWORDS = [
1047
+ "world",
1048
+ "scene",
1049
+ "prefab",
1050
+ "object",
1051
+ "import",
1052
+ "export"
1053
+ ];
1054
+ var HoloScriptValidator = _HoloScriptValidator;
1055
+
1056
+ // src/parser/HoloScriptPlusParser.ts
1457
1057
  var Lexer = class {
1458
1058
  constructor(source) {
1459
1059
  this.pos = 0;
@@ -1847,6 +1447,10 @@ var HoloScriptPlusParser = class {
1847
1447
  this.pos = 0;
1848
1448
  const lexer = new Lexer(source);
1849
1449
  this.tokens = lexer.tokenize();
1450
+ try {
1451
+ chunkJEQ2X3Z6_cjs.__require("fs").writeFileSync("tokens.log", JSON.stringify(this.tokens, null, 2));
1452
+ } catch (e) {
1453
+ }
1850
1454
  const root = this.parseDocument();
1851
1455
  const ast = {
1852
1456
  type: "Program",
@@ -1884,6 +1488,20 @@ var HoloScriptPlusParser = class {
1884
1488
  }
1885
1489
  this.skipNewlines();
1886
1490
  }
1491
+ if (this.check("EOF") && directives.length > 0) {
1492
+ return {
1493
+ type: "fragment",
1494
+ id: "root",
1495
+ properties: {},
1496
+ directives,
1497
+ children: [],
1498
+ traits: /* @__PURE__ */ new Map(),
1499
+ loc: {
1500
+ start: { line: 1, column: 1 },
1501
+ end: { line: this.current().line, column: this.current().column }
1502
+ }
1503
+ };
1504
+ }
1887
1505
  const root = this.parseNode();
1888
1506
  root.directives = [...directives, ...root.directives];
1889
1507
  return root;
@@ -2017,6 +1635,20 @@ var HoloScriptPlusParser = class {
2017
1635
  const body = this.parseControlFlowBody();
2018
1636
  return { type: "for", variable, iterable, body };
2019
1637
  }
1638
+ if (name === "forEach") {
1639
+ this.hasControlFlow = true;
1640
+ const variable = this.expect("IDENTIFIER", "Expected variable name").value;
1641
+ this.expect("IDENTIFIER", 'Expected "in"');
1642
+ const collection = this.parseInlineExpression();
1643
+ const body = this.parseControlFlowBody();
1644
+ return { type: "forEach", variable, collection, body };
1645
+ }
1646
+ if (name === "while") {
1647
+ this.hasControlFlow = true;
1648
+ const condition = this.parseInlineExpression();
1649
+ const body = this.parseControlFlowBody();
1650
+ return { type: "while", condition, body };
1651
+ }
2020
1652
  if (name === "if") {
2021
1653
  this.hasControlFlow = true;
2022
1654
  const condition = this.parseInlineExpression();
@@ -2049,6 +1681,39 @@ var HoloScriptPlusParser = class {
2049
1681
  this.imports.push({ path, alias });
2050
1682
  return { type: "import", path, alias };
2051
1683
  }
1684
+ if (name === "external_api") {
1685
+ const config = this.parseTraitConfig();
1686
+ const url = config.url || "";
1687
+ const method = config.method || "GET";
1688
+ const interval = config.interval || "0s";
1689
+ let body = [];
1690
+ if (this.check("LBRACE")) {
1691
+ body = this.parseControlFlowBody();
1692
+ }
1693
+ return { type: "external_api", url, method, interval, body };
1694
+ }
1695
+ if (name === "generate") {
1696
+ const config = this.parseTraitConfig();
1697
+ const prompt = config.prompt || "";
1698
+ const context = config.context || "";
1699
+ const target = config.target || "children";
1700
+ return { type: "generate", prompt, context, target };
1701
+ }
1702
+ if (name === "npc") {
1703
+ try {
1704
+ chunkJEQ2X3Z6_cjs.__require("fs").appendFileSync("debug_parser.log", `ENTERED NPC BLOCK. Name length: ${name.length}
1705
+ `);
1706
+ } catch (e) {
1707
+ }
1708
+ const npcName = this.expect("STRING", "Expected NPC name").value;
1709
+ const props = this.parsePropsBlock();
1710
+ return { type: "npc", name: npcName, props };
1711
+ }
1712
+ if (name === "dialog") {
1713
+ const dialogName = this.expect("STRING", "Expected dialog name").value;
1714
+ const { props, options } = this.parseDialogBlock();
1715
+ return { type: "dialog", name: dialogName, props, options };
1716
+ }
2052
1717
  if (this.options.strict) {
2053
1718
  this.error(`Unknown directive @${name}`);
2054
1719
  } else {
@@ -2056,32 +1721,87 @@ var HoloScriptPlusParser = class {
2056
1721
  }
2057
1722
  return null;
2058
1723
  }
2059
- parseTraitConfig() {
2060
- const config = {};
2061
- if (this.check("LPAREN")) {
1724
+ parsePropsBlock() {
1725
+ this.skipNewlines();
1726
+ const props = {};
1727
+ if (this.check("LBRACE")) {
2062
1728
  this.advance();
2063
- while (!this.check("RPAREN") && !this.check("EOF")) {
1729
+ this.skipNewlines();
1730
+ while (!this.check("RBRACE") && !this.check("EOF")) {
2064
1731
  const key = this.expect("IDENTIFIER", "Expected property name").value;
2065
1732
  if (this.check("COLON") || this.check("EQUALS")) {
2066
1733
  this.advance();
2067
- config[key] = this.parseValue();
1734
+ props[key] = this.parseValue();
2068
1735
  } else {
2069
- config[key] = true;
1736
+ props[key] = true;
2070
1737
  }
2071
- if (this.check("COMMA")) this.advance();
1738
+ this.skipNewlines();
2072
1739
  }
2073
- this.expect("RPAREN", "Expected )");
1740
+ this.expect("RBRACE", "Expected }");
2074
1741
  }
2075
- return config;
1742
+ return props;
2076
1743
  }
2077
- parseStateBlock() {
2078
- const state = {};
1744
+ parseDialogBlock() {
1745
+ this.skipNewlines();
1746
+ const props = {};
1747
+ const options = [];
2079
1748
  if (this.check("LBRACE")) {
2080
1749
  this.advance();
2081
1750
  this.skipNewlines();
2082
1751
  while (!this.check("RBRACE") && !this.check("EOF")) {
2083
- const key = this.expect("IDENTIFIER", "Expected state variable name").value;
2084
- if (this.check("COLON") || this.check("EQUALS")) {
1752
+ if (this.check("IDENTIFIER") && this.current().value === "option") {
1753
+ this.advance();
1754
+ const text = this.expect("STRING", "Expected option text").value;
1755
+ this.expect("ARROW", "Expected ->");
1756
+ let target;
1757
+ if (this.check("AT")) {
1758
+ const d = this.parseDirective();
1759
+ target = { type: "directive", value: d };
1760
+ } else {
1761
+ target = this.expect("STRING", "Expected target ID").value;
1762
+ }
1763
+ options.push({ text, target });
1764
+ } else {
1765
+ const key = this.expect("IDENTIFIER", "Expected property name").value;
1766
+ if (this.check("COLON") || this.check("EQUALS")) {
1767
+ this.advance();
1768
+ props[key] = this.parseValue();
1769
+ } else {
1770
+ props[key] = true;
1771
+ }
1772
+ }
1773
+ this.skipNewlines();
1774
+ }
1775
+ this.expect("RBRACE", "Expected }");
1776
+ }
1777
+ return { props, options };
1778
+ }
1779
+ parseTraitConfig() {
1780
+ const config = {};
1781
+ if (this.check("LPAREN")) {
1782
+ this.advance();
1783
+ while (!this.check("RPAREN") && !this.check("EOF")) {
1784
+ const key = this.expect("IDENTIFIER", "Expected property name").value;
1785
+ if (this.check("COLON") || this.check("EQUALS")) {
1786
+ this.advance();
1787
+ config[key] = this.parseValue();
1788
+ } else {
1789
+ config[key] = true;
1790
+ }
1791
+ if (this.check("COMMA")) this.advance();
1792
+ }
1793
+ this.expect("RPAREN", "Expected )");
1794
+ }
1795
+ return config;
1796
+ }
1797
+ parseStateBlock() {
1798
+ const state = {};
1799
+ if (this.check("LBRACE")) {
1800
+ this.advance();
1801
+ this.skipNewlines();
1802
+ while (!this.check("RBRACE") && !this.check("EOF")) {
1803
+ const key = this.expect("IDENTIFIER", "Expected state variable name").value;
1804
+ if (this.check("COLON") || this.check("EQUALS")) {
2085
1805
  this.advance();
2086
1806
  state[key] = this.parseValue();
2087
1807
  } else {
@@ -2279,10 +1999,825 @@ function parse(source, options) {
2279
1999
  return parser.parse(source);
2280
2000
  }
2281
2001
 
2002
+ // src/traits/MaterialTrait.ts
2003
+ var MaterialTrait = class {
2004
+ constructor(config) {
2005
+ this.textureCache = /* @__PURE__ */ new Map();
2006
+ this.material = {
2007
+ ...{ type: "pbr" },
2008
+ ...config
2009
+ };
2010
+ }
2011
+ /**
2012
+ * Get material properties
2013
+ */
2014
+ getMaterial() {
2015
+ return { ...this.material };
2016
+ }
2017
+ /**
2018
+ * Update material property
2019
+ */
2020
+ setProperty(key, value) {
2021
+ this.material[key] = value;
2022
+ }
2023
+ /**
2024
+ * Get PBR properties
2025
+ */
2026
+ getPBRProperties() {
2027
+ return this.material.pbr;
2028
+ }
2029
+ /**
2030
+ * Update PBR material
2031
+ */
2032
+ updatePBR(pbr) {
2033
+ if (!this.material.pbr) {
2034
+ this.material.pbr = {
2035
+ baseColor: { r: 1, g: 1, b: 1 },
2036
+ metallic: 0,
2037
+ roughness: 0.5
2038
+ };
2039
+ }
2040
+ this.material.pbr = { ...this.material.pbr, ...pbr };
2041
+ }
2042
+ /**
2043
+ * Add texture map
2044
+ */
2045
+ addTexture(texture) {
2046
+ if (!this.material.textures) {
2047
+ this.material.textures = [];
2048
+ }
2049
+ this.material.textures.push(texture);
2050
+ }
2051
+ /**
2052
+ * Get all textures
2053
+ */
2054
+ getTextures() {
2055
+ return [...this.material.textures || []];
2056
+ }
2057
+ /**
2058
+ * Clear texture cache (for memory optimization)
2059
+ */
2060
+ clearTextureCache() {
2061
+ this.textureCache.clear();
2062
+ }
2063
+ /**
2064
+ * Get shader code if custom
2065
+ */
2066
+ getCustomShader() {
2067
+ return this.material.customShader;
2068
+ }
2069
+ /**
2070
+ * Set custom shader
2071
+ */
2072
+ setCustomShader(shader) {
2073
+ this.material.customShader = shader;
2074
+ }
2075
+ /**
2076
+ * Get optimization hints
2077
+ */
2078
+ getOptimization() {
2079
+ return this.material.optimization;
2080
+ }
2081
+ /**
2082
+ * Enable/disable texture streaming
2083
+ */
2084
+ setTextureStreaming(enabled) {
2085
+ if (!this.material.optimization) {
2086
+ this.material.optimization = {};
2087
+ }
2088
+ this.material.optimization.streamTextures = enabled;
2089
+ }
2090
+ /**
2091
+ * Set texture compression
2092
+ */
2093
+ setCompression(compression) {
2094
+ if (!this.material.optimization) {
2095
+ this.material.optimization = {};
2096
+ }
2097
+ this.material.optimization.compression = compression;
2098
+ }
2099
+ /**
2100
+ * Enable material instancing for performance
2101
+ */
2102
+ setInstanced(instanced) {
2103
+ if (!this.material.optimization) {
2104
+ this.material.optimization = {};
2105
+ }
2106
+ this.material.optimization.instanced = instanced;
2107
+ }
2108
+ /**
2109
+ * Dispose and cleanup
2110
+ */
2111
+ dispose() {
2112
+ this.textureCache.clear();
2113
+ }
2114
+ };
2115
+ function createMaterialTrait(config) {
2116
+ return new MaterialTrait(config);
2117
+ }
2118
+ var MATERIAL_PRESETS = {
2119
+ /** Shiny metal */
2120
+ chrome: () => ({
2121
+ type: "pbr",
2122
+ pbr: {
2123
+ baseColor: { r: 0.77, g: 0.77, b: 0.77 },
2124
+ metallic: 1,
2125
+ roughness: 0.1
2126
+ }
2127
+ }),
2128
+ /** Rough plastic */
2129
+ plastic: () => ({
2130
+ type: "pbr",
2131
+ pbr: {
2132
+ baseColor: { r: 1, g: 1, b: 1 },
2133
+ metallic: 0,
2134
+ roughness: 0.8
2135
+ }
2136
+ }),
2137
+ /** Wood texture */
2138
+ wood: () => ({
2139
+ type: "pbr",
2140
+ pbr: {
2141
+ baseColor: { r: 0.6, g: 0.4, b: 0.2 },
2142
+ metallic: 0,
2143
+ roughness: 0.4
2144
+ }
2145
+ }),
2146
+ /** Glass */
2147
+ glass: () => ({
2148
+ type: "transparent",
2149
+ blendMode: "blend",
2150
+ pbr: {
2151
+ baseColor: { r: 1, g: 1, b: 1, a: 0.3 },
2152
+ metallic: 0,
2153
+ roughness: 0,
2154
+ ior: 1.5,
2155
+ transmission: 0.9
2156
+ }
2157
+ }),
2158
+ /** Emissive (glowing) */
2159
+ emissive: () => ({
2160
+ type: "pbr",
2161
+ pbr: {
2162
+ baseColor: { r: 0, g: 1, b: 0 },
2163
+ metallic: 0,
2164
+ roughness: 1,
2165
+ emission: {
2166
+ color: { r: 0, g: 1, b: 0 },
2167
+ intensity: 2
2168
+ }
2169
+ }
2170
+ }),
2171
+ /** Skin material */
2172
+ skin: () => ({
2173
+ type: "pbr",
2174
+ pbr: {
2175
+ baseColor: { r: 1, g: 0.8, b: 0.7 },
2176
+ metallic: 0,
2177
+ roughness: 0.5,
2178
+ ambientOcclusion: 0.8
2179
+ }
2180
+ })
2181
+ };
2182
+
2183
+ // src/traits/LightingTrait.ts
2184
+ var LightingTrait = class {
2185
+ constructor(config) {
2186
+ this.lights = /* @__PURE__ */ new Map();
2187
+ this.lightIdCounter = 0;
2188
+ this.globalIllumination = {
2189
+ enabled: true,
2190
+ intensity: 1,
2191
+ skyColor: { r: 0.5, g: 0.7, b: 1 },
2192
+ skyIntensity: 1,
2193
+ groundColor: { r: 0.4, g: 0.4, b: 0.4 },
2194
+ groundIntensity: 0.5,
2195
+ probes: true,
2196
+ indirectDiffuse: 1,
2197
+ indirectSpecular: 1,
2198
+ aoIntensity: 1,
2199
+ screenSpaceAO: true,
2200
+ ...config
2201
+ };
2202
+ }
2203
+ /**
2204
+ * Add a light to the scene
2205
+ */
2206
+ addLight(light) {
2207
+ const id = light.name || `light_${this.lightIdCounter++}`;
2208
+ this.lights.set(id, light);
2209
+ return id;
2210
+ }
2211
+ /**
2212
+ * Get light by ID
2213
+ */
2214
+ getLight(id) {
2215
+ return this.lights.get(id);
2216
+ }
2217
+ /**
2218
+ * Get all lights
2219
+ */
2220
+ getLights() {
2221
+ return Array.from(this.lights.values());
2222
+ }
2223
+ /**
2224
+ * Get lights by type
2225
+ */
2226
+ getLightsByType(type) {
2227
+ return Array.from(this.lights.values()).filter((l) => l.type === type);
2228
+ }
2229
+ /**
2230
+ * Update light properties
2231
+ */
2232
+ updateLight(id, updates) {
2233
+ const light = this.lights.get(id);
2234
+ if (!light) return false;
2235
+ this.lights.set(id, { ...light, ...updates });
2236
+ return true;
2237
+ }
2238
+ /**
2239
+ * Remove light
2240
+ */
2241
+ removeLight(id) {
2242
+ return this.lights.delete(id);
2243
+ }
2244
+ /**
2245
+ * Clear all lights
2246
+ */
2247
+ clearLights() {
2248
+ this.lights.clear();
2249
+ }
2250
+ /**
2251
+ * Get global illumination config
2252
+ */
2253
+ getGlobalIllumination() {
2254
+ return { ...this.globalIllumination };
2255
+ }
2256
+ /**
2257
+ * Update global illumination
2258
+ */
2259
+ updateGlobalIllumination(updates) {
2260
+ this.globalIllumination = {
2261
+ ...this.globalIllumination,
2262
+ ...updates
2263
+ };
2264
+ }
2265
+ /**
2266
+ * Enable/disable GI
2267
+ */
2268
+ setGIEnabled(enabled) {
2269
+ this.globalIllumination.enabled = enabled;
2270
+ }
2271
+ /**
2272
+ * Set ambient light colors (skybox mode)
2273
+ */
2274
+ setAmbientLight(skyColor, groundColor, intensity = 1) {
2275
+ this.globalIllumination.skyColor = skyColor;
2276
+ this.globalIllumination.groundColor = groundColor;
2277
+ this.globalIllumination.skyIntensity = intensity;
2278
+ this.globalIllumination.groundIntensity = intensity * 0.5;
2279
+ }
2280
+ /**
2281
+ * Enable/disable screen-space ambient occlusion
2282
+ */
2283
+ setScreenSpaceAO(enabled, intensity = 1) {
2284
+ this.globalIllumination.screenSpaceAO = enabled;
2285
+ this.globalIllumination.aoIntensity = intensity;
2286
+ }
2287
+ /**
2288
+ * Create directional light (sun)
2289
+ */
2290
+ createDirectionalLight(direction, color, intensity = 1, castShadows = true) {
2291
+ const light = {
2292
+ type: "directional",
2293
+ name: `sun_${this.lightIdCounter}`,
2294
+ direction,
2295
+ color,
2296
+ intensity,
2297
+ shadow: castShadows ? {
2298
+ type: "soft",
2299
+ resolution: 2048,
2300
+ cascades: 4,
2301
+ softness: 1
2302
+ } : void 0,
2303
+ volumetric: true,
2304
+ priority: 100
2305
+ };
2306
+ return this.addLight(light);
2307
+ }
2308
+ /**
2309
+ * Create point light
2310
+ */
2311
+ createPointLight(position, color, intensity, range, castShadows = false) {
2312
+ const light = {
2313
+ type: "point",
2314
+ name: `point_${this.lightIdCounter}`,
2315
+ position,
2316
+ color,
2317
+ intensity,
2318
+ range,
2319
+ shadow: castShadows ? {
2320
+ type: "soft",
2321
+ resolution: 512,
2322
+ softness: 0.5
2323
+ } : void 0,
2324
+ priority: 50
2325
+ };
2326
+ return this.addLight(light);
2327
+ }
2328
+ /**
2329
+ * Create spot light
2330
+ */
2331
+ createSpotLight(position, direction, color, intensity, range, spotAngle = 45, castShadows = true) {
2332
+ const light = {
2333
+ type: "spot",
2334
+ name: `spot_${this.lightIdCounter}`,
2335
+ position,
2336
+ direction,
2337
+ color,
2338
+ intensity,
2339
+ range,
2340
+ spotAngle,
2341
+ innerSpotAngle: spotAngle * 0.5,
2342
+ shadow: castShadows ? {
2343
+ type: "soft",
2344
+ resolution: 1024,
2345
+ softness: 0.8
2346
+ } : void 0,
2347
+ priority: 75
2348
+ };
2349
+ return this.addLight(light);
2350
+ }
2351
+ /**
2352
+ * Create area light for soft lighting
2353
+ */
2354
+ createAreaLight(position, color, intensity, width, height) {
2355
+ const light = {
2356
+ type: "area",
2357
+ name: `area_${this.lightIdCounter}`,
2358
+ position,
2359
+ color,
2360
+ intensity,
2361
+ range: Math.max(width, height) * 2,
2362
+ priority: 25
2363
+ };
2364
+ return this.addLight(light);
2365
+ }
2366
+ /**
2367
+ * Get shadow-casting lights
2368
+ */
2369
+ getShadowCastingLights() {
2370
+ return Array.from(this.lights.values()).filter((l) => l.shadow && l.shadow.type !== "none");
2371
+ }
2372
+ /**
2373
+ * Get light count by type
2374
+ */
2375
+ getLightCount() {
2376
+ const counts = {
2377
+ directional: 0,
2378
+ point: 0,
2379
+ spot: 0,
2380
+ area: 0,
2381
+ probe: 0
2382
+ };
2383
+ for (const light of Array.from(this.lights.values())) {
2384
+ counts[light.type]++;
2385
+ }
2386
+ return counts;
2387
+ }
2388
+ /**
2389
+ * Estimate light impact for performance optimization
2390
+ */
2391
+ getPerformanceImpact() {
2392
+ const totalLights = this.lights.size;
2393
+ const shadowCasters = this.getShadowCastingLights().length;
2394
+ let estimatedGPUCost = "low";
2395
+ if (totalLights > 16 || shadowCasters > 4) {
2396
+ estimatedGPUCost = "high";
2397
+ } else if (totalLights > 8 || shadowCasters > 2) {
2398
+ estimatedGPUCost = "medium";
2399
+ }
2400
+ return {
2401
+ totalLights,
2402
+ shadowCasters,
2403
+ estimatedGPUCost
2404
+ };
2405
+ }
2406
+ /**
2407
+ * Get scene complexity info
2408
+ */
2409
+ getSceneInfo() {
2410
+ const counts = this.getLightCount();
2411
+ const impact = this.getPerformanceImpact();
2412
+ return `Lighting: ${counts.directional} dir, ${counts.point} point, ${counts.spot} spot | Shadows: ${impact.shadowCasters} | GPU: ${impact.estimatedGPUCost}`;
2413
+ }
2414
+ /**
2415
+ * Dispose and cleanup
2416
+ */
2417
+ dispose() {
2418
+ this.lights.clear();
2419
+ }
2420
+ };
2421
+ function createLightingTrait(config) {
2422
+ return new LightingTrait(config);
2423
+ }
2424
+ var LIGHTING_PRESETS = {
2425
+ /** Neutral studio lighting */
2426
+ studio: () => ({
2427
+ enabled: true,
2428
+ intensity: 1,
2429
+ skyColor: { r: 0.5, g: 0.5, b: 0.5 },
2430
+ skyIntensity: 0.5,
2431
+ groundColor: { r: 0.3, g: 0.3, b: 0.3 },
2432
+ groundIntensity: 0.3
2433
+ }),
2434
+ /** Bright outdoor lighting */
2435
+ outdoor: () => ({
2436
+ enabled: true,
2437
+ intensity: 1.2,
2438
+ skyColor: { r: 0.7, g: 0.85, b: 1 },
2439
+ skyIntensity: 1,
2440
+ groundColor: { r: 0.4, g: 0.4, b: 0.35 },
2441
+ groundIntensity: 0.6,
2442
+ indirectDiffuse: 1.2
2443
+ }),
2444
+ /** Dim interior lighting */
2445
+ interior: () => ({
2446
+ enabled: true,
2447
+ intensity: 0.6,
2448
+ skyColor: { r: 0.3, g: 0.3, b: 0.35 },
2449
+ skyIntensity: 0.4,
2450
+ groundColor: { r: 0.2, g: 0.2, b: 0.2 },
2451
+ groundIntensity: 0.2
2452
+ }),
2453
+ /** Night scene */
2454
+ night: () => ({
2455
+ enabled: true,
2456
+ intensity: 0.3,
2457
+ skyColor: { r: 0.01, g: 0.01, b: 0.02 },
2458
+ skyIntensity: 0.1,
2459
+ groundColor: { r: 0.02, g: 0.02, b: 0.02 },
2460
+ groundIntensity: 0.05,
2461
+ screenSpaceAO: false
2462
+ }),
2463
+ /** Sunset/golden hour */
2464
+ sunset: () => ({
2465
+ enabled: true,
2466
+ intensity: 1.1,
2467
+ skyColor: { r: 1, g: 0.7, b: 0.3 },
2468
+ skyIntensity: 1,
2469
+ groundColor: { r: 0.6, g: 0.4, b: 0.2 },
2470
+ groundIntensity: 0.8
2471
+ })
2472
+ };
2473
+
2474
+ // src/traits/RenderingTrait.ts
2475
+ var RenderingTrait = class {
2476
+ constructor(config) {
2477
+ this.optimization = {
2478
+ lodStrategy: "automatic",
2479
+ culling: {
2480
+ mode: "back",
2481
+ frustum: true,
2482
+ occlusion: true
2483
+ },
2484
+ batching: {
2485
+ static: true,
2486
+ dynamic: true,
2487
+ instancing: true,
2488
+ maxInstanceCount: 1e3
2489
+ },
2490
+ textures: {
2491
+ streaming: true,
2492
+ compression: "auto",
2493
+ mipmaps: true,
2494
+ maxResolution: 2048
2495
+ },
2496
+ shaders: {
2497
+ simplifiedShaders: true,
2498
+ lodBias: 0
2499
+ },
2500
+ targetGPUTier: "high",
2501
+ adaptiveQuality: true,
2502
+ targetFrameRate: 60,
2503
+ ...config
2504
+ };
2505
+ }
2506
+ /**
2507
+ * Get rendering optimization config
2508
+ */
2509
+ getOptimization() {
2510
+ return JSON.parse(JSON.stringify(this.optimization));
2511
+ }
2512
+ /**
2513
+ * Update rendering configuration
2514
+ */
2515
+ updateOptimization(updates) {
2516
+ this.optimization = { ...this.optimization, ...updates };
2517
+ }
2518
+ /**
2519
+ * Setup LOD levels (3 levels is typical)
2520
+ */
2521
+ setupLODLevels(strategy = "automatic") {
2522
+ const levels = [
2523
+ {
2524
+ level: 0,
2525
+ screenRelativeSize: 0.5,
2526
+ polygonReduction: 1,
2527
+ textureScale: 1
2528
+ },
2529
+ {
2530
+ level: 1,
2531
+ screenRelativeSize: 0.25,
2532
+ polygonReduction: 0.6,
2533
+ disabledFeatures: ["specular"],
2534
+ textureScale: 0.5
2535
+ },
2536
+ {
2537
+ level: 2,
2538
+ screenRelativeSize: 0.1,
2539
+ polygonReduction: 0.3,
2540
+ disabledFeatures: ["specular", "normals"],
2541
+ textureScale: 0.25
2542
+ }
2543
+ ];
2544
+ this.optimization.lodStrategy = strategy;
2545
+ this.optimization.lodLevels = levels;
2546
+ }
2547
+ /**
2548
+ * Get LOD levels
2549
+ */
2550
+ getLODLevels() {
2551
+ return [...this.optimization.lodLevels || []];
2552
+ }
2553
+ /**
2554
+ * Configure culling
2555
+ */
2556
+ setCulling(config) {
2557
+ const defaultCulling = { mode: "back" };
2558
+ this.optimization.culling = {
2559
+ ...defaultCulling,
2560
+ ...this.optimization.culling,
2561
+ ...config
2562
+ };
2563
+ }
2564
+ /**
2565
+ * Enable frustum culling
2566
+ */
2567
+ setFrustumCulling(enabled) {
2568
+ if (!this.optimization.culling) {
2569
+ this.optimization.culling = { mode: "back" };
2570
+ }
2571
+ this.optimization.culling.frustum = enabled;
2572
+ }
2573
+ /**
2574
+ * Enable occlusion culling
2575
+ */
2576
+ setOcclusionCulling(enabled, distance) {
2577
+ if (!this.optimization.culling) {
2578
+ this.optimization.culling = { mode: "back" };
2579
+ }
2580
+ this.optimization.culling.occlusion = enabled;
2581
+ if (distance) {
2582
+ this.optimization.culling.occlusionDistance = distance;
2583
+ }
2584
+ }
2585
+ /**
2586
+ * Configure batching
2587
+ */
2588
+ setBatching(config) {
2589
+ this.optimization.batching = {
2590
+ ...this.optimization.batching,
2591
+ ...config
2592
+ };
2593
+ }
2594
+ /**
2595
+ * Enable GPU instancing
2596
+ */
2597
+ setInstancing(enabled, maxInstances) {
2598
+ if (!this.optimization.batching) {
2599
+ this.optimization.batching = {};
2600
+ }
2601
+ this.optimization.batching.instancing = enabled;
2602
+ if (maxInstances) {
2603
+ this.optimization.batching.maxInstanceCount = maxInstances;
2604
+ }
2605
+ }
2606
+ /**
2607
+ * Configure texture optimization
2608
+ */
2609
+ setTextureOptimization(config) {
2610
+ this.optimization.textures = {
2611
+ ...this.optimization.textures,
2612
+ ...config
2613
+ };
2614
+ }
2615
+ /**
2616
+ * Enable texture streaming
2617
+ */
2618
+ setTextureStreaming(enabled, budgetMB) {
2619
+ if (!this.optimization.textures) {
2620
+ this.optimization.textures = {};
2621
+ }
2622
+ this.optimization.textures.streaming = enabled;
2623
+ if (budgetMB) {
2624
+ this.optimization.textures.streamingBudget = budgetMB;
2625
+ }
2626
+ }
2627
+ /**
2628
+ * Set texture compression
2629
+ */
2630
+ setTextureCompression(compression) {
2631
+ if (!this.optimization.textures) {
2632
+ this.optimization.textures = {};
2633
+ }
2634
+ this.optimization.textures.compression = compression;
2635
+ }
2636
+ /**
2637
+ * Set max texture resolution
2638
+ */
2639
+ setMaxTextureResolution(resolution) {
2640
+ if (!this.optimization.textures) {
2641
+ this.optimization.textures = {};
2642
+ }
2643
+ this.optimization.textures.maxResolution = resolution;
2644
+ }
2645
+ /**
2646
+ * Configure shader optimization
2647
+ */
2648
+ setShaderOptimization(config) {
2649
+ this.optimization.shaders = {
2650
+ ...this.optimization.shaders,
2651
+ ...config
2652
+ };
2653
+ }
2654
+ /**
2655
+ * Set target GPU tier
2656
+ */
2657
+ setTargetGPUTier(tier) {
2658
+ this.optimization.targetGPUTier = tier;
2659
+ }
2660
+ /**
2661
+ * Enable adaptive quality (adjust based on frame rate)
2662
+ */
2663
+ setAdaptiveQuality(enabled, targetFrameRate) {
2664
+ this.optimization.adaptiveQuality = enabled;
2665
+ if (targetFrameRate) {
2666
+ this.optimization.targetFrameRate = targetFrameRate;
2667
+ }
2668
+ }
2669
+ /**
2670
+ * Set fixed timestep for VR/AR
2671
+ */
2672
+ setFixedTimestep(timestep) {
2673
+ this.optimization.fixedTimestep = timestep;
2674
+ }
2675
+ /**
2676
+ * Get rendering preset for quality level
2677
+ */
2678
+ getPresetForQuality(quality) {
2679
+ const presets = {
2680
+ low: {
2681
+ targetGPUTier: "low",
2682
+ lodStrategy: "automatic",
2683
+ culling: { mode: "back", frustum: true, occlusion: false },
2684
+ batching: { instancing: true, maxInstanceCount: 500 },
2685
+ textures: {
2686
+ compression: "astc",
2687
+ maxResolution: 512,
2688
+ streaming: true,
2689
+ streamingBudget: 128
2690
+ },
2691
+ adaptiveQuality: true,
2692
+ targetFrameRate: 30
2693
+ },
2694
+ medium: {
2695
+ targetGPUTier: "medium",
2696
+ lodStrategy: "automatic",
2697
+ culling: { mode: "back", frustum: true, occlusion: true },
2698
+ batching: { instancing: true, maxInstanceCount: 1e3 },
2699
+ textures: {
2700
+ compression: "basis",
2701
+ maxResolution: 1024,
2702
+ streaming: true,
2703
+ streamingBudget: 256
2704
+ },
2705
+ adaptiveQuality: true,
2706
+ targetFrameRate: 60
2707
+ },
2708
+ high: {
2709
+ targetGPUTier: "high",
2710
+ lodStrategy: "automatic",
2711
+ culling: { mode: "back", frustum: true, occlusion: true },
2712
+ batching: { instancing: true, maxInstanceCount: 2e3 },
2713
+ textures: {
2714
+ compression: "dxt",
2715
+ maxResolution: 2048,
2716
+ streaming: true,
2717
+ streamingBudget: 512
2718
+ },
2719
+ adaptiveQuality: false,
2720
+ targetFrameRate: 60
2721
+ },
2722
+ ultra: {
2723
+ targetGPUTier: "ultra",
2724
+ lodStrategy: "manual",
2725
+ culling: {
2726
+ mode: "back",
2727
+ frustum: true,
2728
+ occlusion: true,
2729
+ hierarchicalZ: true
2730
+ },
2731
+ batching: { instancing: true, maxInstanceCount: 5e3 },
2732
+ textures: {
2733
+ compression: "none",
2734
+ maxResolution: 4096,
2735
+ virtualTexturing: true,
2736
+ streaming: true,
2737
+ streamingBudget: 1024
2738
+ },
2739
+ adaptiveQuality: false,
2740
+ targetFrameRate: 120
2741
+ }
2742
+ };
2743
+ return { ...this.optimization, ...presets[quality] };
2744
+ }
2745
+ /**
2746
+ * Apply quality preset
2747
+ */
2748
+ applyQualityPreset(quality) {
2749
+ const preset = this.getPresetForQuality(quality);
2750
+ this.optimization = preset;
2751
+ }
2752
+ /**
2753
+ * Estimate GPU memory usage
2754
+ */
2755
+ estimateGPUMemory() {
2756
+ let textureMemory = 0;
2757
+ let vertexBuffers = 0;
2758
+ const maxRes = this.optimization.textures?.maxResolution || 2048;
2759
+ textureMemory = maxRes * maxRes * 4 / (1024 * 1024);
2760
+ const instanceCount = this.optimization.batching?.maxInstanceCount || 1e3;
2761
+ const verticesPerMesh = 1e4;
2762
+ vertexBuffers = verticesPerMesh * 36 * instanceCount / (1024 * 1024) * 0.1;
2763
+ return {
2764
+ textureMemory: Math.round(textureMemory),
2765
+ vertexBuffers: Math.max(1, Math.round(vertexBuffers)),
2766
+ // At least 1MB
2767
+ estimatedTotal: Math.round(textureMemory + Math.max(1, vertexBuffers))
2768
+ };
2769
+ }
2770
+ /**
2771
+ * Get rendering statistics/info
2772
+ */
2773
+ getInfo() {
2774
+ const tier = this.optimization.targetGPUTier;
2775
+ const lod = this.optimization.lodStrategy;
2776
+ const culling = this.optimization.culling?.mode;
2777
+ const instancing = this.optimization.batching?.instancing ? "yes" : "no";
2778
+ const memory = this.estimateGPUMemory();
2779
+ return `Rendering: tier=${tier} | LOD=${lod} | culling=${culling} | instancing=${instancing} | memory=${memory.estimatedTotal}MB`;
2780
+ }
2781
+ /**
2782
+ * Optimize for VR/AR (fixed timestep, fast culling)
2783
+ */
2784
+ optimizeForVRAR(targetFPS = 90) {
2785
+ this.optimization.fixedTimestep = 1 / targetFPS;
2786
+ this.optimization.targetFrameRate = targetFPS;
2787
+ this.setOcclusionCulling(true, 50);
2788
+ this.setInstancing(true, 5e3);
2789
+ this.setAdaptiveQuality(true, targetFPS);
2790
+ }
2791
+ /**
2792
+ * Optimize for mobile (lower resources)
2793
+ */
2794
+ optimizeForMobile() {
2795
+ this.applyQualityPreset("low");
2796
+ this.setTextureCompression("astc");
2797
+ this.setInstancing(true, 256);
2798
+ }
2799
+ /**
2800
+ * Optimize for desktop (higher resources)
2801
+ */
2802
+ optimizeForDesktop() {
2803
+ this.applyQualityPreset("ultra");
2804
+ this.setTextureCompression("none");
2805
+ this.setInstancing(true, 5e3);
2806
+ }
2807
+ /**
2808
+ * Dispose and cleanup
2809
+ */
2810
+ dispose() {
2811
+ }
2812
+ };
2813
+ function createRenderingTrait(config) {
2814
+ return new RenderingTrait(config);
2815
+ }
2816
+
2282
2817
  // src/HoloScriptPlusParser.ts
2283
2818
  var HoloScriptPlusParser2 = class {
2284
2819
  constructor() {
2285
- this.baseParser = new chunk4OHVW4XR_cjs.HoloScriptCodeParser();
2820
+ this.baseParser = new chunkT57ZL7KR_cjs.HoloScriptCodeParser();
2286
2821
  }
2287
2822
  /**
2288
2823
  * Parse HoloScript+ code with trait annotations
@@ -2530,8 +3065,7 @@ var HoloScriptPlusParser2 = class {
2530
3065
  * Create MaterialTrait from config
2531
3066
  */
2532
3067
  createMaterialTrait(config) {
2533
- const { MaterialTrait: MaterialTrait2 } = (init_MaterialTrait(), chunkCZLDE2OZ_cjs.__toCommonJS(MaterialTrait_exports));
2534
- const material = new MaterialTrait2({
3068
+ const material = new MaterialTrait({
2535
3069
  type: config.type || "pbr",
2536
3070
  pbr: config.pbr
2537
3071
  });
@@ -2555,13 +3089,13 @@ var HoloScriptPlusParser2 = class {
2555
3089
  * Create LightingTrait from config
2556
3090
  */
2557
3091
  createLightingTrait(config) {
2558
- const { LightingTrait: LightingTrait2, LIGHTING_PRESETS: LIGHTING_PRESETS2 } = (init_LightingTrait(), chunkCZLDE2OZ_cjs.__toCommonJS(LightingTrait_exports));
2559
3092
  let lighting;
2560
3093
  if (config.preset) {
2561
- const preset = LIGHTING_PRESETS2[config.preset];
2562
- lighting = new LightingTrait2(preset);
3094
+ const presetFactory = LIGHTING_PRESETS[config.preset];
3095
+ const presetConfig = presetFactory ? presetFactory() : void 0;
3096
+ lighting = new LightingTrait(presetConfig);
2563
3097
  } else {
2564
- lighting = new LightingTrait2();
3098
+ lighting = new LightingTrait();
2565
3099
  }
2566
3100
  if (config.globalIllumination) {
2567
3101
  lighting.setGlobalIllumination(config.globalIllumination);
@@ -2577,8 +3111,7 @@ var HoloScriptPlusParser2 = class {
2577
3111
  * Create RenderingTrait from config
2578
3112
  */
2579
3113
  createRenderingTrait(config) {
2580
- const { RenderingTrait: RenderingTrait2 } = (init_RenderingTrait(), chunkCZLDE2OZ_cjs.__toCommonJS(RenderingTrait_exports));
2581
- const rendering = new RenderingTrait2();
3114
+ const rendering = new RenderingTrait();
2582
3115
  if (config.quality) {
2583
3116
  rendering.applyQualityPreset(config.quality);
2584
3117
  }
@@ -2909,6 +3442,25 @@ var ExpressionEvaluator = class {
2909
3442
  };
2910
3443
  }
2911
3444
  evaluate(expression) {
3445
+ const dangerousPatterns = [
3446
+ /\beval\s*\(/,
3447
+ /\brequire\s*\(/,
3448
+ /\bimport\s*\(/,
3449
+ /\bprocess\s*\./,
3450
+ /\bglobal\s*\./,
3451
+ /\b__dirname\b/,
3452
+ /\b__filename\b/,
3453
+ /\bfs\s*\./,
3454
+ /\bchild_process\s*\./,
3455
+ /\bfs\.writeFileSync/,
3456
+ /\bfs\.readFileSync/
3457
+ ];
3458
+ for (const pattern of dangerousPatterns) {
3459
+ if (pattern.test(expression)) {
3460
+ console.warn(`Security: Blocked suspicious expression: ${expression}`);
3461
+ return void 0;
3462
+ }
3463
+ }
2912
3464
  const contextKeys = Object.keys(this.context);
2913
3465
  const contextValues = Object.values(this.context);
2914
3466
  const builtinKeys = Object.keys(this.builtins);
@@ -2988,7 +3540,8 @@ var grabbableHandler = {
2988
3540
  const distance = Math.sqrt(
2989
3541
  Math.pow(handPos[0] - nodePos2[0], 2) + Math.pow(handPos[1] - nodePos2[1], 2) + Math.pow(handPos[2] - nodePos2[2], 2)
2990
3542
  );
2991
- if (distance > (config.max_grab_distance || 3)) return;
3543
+ const maxDist = (config.max_grab_distance || 3) * context.getScaleMultiplier();
3544
+ if (distance > maxDist) return;
2992
3545
  }
2993
3546
  state.isGrabbed = true;
2994
3547
  state.grabbingHand = event.hand;
@@ -3019,7 +3572,7 @@ var grabbableHandler = {
3019
3572
  ];
3020
3573
  if (node.traits.has("throwable")) {
3021
3574
  const throwConfig = node.traits.get("throwable");
3022
- const multiplier = throwConfig.velocity_multiplier || 1;
3575
+ const multiplier = (throwConfig.velocity_multiplier || 1) * context.getScaleMultiplier();
3023
3576
  context.physics.applyVelocity(node, [
3024
3577
  velocity[0] * multiplier,
3025
3578
  velocity[1] * multiplier,
@@ -3197,6 +3750,21 @@ var scalableHandler = {
3197
3750
  const scaleFactor = currentDistance / state.initialDistance;
3198
3751
  let newScale = state.initialScale * scaleFactor;
3199
3752
  newScale = Math.max(config.min_scale || 0.1, Math.min(config.max_scale || 10, newScale));
3753
+ const scaleMultiplier = context.getScaleMultiplier();
3754
+ const effectiveScale = newScale * scaleMultiplier;
3755
+ if (effectiveScale > 1e6 && scaleMultiplier < 1e6) {
3756
+ context.setScaleContext("galactic");
3757
+ newScale /= 1e6;
3758
+ } else if (effectiveScale > 1e3 && scaleMultiplier < 1e3) {
3759
+ context.setScaleContext("macro");
3760
+ newScale /= 1e3;
3761
+ } else if (effectiveScale < 1e-3 && scaleMultiplier > 1e-3) {
3762
+ context.setScaleContext("micro");
3763
+ newScale *= 1e3;
3764
+ } else if (effectiveScale < 1e-6 && scaleMultiplier > 1e-6) {
3765
+ context.setScaleContext("atomic");
3766
+ newScale *= 1e6;
3767
+ }
3200
3768
  node.properties.scale = newScale;
3201
3769
  context.emit("scale_update", { node, scale: newScale });
3202
3770
  },
@@ -3372,12 +3940,12 @@ var snappableHandler = {
3372
3940
  snap_rotation: false,
3373
3941
  magnetic: false
3374
3942
  },
3375
- onUpdate(node, config, _context, _delta) {
3943
+ onUpdate(node, config, context, _delta) {
3376
3944
  if (!config.snap_points || config.snap_points.length === 0) return;
3377
3945
  if (!config.magnetic) return;
3378
3946
  const nodePos = node.properties.position || [0, 0, 0];
3379
3947
  let closestPoint = null;
3380
- let closestDistance = config.snap_distance || 0.3;
3948
+ let closestDistance = (config.snap_distance || 0.3) * context.getScaleMultiplier();
3381
3949
  for (const snapPoint of config.snap_points) {
3382
3950
  const distance = Math.sqrt(
3383
3951
  Math.pow(nodePos[0] - snapPoint[0], 2) + Math.pow(nodePos[1] - snapPoint[1], 2) + Math.pow(nodePos[2] - snapPoint[2], 2)
@@ -3401,7 +3969,7 @@ var snappableHandler = {
3401
3969
  if (!config.snap_points || config.snap_points.length === 0) return;
3402
3970
  const nodePos = node.properties.position || [0, 0, 0];
3403
3971
  let closestPoint = null;
3404
- let closestDistance = config.snap_distance || 0.3;
3972
+ let closestDistance = (config.snap_distance || 0.3) * context.getScaleMultiplier();
3405
3973
  for (const snapPoint of config.snap_points) {
3406
3974
  const distance = Math.sqrt(
3407
3975
  Math.pow(nodePos[0] - snapPoint[0], 2) + Math.pow(nodePos[1] - snapPoint[1], 2) + Math.pow(nodePos[2] - snapPoint[2], 2)
@@ -3457,202 +4025,138 @@ var breakableHandler = {
3457
4025
  }
3458
4026
  context.emit("break", { node, impactVelocity, collision });
3459
4027
  if (config.respawn) {
3460
- const delay = parseDuration(config.respawn_delay || "5s");
3461
- setTimeout(() => {
3462
- context.emit("respawn", { node });
3463
- }, delay);
3464
- }
3465
- node.properties.__destroyed = true;
3466
- }
3467
- };
3468
- function parseDuration(duration) {
3469
- const match = duration.match(/^(\d+(?:\.\d+)?)(ms|s|m)$/);
3470
- if (!match) return 0;
3471
- const value = parseFloat(match[1]);
3472
- const unit = match[2];
3473
- switch (unit) {
3474
- case "ms":
3475
- return value;
3476
- case "s":
3477
- return value * 1e3;
3478
- case "m":
3479
- return value * 60 * 1e3;
3480
- default:
3481
- return value;
3482
- }
3483
- }
3484
- var VRTraitRegistry = class {
3485
- constructor() {
3486
- this.handlers = /* @__PURE__ */ new Map();
3487
- this.register(grabbableHandler);
3488
- this.register(throwableHandler);
3489
- this.register(pointableHandler);
3490
- this.register(hoverableHandler);
3491
- this.register(scalableHandler);
3492
- this.register(rotatableHandler);
3493
- this.register(stackableHandler);
3494
- this.register(snappableHandler);
3495
- this.register(breakableHandler);
3496
- }
3497
- register(handler) {
3498
- this.handlers.set(handler.name, handler);
3499
- }
3500
- getHandler(name) {
3501
- return this.handlers.get(name);
3502
- }
3503
- attachTrait(node, traitName, config, context) {
3504
- const handler = this.handlers.get(traitName);
3505
- if (!handler) return;
3506
- const mergedConfig = { ...handler.defaultConfig, ...config };
3507
- node.traits.set(traitName, mergedConfig);
3508
- if (handler.onAttach) {
3509
- handler.onAttach(node, mergedConfig, context);
3510
- }
3511
- }
3512
- detachTrait(node, traitName, context) {
3513
- const handler = this.handlers.get(traitName);
3514
- if (!handler) return;
3515
- const config = node.traits.get(traitName);
3516
- if (config && handler.onDetach) {
3517
- handler.onDetach(node, config, context);
3518
- }
3519
- node.traits.delete(traitName);
3520
- }
3521
- updateTrait(node, traitName, context, delta) {
3522
- const handler = this.handlers.get(traitName);
3523
- if (!handler || !handler.onUpdate) return;
3524
- const config = node.traits.get(traitName);
3525
- if (config) {
3526
- handler.onUpdate(node, config, context, delta);
3527
- }
3528
- }
3529
- handleEvent(node, traitName, context, event) {
3530
- const handler = this.handlers.get(traitName);
3531
- if (!handler || !handler.onEvent) return;
3532
- const config = node.traits.get(traitName);
3533
- if (config) {
3534
- handler.onEvent(node, config, context, event);
3535
- }
3536
- }
3537
- updateAllTraits(node, context, delta) {
3538
- for (const traitName of node.traits.keys()) {
3539
- this.updateTrait(node, traitName, context, delta);
3540
- }
3541
- }
3542
- handleEventForAllTraits(node, context, event) {
3543
- for (const traitName of node.traits.keys()) {
3544
- this.handleEvent(node, traitName, context, event);
3545
- }
3546
- }
3547
- };
3548
- var vrTraitRegistry = new VRTraitRegistry();
3549
-
3550
- // src/runtime/HoloScriptPlusRuntime.ts
3551
- function createBuiltins(runtime) {
3552
- return {
3553
- Math,
3554
- range: (start, end, step = 1) => {
3555
- const result = [];
3556
- if (step > 0) {
3557
- for (let i = start; i < end; i += step) {
3558
- result.push(i);
3559
- }
3560
- } else if (step < 0) {
3561
- for (let i = start; i > end; i += step) {
3562
- result.push(i);
3563
- }
3564
- }
3565
- return result;
3566
- },
3567
- interpolate_color: (t, from, to) => {
3568
- const parseHex = (hex) => {
3569
- const clean = hex.replace("#", "");
3570
- return [
3571
- parseInt(clean.substring(0, 2), 16),
3572
- parseInt(clean.substring(2, 4), 16),
3573
- parseInt(clean.substring(4, 6), 16)
3574
- ];
3575
- };
3576
- const toHex = (r, g, b) => {
3577
- const clamp = (v) => Math.max(0, Math.min(255, Math.round(v)));
3578
- return `#${clamp(r).toString(16).padStart(2, "0")}${clamp(g).toString(16).padStart(2, "0")}${clamp(b).toString(16).padStart(2, "0")}`;
3579
- };
3580
- const [r1, g1, b1] = parseHex(from);
3581
- const [r2, g2, b2] = parseHex(to);
3582
- return toHex(
3583
- r1 + (r2 - r1) * t,
3584
- g1 + (g2 - g1) * t,
3585
- b1 + (b2 - b1) * t
3586
- );
3587
- },
3588
- distance_to: (point) => {
3589
- const viewer = runtime.vrContext.headset.position;
3590
- return Math.sqrt(
3591
- Math.pow(point[0] - viewer[0], 2) + Math.pow(point[1] - viewer[1], 2) + Math.pow(point[2] - viewer[2], 2)
3592
- );
3593
- },
3594
- distance_to_viewer: () => {
3595
- return 0;
3596
- },
3597
- hand_position: (handId) => {
3598
- const hand = handId === "left" ? runtime.vrContext.hands.left : runtime.vrContext.hands.right;
3599
- return hand?.position || [0, 0, 0];
3600
- },
3601
- hand_velocity: (handId) => {
3602
- const hand = handId === "left" ? runtime.vrContext.hands.left : runtime.vrContext.hands.right;
3603
- return hand?.velocity || [0, 0, 0];
3604
- },
3605
- dominant_hand: () => {
3606
- return runtime.vrContext.hands.right || runtime.vrContext.hands.left || {
3607
- id: "right",
3608
- position: [0, 0, 0],
3609
- rotation: [0, 0, 0],
3610
- velocity: [0, 0, 0],
3611
- grip: 0,
3612
- trigger: 0
3613
- };
3614
- },
3615
- play_sound: (source, options) => {
3616
- runtime.emit("play_sound", { source, ...options });
3617
- },
3618
- haptic_feedback: (hand, intensity) => {
3619
- const handId = typeof hand === "string" ? hand : hand.id;
3620
- runtime.emit("haptic", { hand: handId, intensity });
3621
- },
3622
- haptic_pulse: (intensity) => {
3623
- runtime.emit("haptic", { hand: "both", intensity });
3624
- },
3625
- apply_velocity: (node, velocity) => {
3626
- runtime.emit("apply_velocity", { node, velocity });
3627
- },
3628
- spawn: (template, position) => {
3629
- return runtime.spawnTemplate(template, position);
3630
- },
3631
- destroy: (node) => {
3632
- runtime.destroyNode(node);
3633
- },
3634
- api_call: async (url, method, body) => {
3635
- const response = await fetch(url, {
3636
- method,
3637
- headers: body ? { "Content-Type": "application/json" } : void 0,
3638
- body: body ? JSON.stringify(body) : void 0
3639
- });
3640
- return response.json();
3641
- },
3642
- open_modal: (modalId) => {
3643
- runtime.emit("open_modal", { id: modalId });
3644
- },
3645
- close_modal: (modalId) => {
3646
- runtime.emit("close_modal", { id: modalId });
3647
- },
3648
- setTimeout: (callback, delay) => {
3649
- return window.setTimeout(callback, delay);
3650
- },
3651
- clearTimeout: (id) => {
3652
- window.clearTimeout(id);
4028
+ const delay = parseDuration(config.respawn_delay || "5s");
4029
+ setTimeout(() => {
4030
+ context.emit("respawn", { node });
4031
+ }, delay);
3653
4032
  }
3654
- };
4033
+ node.properties.__destroyed = true;
4034
+ }
4035
+ };
4036
+ var proactiveHandler = {
4037
+ name: "proactive",
4038
+ defaultConfig: {
4039
+ intelligence_tier: "basic",
4040
+ observation_range: 5,
4041
+ learning_rate: 0.1,
4042
+ auto_suggest: true,
4043
+ context_window: 10
4044
+ },
4045
+ onAttach(node, config, context) {
4046
+ console.log(`[Proactive] Neural bridge attached to ${node.id || node.type}`);
4047
+ context.emit("proactive_init", { nodeId: node.id, tier: config.intelligence_tier });
4048
+ },
4049
+ onUpdate(node, config, context, delta) {
4050
+ if (!config || !config.auto_suggest) return;
4051
+ const vr = context.vr;
4052
+ const pos = node.properties.position;
4053
+ if (!pos || !vr.headset.position) return;
4054
+ const dx = pos[0] - vr.headset.position[0];
4055
+ const dy = pos[1] - vr.headset.position[1];
4056
+ const dz = pos[2] - vr.headset.position[2];
4057
+ const distanceToHead = Math.sqrt(dx * dx + dy * dy + dz * dz);
4058
+ if (distanceToHead < (config.observation_range || 5)) {
4059
+ if (Math.random() < 0.01 * (config.learning_rate || 0.1) * delta) {
4060
+ context.emit("proactive_suggestion", {
4061
+ nodeId: node.id,
4062
+ type: "interaction_hint",
4063
+ suggestion: "Object is observing your proximity. Suggesting engagement."
4064
+ });
4065
+ }
4066
+ }
4067
+ }
4068
+ };
4069
+ function parseDuration(duration) {
4070
+ const match = duration.match(/^(\d+(?:\.\d+)?)(ms|s|m)$/);
4071
+ if (!match) return 0;
4072
+ const value = parseFloat(match[1]);
4073
+ const unit = match[2];
4074
+ switch (unit) {
4075
+ case "ms":
4076
+ return value;
4077
+ case "s":
4078
+ return value * 1e3;
4079
+ case "m":
4080
+ return value * 60 * 1e3;
4081
+ default:
4082
+ return value;
4083
+ }
3655
4084
  }
4085
+ var VRTraitRegistry = class {
4086
+ constructor() {
4087
+ this.handlers = /* @__PURE__ */ new Map();
4088
+ this.register(grabbableHandler);
4089
+ this.register(throwableHandler);
4090
+ this.register(pointableHandler);
4091
+ this.register(hoverableHandler);
4092
+ this.register(scalableHandler);
4093
+ this.register(rotatableHandler);
4094
+ this.register(stackableHandler);
4095
+ this.register(snappableHandler);
4096
+ this.register(breakableHandler);
4097
+ this.register(proactiveHandler);
4098
+ }
4099
+ register(handler) {
4100
+ this.handlers.set(handler.name, handler);
4101
+ }
4102
+ getHandler(name) {
4103
+ return this.handlers.get(name);
4104
+ }
4105
+ attachTrait(node, traitName, config, context) {
4106
+ const handler = this.handlers.get(traitName);
4107
+ if (!handler) return;
4108
+ const mergedConfig = { ...handler.defaultConfig, ...config };
4109
+ node.traits.set(traitName, mergedConfig);
4110
+ if (handler.onAttach) {
4111
+ handler.onAttach(node, mergedConfig, context);
4112
+ }
4113
+ }
4114
+ detachTrait(node, traitName, context) {
4115
+ const handler = this.handlers.get(traitName);
4116
+ if (!handler) return;
4117
+ const config = node.traits.get(traitName);
4118
+ if (config && handler.onDetach) {
4119
+ handler.onDetach(node, config, context);
4120
+ }
4121
+ node.traits.delete(traitName);
4122
+ }
4123
+ updateTrait(node, traitName, context, delta) {
4124
+ const handler = this.handlers.get(traitName);
4125
+ if (!handler || !handler.onUpdate) return;
4126
+ const config = node.traits.get(traitName);
4127
+ if (config) {
4128
+ handler.onUpdate(node, config, context, delta);
4129
+ }
4130
+ }
4131
+ handleEvent(node, traitName, context, event) {
4132
+ const handler = this.handlers.get(traitName);
4133
+ if (!handler || !handler.onEvent) return;
4134
+ const config = node.traits.get(traitName);
4135
+ if (config) {
4136
+ handler.onEvent(node, config, context, event);
4137
+ }
4138
+ }
4139
+ updateAllTraits(node, context, delta) {
4140
+ for (const traitName of node.traits.keys()) {
4141
+ this.updateTrait(node, traitName, context, delta);
4142
+ }
4143
+ }
4144
+ handleEventForAllTraits(node, context, event) {
4145
+ for (const traitName of node.traits.keys()) {
4146
+ this.handleEvent(node, traitName, context, event);
4147
+ }
4148
+ }
4149
+ };
4150
+ var vrTraitRegistry = new VRTraitRegistry();
4151
+
4152
+ // src/runtime/HoloScriptPlusRuntime.ts
4153
+ var StateSync = class {
4154
+ constructor(_options) {
4155
+ }
4156
+ getInterpolatedState(_id) {
4157
+ return null;
4158
+ }
4159
+ };
3656
4160
  var HoloScriptPlusRuntimeImpl = class {
3657
4161
  constructor(ast, options = {}) {
3658
4162
  this.rootInstance = null;
@@ -3661,6 +4165,7 @@ var HoloScriptPlusRuntimeImpl = class {
3661
4165
  this.updateLoopId = null;
3662
4166
  this.lastUpdateTime = 0;
3663
4167
  this.mounted = false;
4168
+ this.scaleMultiplier = 1;
3664
4169
  // VR context
3665
4170
  this.vrContext = {
3666
4171
  hands: {
@@ -3676,12 +4181,15 @@ var HoloScriptPlusRuntimeImpl = class {
3676
4181
  right: null
3677
4182
  }
3678
4183
  };
4184
+ this.generatedNodes = /* @__PURE__ */ new Set();
4185
+ this.apiPollingTimers = /* @__PURE__ */ new Map();
3679
4186
  this.ast = ast;
3680
4187
  this.options = options;
3681
4188
  this.state = createState({});
3682
4189
  this.traitRegistry = vrTraitRegistry;
3683
4190
  this.companions = options.companions || {};
3684
4191
  this.builtins = createBuiltins(this);
4192
+ this.networkSync = new StateSync({ interpolation: true });
3685
4193
  this.evaluator = new ExpressionEvaluator(
3686
4194
  this.state.getSnapshot(),
3687
4195
  this.builtins
@@ -3950,6 +4458,20 @@ var HoloScriptPlusRuntimeImpl = class {
3950
4458
  if (instance.destroyed) return;
3951
4459
  const traitContext = this.createTraitContext(instance);
3952
4460
  this.traitRegistry.updateAllTraits(instance.node, traitContext, delta);
4461
+ if (instance.node.type === "avatar") {
4462
+ this.syncAvatarParts(instance);
4463
+ }
4464
+ if (instance.node.traits.has("networked")) {
4465
+ const interpolated = this.networkSync.getInterpolatedState(instance.node.id || "");
4466
+ if (interpolated) {
4467
+ if (interpolated.position) {
4468
+ instance.node.properties.position = [interpolated.position.x, interpolated.position.y, interpolated.position.z];
4469
+ }
4470
+ if (interpolated.rotation) {
4471
+ instance.node.properties.rotation = [interpolated.rotation.x, interpolated.rotation.y, interpolated.rotation.z];
4472
+ }
4473
+ }
4474
+ }
3953
4475
  if (this.options.renderer && instance.renderedNode) {
3954
4476
  const properties = this.evaluateProperties(instance.node.properties);
3955
4477
  this.options.renderer.updateElement(instance.renderedNode, properties);
@@ -3957,6 +4479,91 @@ var HoloScriptPlusRuntimeImpl = class {
3957
4479
  for (const child of instance.children) {
3958
4480
  this.updateInstance(child, delta);
3959
4481
  }
4482
+ this.updateExternalApis(instance, delta);
4483
+ this.processGenerateDirectives(instance);
4484
+ }
4485
+ syncAvatarParts(instance) {
4486
+ const vrHands = this.vrContext.hands;
4487
+ const vrHead = this.vrContext.headset;
4488
+ if (instance.node.id === "local_player") {
4489
+ instance.node.properties.position = vrHead.position;
4490
+ instance.node.properties.rotation = vrHead.rotation;
4491
+ instance.children.forEach((child) => {
4492
+ if (child.node.id === "left_hand" && vrHands.left) {
4493
+ child.node.properties.position = vrHands.left.position;
4494
+ child.node.properties.rotation = vrHands.left.rotation;
4495
+ } else if (child.node.id === "right_hand" && vrHands.right) {
4496
+ child.node.properties.position = vrHands.right.position;
4497
+ child.node.properties.rotation = vrHands.right.rotation;
4498
+ }
4499
+ });
4500
+ if (instance.node.traits.has("networked")) {
4501
+ this.emit("network_snapshot", {
4502
+ objectId: instance.node.id,
4503
+ position: { x: vrHead.position[0], y: vrHead.position[1], z: vrHead.position[2] },
4504
+ rotation: { x: vrHead.rotation[0], y: vrHead.rotation[1], z: vrHead.rotation[2] },
4505
+ timestamp: Date.now()
4506
+ });
4507
+ }
4508
+ }
4509
+ }
4510
+ processGenerateDirectives(instance) {
4511
+ const generateDirectives = instance.node.directives.filter((d) => d.type === "generate");
4512
+ for (const d of generateDirectives) {
4513
+ const directive = d;
4514
+ const genId = `${instance.node.id || "node"}_${directive.prompt.substring(0, 10)}`;
4515
+ if (this.generatedNodes.has(genId)) continue;
4516
+ console.log(`[Generate] AI Bridge Request: "${directive.prompt}"`);
4517
+ this.emit("generate_request", {
4518
+ id: genId,
4519
+ nodeId: instance.node.id,
4520
+ prompt: directive.prompt,
4521
+ context: directive.context,
4522
+ target: directive.target || "children"
4523
+ });
4524
+ this.generatedNodes.add(genId);
4525
+ }
4526
+ }
4527
+ updateExternalApis(instance, _delta) {
4528
+ const apiDirectives = instance.node.directives.filter((d) => d.type === "external_api");
4529
+ for (const d of apiDirectives) {
4530
+ const directive = d;
4531
+ if (directive.type !== "external_api") continue;
4532
+ const intervalStr = directive.interval || "0s";
4533
+ const intervalMs = this.parseDurationToMs(intervalStr);
4534
+ if (intervalMs <= 0) continue;
4535
+ let lastTime = this.apiPollingTimers.get(instance) || 0;
4536
+ const now = performance.now();
4537
+ if (now - lastTime >= intervalMs) {
4538
+ this.apiPollingTimers.set(instance, now);
4539
+ this.executeExternalApi(instance, directive);
4540
+ }
4541
+ }
4542
+ }
4543
+ async executeExternalApi(instance, directive) {
4544
+ try {
4545
+ const data = await this.builtins.api_call(directive.url, directive.method || "GET");
4546
+ this.state.set("api_data", data);
4547
+ this.updateData(data);
4548
+ } catch (error) {
4549
+ console.error(`External API error for ${directive.url}:`, error);
4550
+ }
4551
+ }
4552
+ parseDurationToMs(duration) {
4553
+ const match = duration.match(/^(\d+)(ms|s|m)$/);
4554
+ if (!match) return 0;
4555
+ const value = parseInt(match[1], 10);
4556
+ const unit = match[2];
4557
+ switch (unit) {
4558
+ case "ms":
4559
+ return value;
4560
+ case "s":
4561
+ return value * 1e3;
4562
+ case "m":
4563
+ return value * 6e4;
4564
+ default:
4565
+ return 0;
4566
+ }
3960
4567
  }
3961
4568
  // ==========================================================================
3962
4569
  // TRAIT CONTEXT
@@ -4006,7 +4613,22 @@ var HoloScriptPlusRuntimeImpl = class {
4006
4613
  },
4007
4614
  emit: this.emit.bind(this),
4008
4615
  getState: () => this.state.getSnapshot(),
4009
- setState: (updates) => this.state.update(updates)
4616
+ setState: (updates) => this.state.update(updates),
4617
+ getScaleMultiplier: () => this.scaleMultiplier,
4618
+ setScaleContext: (magnitude) => {
4619
+ const multipliers = {
4620
+ "galactic": 1e6,
4621
+ "macro": 1e3,
4622
+ "standard": 1,
4623
+ "micro": 1e-3,
4624
+ "atomic": 1e-6
4625
+ };
4626
+ const newMultiplier = multipliers[magnitude] || 1;
4627
+ if (this.scaleMultiplier !== newMultiplier) {
4628
+ this.scaleMultiplier = newMultiplier;
4629
+ this.emit("scale_change", { magnitude, multiplier: newMultiplier });
4630
+ }
4631
+ }
4010
4632
  };
4011
4633
  }
4012
4634
  // ==========================================================================
@@ -4038,6 +4660,54 @@ var HoloScriptPlusRuntimeImpl = class {
4038
4660
  getState() {
4039
4661
  return this.state.getSnapshot();
4040
4662
  }
4663
+ // ==========================================================================
4664
+ // COMPATIBILITY METHODS
4665
+ // ==========================================================================
4666
+ getVariable(name) {
4667
+ return this.state.get(name);
4668
+ }
4669
+ setVariable(name, value) {
4670
+ this.state.set(name, value);
4671
+ }
4672
+ getContext() {
4673
+ const spatialMemory = /* @__PURE__ */ new Map();
4674
+ const hologramState = /* @__PURE__ */ new Map();
4675
+ const traverse = (instance) => {
4676
+ if (instance.node.id) {
4677
+ spatialMemory.set(instance.node.id, instance.node.properties.position || { x: 0, y: 0, z: 0 });
4678
+ hologramState.set(instance.node.id, {
4679
+ shape: instance.node.properties.shape || instance.node.type,
4680
+ color: instance.node.properties.color,
4681
+ size: instance.node.properties.size,
4682
+ glow: instance.node.properties.glow,
4683
+ interactive: instance.node.properties.interactive
4684
+ });
4685
+ }
4686
+ instance.children.forEach(traverse);
4687
+ };
4688
+ if (this.rootInstance) traverse(this.rootInstance);
4689
+ return {
4690
+ spatialMemory,
4691
+ hologramState,
4692
+ state: this.state,
4693
+ builtins: this.builtins,
4694
+ vr: this.vrContext
4695
+ };
4696
+ }
4697
+ reset() {
4698
+ this.unmount();
4699
+ this.state = createState({});
4700
+ this.mounted = false;
4701
+ }
4702
+ updateAnimations() {
4703
+ this.update(1 / 60);
4704
+ }
4705
+ updateParticles(delta) {
4706
+ this.update(delta);
4707
+ }
4708
+ getHologramStates() {
4709
+ return this.getContext().hologramState;
4710
+ }
4041
4711
  setState(updates) {
4042
4712
  this.state.update(updates);
4043
4713
  }
@@ -4053,6 +4723,22 @@ var HoloScriptPlusRuntimeImpl = class {
4053
4723
  });
4054
4724
  }
4055
4725
  }
4726
+ updateEntity(id, properties) {
4727
+ if (!this.rootInstance) return false;
4728
+ let found = false;
4729
+ const traverse = (instance) => {
4730
+ if (instance.node.id === id) {
4731
+ instance.node.properties = { ...instance.node.properties, ...properties };
4732
+ if (this.options.renderer && instance.renderedNode) {
4733
+ this.options.renderer.updateElement(instance.renderedNode, properties);
4734
+ }
4735
+ found = true;
4736
+ }
4737
+ instance.children.forEach(traverse);
4738
+ };
4739
+ traverse(this.rootInstance);
4740
+ return found;
4741
+ }
4056
4742
  on(event, handler) {
4057
4743
  if (!this.eventHandlers.has(event)) {
4058
4744
  this.eventHandlers.set(event, /* @__PURE__ */ new Set());
@@ -4138,6 +4824,114 @@ var HoloScriptPlusRuntimeImpl = class {
4138
4824
  this.destroyInstance(instance);
4139
4825
  }
4140
4826
  };
4827
+ function createBuiltins(runtime) {
4828
+ return {
4829
+ Math,
4830
+ range: (start, end, step = 1) => {
4831
+ const result = [];
4832
+ if (step > 0) {
4833
+ for (let i = start; i < end; i += step) {
4834
+ result.push(i);
4835
+ }
4836
+ } else if (step < 0) {
4837
+ for (let i = start; i > end; i += step) {
4838
+ result.push(i);
4839
+ }
4840
+ }
4841
+ return result;
4842
+ },
4843
+ interpolate_color: (t, from, to) => {
4844
+ const parseHex = (hex) => {
4845
+ const clean = hex.replace("#", "");
4846
+ return [
4847
+ parseInt(clean.substring(0, 2), 16),
4848
+ parseInt(clean.substring(2, 4), 16),
4849
+ parseInt(clean.substring(4, 6), 16)
4850
+ ];
4851
+ };
4852
+ const toHex = (r, g, b) => {
4853
+ const clamp = (v) => Math.max(0, Math.min(255, Math.round(v)));
4854
+ return `#${clamp(r).toString(16).padStart(2, "0")}${clamp(g).toString(16).padStart(2, "0")}${clamp(b).toString(16).padStart(2, "0")}`;
4855
+ };
4856
+ const [r1, g1, b1] = parseHex(from);
4857
+ const [r2, g2, b2] = parseHex(to);
4858
+ return toHex(
4859
+ r1 + (r2 - r1) * t,
4860
+ g1 + (g2 - g1) * t,
4861
+ b1 + (b2 - b1) * t
4862
+ );
4863
+ },
4864
+ distance_to: (point) => {
4865
+ const viewer = runtime.vrContext.headset.position;
4866
+ return Math.sqrt(
4867
+ Math.pow(point[0] - viewer[0], 2) + Math.pow(point[1] - viewer[1], 2) + Math.pow(point[2] - viewer[2], 2)
4868
+ );
4869
+ },
4870
+ distance_to_viewer: () => {
4871
+ return 0;
4872
+ },
4873
+ hand_position: (handId) => {
4874
+ const hand = handId === "left" ? runtime.vrContext.hands.left : runtime.vrContext.hands.right;
4875
+ return hand?.position || [0, 0, 0];
4876
+ },
4877
+ hand_velocity: (handId) => {
4878
+ const hand = handId === "left" ? runtime.vrContext.hands.left : runtime.vrContext.hands.right;
4879
+ return hand?.velocity || [0, 0, 0];
4880
+ },
4881
+ dominant_hand: () => {
4882
+ return runtime.vrContext.hands.right || runtime.vrContext.hands.left || {
4883
+ id: "right",
4884
+ position: [0, 0, 0],
4885
+ rotation: [0, 0, 0],
4886
+ velocity: [0, 0, 0],
4887
+ grip: 0,
4888
+ trigger: 0
4889
+ };
4890
+ },
4891
+ play_sound: (source, options) => {
4892
+ runtime.emit("play_sound", { source, ...options });
4893
+ },
4894
+ haptic_feedback: (hand, intensity) => {
4895
+ const handId = typeof hand === "string" ? hand : hand.id;
4896
+ runtime.emit("haptic", { hand: handId, intensity });
4897
+ },
4898
+ haptic_pulse: (intensity) => {
4899
+ runtime.emit("haptic", { hand: "both", intensity });
4900
+ },
4901
+ apply_velocity: (node, velocity) => {
4902
+ runtime.emit("apply_velocity", { node, velocity });
4903
+ },
4904
+ spawn: (template, position) => {
4905
+ return runtime.spawnTemplate(template, position);
4906
+ },
4907
+ assistant_generate: (prompt, context) => {
4908
+ runtime.emit("assistant_generate", { prompt, context });
4909
+ },
4910
+ destroy: (node) => {
4911
+ runtime.destroyNode(node);
4912
+ },
4913
+ api_call: async (url, method, body) => {
4914
+ const response = await fetch(url, {
4915
+ method,
4916
+ headers: body ? { "Content-Type": "application/json" } : void 0,
4917
+ body: body ? JSON.stringify(body) : void 0
4918
+ });
4919
+ return response.json();
4920
+ },
4921
+ open_modal: (modalId) => {
4922
+ runtime.emit("open_modal", { id: modalId });
4923
+ },
4924
+ close_modal: (modalId) => {
4925
+ runtime.emit("close_modal", { id: modalId });
4926
+ },
4927
+ setTimeout: (callback, delay) => {
4928
+ return window.setTimeout(callback, delay);
4929
+ },
4930
+ clearTimeout: (id) => {
4931
+ window.clearTimeout(id);
4932
+ }
4933
+ };
4934
+ }
4141
4935
 
4142
4936
  // src/traits/VoiceInputTrait.ts
4143
4937
  var VoiceInputTrait = class {
@@ -4680,11 +5474,6 @@ function createAIDriverTrait(config) {
4680
5474
  return new AIDriverTrait(config);
4681
5475
  }
4682
5476
 
4683
- // src/index.ts
4684
- init_MaterialTrait();
4685
- init_LightingTrait();
4686
- init_RenderingTrait();
4687
-
4688
5477
  // src/runtime/PerformanceTelemetry.ts
4689
5478
  var PerformanceTelemetry = class {
4690
5479
  // Export every 10s
@@ -5909,7 +6698,7 @@ button refreshBtn {
5909
6698
  function createHoloScriptEnvironment() {
5910
6699
  return {
5911
6700
  parser: new HoloScriptParser(),
5912
- runtime: new chunk3N67RLQP_cjs.HoloScriptRuntime(),
6701
+ runtime: new chunkL6VLNVKP_cjs.HoloScriptRuntime(),
5913
6702
  version: HOLOSCRIPT_VERSION
5914
6703
  };
5915
6704
  }
@@ -5922,27 +6711,27 @@ function isHoloScriptSupported() {
5922
6711
 
5923
6712
  Object.defineProperty(exports, "HoloScriptTypeChecker", {
5924
6713
  enumerable: true,
5925
- get: function () { return chunkVMZN4EVR_cjs.HoloScriptTypeChecker; }
6714
+ get: function () { return chunkMFNO57XL_cjs.HoloScriptTypeChecker; }
5926
6715
  });
5927
6716
  Object.defineProperty(exports, "createTypeChecker", {
5928
6717
  enumerable: true,
5929
- get: function () { return chunkVMZN4EVR_cjs.createTypeChecker; }
6718
+ get: function () { return chunkMFNO57XL_cjs.createTypeChecker; }
5930
6719
  });
5931
6720
  Object.defineProperty(exports, "HoloScriptDebugger", {
5932
6721
  enumerable: true,
5933
- get: function () { return chunkWFI4T3XB_cjs.HoloScriptDebugger; }
6722
+ get: function () { return chunkR75MREOS_cjs.HoloScriptDebugger; }
5934
6723
  });
5935
6724
  Object.defineProperty(exports, "createDebugger", {
5936
6725
  enumerable: true,
5937
- get: function () { return chunkWFI4T3XB_cjs.createDebugger; }
6726
+ get: function () { return chunkR75MREOS_cjs.createDebugger; }
5938
6727
  });
5939
6728
  Object.defineProperty(exports, "HoloScriptCodeParser", {
5940
6729
  enumerable: true,
5941
- get: function () { return chunk4OHVW4XR_cjs.HoloScriptCodeParser; }
6730
+ get: function () { return chunkT57ZL7KR_cjs.HoloScriptCodeParser; }
5942
6731
  });
5943
6732
  Object.defineProperty(exports, "HoloScriptRuntime", {
5944
6733
  enumerable: true,
5945
- get: function () { return chunk3N67RLQP_cjs.HoloScriptRuntime; }
6734
+ get: function () { return chunkL6VLNVKP_cjs.HoloScriptRuntime; }
5946
6735
  });
5947
6736
  Object.defineProperty(exports, "ConsoleLogger", {
5948
6737
  enumerable: true,
@@ -5981,11 +6770,19 @@ exports.HoloScriptParser = HoloScriptParser;
5981
6770
  exports.HoloScriptPlusParser = HoloScriptPlusParser;
5982
6771
  exports.HoloScriptPlusRuntimeImpl = HoloScriptPlusRuntimeImpl;
5983
6772
  exports.HoloScriptTraitAnnotationParser = HoloScriptPlusParser2;
6773
+ exports.HoloScriptValidator = HoloScriptValidator;
5984
6774
  exports.HololandGraphicsPipelineService = HololandGraphicsPipelineService;
6775
+ exports.LIFECYCLE_HOOKS = LIFECYCLE_HOOKS;
6776
+ exports.LIGHTING_PRESETS = LIGHTING_PRESETS;
6777
+ exports.LightingTrait = LightingTrait;
6778
+ exports.MATERIAL_PRESETS = MATERIAL_PRESETS;
6779
+ exports.MaterialTrait = MaterialTrait;
5985
6780
  exports.PerformanceTelemetry = PerformanceTelemetry;
5986
6781
  exports.PlatformPerformanceOptimizer = PlatformPerformanceOptimizer;
5987
6782
  exports.ReactiveState = ReactiveState;
6783
+ exports.RenderingTrait = RenderingTrait;
5988
6784
  exports.VRTraitRegistry = VRTraitRegistry;
6785
+ exports.VR_TRAITS = VR_TRAITS;
5989
6786
  exports.VoiceInputTrait = VoiceInputTrait;
5990
6787
  exports.bind = bind;
5991
6788
  exports.computed = computed;