@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.
- package/dist/{chunk-KWYIVRIH.js → chunk-2XXE34KS.js} +2 -2
- package/dist/chunk-2XXE34KS.js.map +1 -0
- package/dist/{chunk-EU6CZMGJ.js → chunk-AFFVFO4D.js} +511 -118
- package/dist/chunk-AFFVFO4D.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/{chunk-4CV4JOE5.js.map → chunk-DGUM43GV.js.map} +1 -1
- package/dist/{chunk-VYIDLUCV.js → chunk-DOY73HDH.js} +4 -4
- package/dist/{chunk-VYIDLUCV.js.map → chunk-DOY73HDH.js.map} +1 -1
- package/dist/chunk-JEQ2X3Z6.cjs +12 -0
- package/dist/{chunk-CZLDE2OZ.cjs.map → chunk-JEQ2X3Z6.cjs.map} +1 -1
- package/dist/{chunk-3N67RLQP.cjs → chunk-L6VLNVKP.cjs} +511 -118
- package/dist/chunk-L6VLNVKP.cjs.map +1 -0
- package/dist/{chunk-VMZN4EVR.cjs → chunk-MFNO57XL.cjs} +2 -2
- package/dist/chunk-MFNO57XL.cjs.map +1 -0
- package/dist/{chunk-WFI4T3XB.cjs → chunk-R75MREOS.cjs} +6 -6
- package/dist/{chunk-WFI4T3XB.cjs.map → chunk-R75MREOS.cjs.map} +1 -1
- package/dist/{chunk-4OHVW4XR.cjs → chunk-T57ZL7KR.cjs} +299 -45
- package/dist/chunk-T57ZL7KR.cjs.map +1 -0
- package/dist/{chunk-MCP6D4LT.js → chunk-U72GEJZT.js} +299 -45
- package/dist/chunk-U72GEJZT.js.map +1 -0
- package/dist/debugger.cjs +6 -6
- package/dist/debugger.d.cts +1 -1
- package/dist/debugger.d.ts +1 -1
- package/dist/debugger.js +4 -4
- package/dist/index.cjs +1896 -1099
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3145 -1534
- package/dist/index.d.ts +3145 -1534
- package/dist/index.js +1922 -1133
- package/dist/index.js.map +1 -1
- package/dist/parser.cjs +3 -3
- package/dist/parser.d.cts +34 -1
- package/dist/parser.d.ts +34 -1
- package/dist/parser.js +2 -2
- package/dist/runtime.cjs +3 -3
- package/dist/runtime.d.cts +47 -27
- package/dist/runtime.d.ts +47 -27
- package/dist/runtime.js +2 -2
- package/dist/type-checker.cjs +4 -4
- package/dist/type-checker.d.cts +3 -3
- package/dist/type-checker.d.ts +3 -3
- package/dist/type-checker.js +2 -2
- package/dist/{types-D6g4ACjP.d.cts → types-4h8cbtF_.d.cts} +80 -13
- package/dist/{types-D6g4ACjP.d.ts → types-4h8cbtF_.d.ts} +80 -13
- package/package.json +21 -20
- package/LICENSE +0 -21
- package/dist/chunk-3N67RLQP.cjs.map +0 -1
- package/dist/chunk-4CV4JOE5.js +0 -24
- package/dist/chunk-4OHVW4XR.cjs.map +0 -1
- package/dist/chunk-CZLDE2OZ.cjs +0 -28
- package/dist/chunk-EU6CZMGJ.js.map +0 -1
- package/dist/chunk-KWYIVRIH.js.map +0 -1
- package/dist/chunk-MCP6D4LT.js.map +0 -1
- 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
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
373
|
+
res = [this.createFunctionNode(name, tokens.slice(2), position)];
|
|
374
|
+
break;
|
|
1204
375
|
case "gate":
|
|
1205
|
-
|
|
376
|
+
res = [this.createGateNode(name, tokens.slice(2), position)];
|
|
377
|
+
break;
|
|
1206
378
|
case "stream":
|
|
1207
|
-
|
|
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
|
-
|
|
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.
|
|
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/
|
|
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
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
1724
|
+
parsePropsBlock() {
|
|
1725
|
+
this.skipNewlines();
|
|
1726
|
+
const props = {};
|
|
1727
|
+
if (this.check("LBRACE")) {
|
|
2062
1728
|
this.advance();
|
|
2063
|
-
|
|
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
|
-
|
|
1734
|
+
props[key] = this.parseValue();
|
|
2068
1735
|
} else {
|
|
2069
|
-
|
|
1736
|
+
props[key] = true;
|
|
2070
1737
|
}
|
|
2071
|
-
|
|
1738
|
+
this.skipNewlines();
|
|
2072
1739
|
}
|
|
2073
|
-
this.expect("
|
|
1740
|
+
this.expect("RBRACE", "Expected }");
|
|
2074
1741
|
}
|
|
2075
|
-
return
|
|
1742
|
+
return props;
|
|
2076
1743
|
}
|
|
2077
|
-
|
|
2078
|
-
|
|
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
|
-
|
|
2084
|
-
|
|
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
|
|
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
|
|
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
|
|
2562
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
|
6714
|
+
get: function () { return chunkMFNO57XL_cjs.HoloScriptTypeChecker; }
|
|
5926
6715
|
});
|
|
5927
6716
|
Object.defineProperty(exports, "createTypeChecker", {
|
|
5928
6717
|
enumerable: true,
|
|
5929
|
-
get: function () { return
|
|
6718
|
+
get: function () { return chunkMFNO57XL_cjs.createTypeChecker; }
|
|
5930
6719
|
});
|
|
5931
6720
|
Object.defineProperty(exports, "HoloScriptDebugger", {
|
|
5932
6721
|
enumerable: true,
|
|
5933
|
-
get: function () { return
|
|
6722
|
+
get: function () { return chunkR75MREOS_cjs.HoloScriptDebugger; }
|
|
5934
6723
|
});
|
|
5935
6724
|
Object.defineProperty(exports, "createDebugger", {
|
|
5936
6725
|
enumerable: true,
|
|
5937
|
-
get: function () { return
|
|
6726
|
+
get: function () { return chunkR75MREOS_cjs.createDebugger; }
|
|
5938
6727
|
});
|
|
5939
6728
|
Object.defineProperty(exports, "HoloScriptCodeParser", {
|
|
5940
6729
|
enumerable: true,
|
|
5941
|
-
get: function () { return
|
|
6730
|
+
get: function () { return chunkT57ZL7KR_cjs.HoloScriptCodeParser; }
|
|
5942
6731
|
});
|
|
5943
6732
|
Object.defineProperty(exports, "HoloScriptRuntime", {
|
|
5944
6733
|
enumerable: true,
|
|
5945
|
-
get: function () { return
|
|
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;
|