@rezless/vm 0.4.0 → 0.5.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/builtins/base64.d.ts.map +1 -1
- package/dist/builtins/base64.js +29 -2
- package/dist/builtins/base64.js.map +1 -1
- package/dist/builtins/chat.d.ts +7 -1
- package/dist/builtins/chat.d.ts.map +1 -1
- package/dist/builtins/chat.js +26 -29
- package/dist/builtins/chat.js.map +1 -1
- package/dist/builtins/dataserver.d.ts +2 -1
- package/dist/builtins/dataserver.d.ts.map +1 -1
- package/dist/builtins/dataserver.js +5 -4
- package/dist/builtins/dataserver.js.map +1 -1
- package/dist/builtins/debug.d.ts +4 -0
- package/dist/builtins/debug.d.ts.map +1 -0
- package/dist/builtins/debug.js +7 -0
- package/dist/builtins/debug.js.map +1 -0
- package/dist/builtins/http.d.ts +8 -1
- package/dist/builtins/http.d.ts.map +1 -1
- package/dist/builtins/http.js +87 -9
- package/dist/builtins/http.js.map +1 -1
- package/dist/builtins/identity.d.ts +2 -0
- package/dist/builtins/identity.d.ts.map +1 -1
- package/dist/builtins/identity.js +9 -1
- package/dist/builtins/identity.js.map +1 -1
- package/dist/builtins/index.d.ts.map +1 -1
- package/dist/builtins/index.js +29 -7
- package/dist/builtins/index.js.map +1 -1
- package/dist/builtins/inventory.d.ts +13 -2
- package/dist/builtins/inventory.d.ts.map +1 -1
- package/dist/builtins/inventory.js +82 -43
- package/dist/builtins/inventory.js.map +1 -1
- package/dist/builtins/json.d.ts.map +1 -1
- package/dist/builtins/json.js +11 -36
- package/dist/builtins/json.js.map +1 -1
- package/dist/builtins/link-info.d.ts +1 -1
- package/dist/builtins/link-info.d.ts.map +1 -1
- package/dist/builtins/link-info.js +2 -2
- package/dist/builtins/link-info.js.map +1 -1
- package/dist/builtins/linksetdata.d.ts.map +1 -1
- package/dist/builtins/linksetdata.js +298 -31
- package/dist/builtins/linksetdata.js.map +1 -1
- package/dist/builtins/listen.d.ts +3 -1
- package/dist/builtins/listen.d.ts.map +1 -1
- package/dist/builtins/listen.js +9 -1
- package/dist/builtins/listen.js.map +1 -1
- package/dist/builtins/lists.d.ts +21 -0
- package/dist/builtins/lists.d.ts.map +1 -1
- package/dist/builtins/lists.js +82 -38
- package/dist/builtins/lists.js.map +1 -1
- package/dist/builtins/math.d.ts +27 -4
- package/dist/builtins/math.d.ts.map +1 -1
- package/dist/builtins/math.js +118 -41
- package/dist/builtins/math.js.map +1 -1
- package/dist/builtins/permissions.d.ts +18 -0
- package/dist/builtins/permissions.d.ts.map +1 -0
- package/dist/builtins/permissions.js +17 -0
- package/dist/builtins/permissions.js.map +1 -0
- package/dist/builtins/prim-accessors.d.ts +1 -0
- package/dist/builtins/prim-accessors.d.ts.map +1 -1
- package/dist/builtins/prim-accessors.js +44 -42
- package/dist/builtins/prim-accessors.js.map +1 -1
- package/dist/builtins/prim-params.d.ts +1 -1
- package/dist/builtins/prim-params.d.ts.map +1 -1
- package/dist/builtins/prim-params.js +19 -11
- package/dist/builtins/prim-params.js.map +1 -1
- package/dist/builtins/strings.d.ts.map +1 -1
- package/dist/builtins/strings.js +37 -33
- package/dist/builtins/strings.js.map +1 -1
- package/dist/builtins/time.d.ts +2 -0
- package/dist/builtins/time.d.ts.map +1 -1
- package/dist/builtins/time.js +2 -0
- package/dist/builtins/time.js.map +1 -1
- package/dist/clock.d.ts +23 -9
- package/dist/clock.d.ts.map +1 -1
- package/dist/clock.js +40 -13
- package/dist/clock.js.map +1 -1
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +10 -3
- package/dist/dispatch.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interpreter.js +2 -2
- package/dist/interpreter.js.map +1 -1
- package/dist/inventory.d.ts +2 -0
- package/dist/inventory.d.ts.map +1 -1
- package/dist/inventory.js +4 -0
- package/dist/inventory.js.map +1 -1
- package/dist/keys.d.ts +6 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +20 -0
- package/dist/keys.js.map +1 -0
- package/dist/linkset.d.ts +28 -3
- package/dist/linkset.d.ts.map +1 -1
- package/dist/linkset.js +66 -7
- package/dist/linkset.js.map +1 -1
- package/dist/prim-params.d.ts +5 -0
- package/dist/prim-params.d.ts.map +1 -1
- package/dist/prim-params.js +187 -107
- package/dist/prim-params.js.map +1 -1
- package/dist/prim.d.ts +6 -1
- package/dist/prim.d.ts.map +1 -1
- package/dist/prim.js +23 -3
- package/dist/prim.js.map +1 -1
- package/dist/runtime.d.ts +11 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/script.d.ts +27 -2
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +89 -27
- package/dist/script.js.map +1 -1
- package/dist/values/coerce.d.ts +11 -0
- package/dist/values/coerce.d.ts.map +1 -1
- package/dist/values/coerce.js +65 -38
- package/dist/values/coerce.js.map +1 -1
- package/dist/values/format.d.ts +24 -16
- package/dist/values/format.d.ts.map +1 -1
- package/dist/values/format.js +42 -25
- package/dist/values/format.js.map +1 -1
- package/dist/values/ops.d.ts +2 -1
- package/dist/values/ops.d.ts.map +1 -1
- package/dist/values/ops.js +13 -5
- package/dist/values/ops.js.map +1 -1
- package/dist/values/utf8.d.ts +3 -0
- package/dist/values/utf8.d.ts.map +1 -0
- package/dist/values/utf8.js +14 -0
- package/dist/values/utf8.js.map +1 -0
- package/dist/world.d.ts +29 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +29 -0
- package/dist/world.js.map +1 -0
- package/package.json +2 -2
package/dist/prim-params.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { ALL_SIDES, CLICK_ACTION_TOUCH, PRIM_ALPHA_MODE, PRIM_ALPHA_MODE_NONE, PRIM_ALLOW_UNSIT, PRIM_BUMP_NONE, PRIM_BUMP_SHINY, PRIM_CAST_SHADOWS, PRIM_CLICK_ACTION, PRIM_COLOR, PRIM_DAMAGE, PRIM_DESC, PRIM_FLEXIBLE, PRIM_FULLBRIGHT, PRIM_GLOW, PRIM_GLTF_ALPHA_MODE_OPAQUE, PRIM_GLTF_BASE_COLOR, PRIM_GLTF_EMISSIVE, PRIM_GLTF_METALLIC_ROUGHNESS, PRIM_GLTF_NORMAL, PRIM_HEALTH, PRIM_HOLE_DEFAULT, PRIM_LINK_TARGET, PRIM_MATERIAL,
|
|
2
|
-
import { NULL_KEY } from './values/types.js';
|
|
1
|
+
import { ALL_SIDES, CLICK_ACTION_TOUCH, PRIM_ALPHA_MODE, PRIM_ALPHA_MODE_NONE, PRIM_ALLOW_UNSIT, PRIM_BUMP_NONE, PRIM_BUMP_SHINY, PRIM_CAST_SHADOWS, PRIM_CLICK_ACTION, PRIM_COLOR, PRIM_DAMAGE, PRIM_DESC, PRIM_FLEXIBLE, PRIM_FULLBRIGHT, PRIM_GLOW, PRIM_GLTF_ALPHA_MODE_OPAQUE, PRIM_GLTF_BASE_COLOR, PRIM_GLTF_EMISSIVE, PRIM_GLTF_METALLIC_ROUGHNESS, PRIM_GLTF_NORMAL, PRIM_HEALTH, PRIM_HOLE_DEFAULT, PRIM_LINK_TARGET, PRIM_MATERIAL, PRIM_MATERIAL_WOOD, PRIM_NAME, PRIM_NORMAL, PRIM_OMEGA, PRIM_PHANTOM, PRIM_PHYSICS, PRIM_PHYSICS_SHAPE_PRIM, PRIM_PHYSICS_SHAPE_TYPE, PRIM_POINT_LIGHT, PRIM_POSITION, PRIM_POS_LOCAL, PRIM_PROJECTOR, PRIM_REFLECTION_PROBE, PRIM_RENDER_MATERIAL, PRIM_ROTATION, PRIM_ROT_LOCAL, PRIM_SCRIPTED_SIT_ONLY, PRIM_SCULPT_TYPE_SPHERE, PRIM_SHINY_NONE, PRIM_SIT_FLAGS, PRIM_SIT_TARGET, PRIM_SIZE, PRIM_SLICE, PRIM_SPECULAR, PRIM_TEMP_ON_REZ, PRIM_TEXGEN, PRIM_TEXGEN_DEFAULT, PRIM_TEXT, PRIM_TEXTURE, PRIM_TYPE, PRIM_TYPE_BOX, PRIM_TYPE_CYLINDER, PRIM_TYPE_PRISM, PRIM_TYPE_RING, PRIM_TYPE_SCULPT, PRIM_TYPE_SPHERE, PRIM_TYPE_TORUS, PRIM_TYPE_TUBE, STATUS_PHANTOM, STATUS_PHYSICS, TEXTURE_DEFAULT, } from './generated/constants.js';
|
|
2
|
+
import { NULL_KEY, isRotation, isVector } from './values/types.js';
|
|
3
|
+
import { listElementType } from './values/list-types.js';
|
|
4
|
+
import { truncateUtf8 } from './values/utf8.js';
|
|
3
5
|
/**
|
|
4
6
|
* Typed-literal aliases for the PRIM_TYPE_* constants. The
|
|
5
7
|
* generated module exports them as `: number` so TS can't narrow on
|
|
@@ -80,7 +82,7 @@ export function defaultPrimParams() {
|
|
|
80
82
|
sculpt: { textureKey: '', type: PRIM_SCULPT_TYPE_SPHERE },
|
|
81
83
|
slice: { x: 0, y: 1, z: 0 },
|
|
82
84
|
shape: defaultShape(),
|
|
83
|
-
material:
|
|
85
|
+
material: PRIM_MATERIAL_WOOD,
|
|
84
86
|
tempOnRez: false,
|
|
85
87
|
castShadows: false,
|
|
86
88
|
allowUnsit: true,
|
|
@@ -92,7 +94,7 @@ export function defaultPrimParams() {
|
|
|
92
94
|
damage: { amount: 0, type: 0 },
|
|
93
95
|
health: 1,
|
|
94
96
|
reflectionProbe: { enabled: false, ambiance: 0, clipDistance: 0, flags: 0 },
|
|
95
|
-
physicsMaterial: { gravityMultiplier: 1, restitution: 0, friction: 0, density: 1000 },
|
|
97
|
+
physicsMaterial: { gravityMultiplier: 1, restitution: 0.5, friction: Math.fround(0.6), density: 1000 },
|
|
96
98
|
textureAnim: { mode: 0, face: 0, sizex: 0, sizey: 0, start: 0, length: 0, rate: 0 },
|
|
97
99
|
passCollisions: 0,
|
|
98
100
|
passTouches: 0,
|
|
@@ -118,15 +120,21 @@ const asRot = (v) => {
|
|
|
118
120
|
return identityRot();
|
|
119
121
|
};
|
|
120
122
|
const toByteChannel = (c) => Math.floor(Math.min(1, Math.max(0, c)) * 255) / 255;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
124
|
+
const clampVec = (v, lo, hi) => ({ x: clamp(v.x, lo, hi), y: clamp(v.y, lo, hi), z: clamp(v.z, lo, hi) });
|
|
125
|
+
function normalizeRot(r) {
|
|
126
|
+
const mag = Math.hypot(r.x, r.y, r.z, r.s);
|
|
127
|
+
if (mag === 0)
|
|
128
|
+
return identityRot();
|
|
129
|
+
return { x: r.x / mag, y: r.y / mag, z: r.z / mag, s: r.s / mag };
|
|
126
130
|
}
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
/** Face indexes a face argument names: every face for ALL_SIDES, none past the shape's face count. */
|
|
132
|
+
export function faceIndices(p, face) {
|
|
133
|
+
if (face === ALL_SIDES)
|
|
134
|
+
return p.faces.map((_, i) => i);
|
|
135
|
+
return face >= 0 && face < p.faces.length ? [face] : [];
|
|
129
136
|
}
|
|
137
|
+
const facesOf = (p, faceArg) => faceIndices(p, num(faceArg, 0) | 0);
|
|
130
138
|
/**
|
|
131
139
|
* Slot count for a PRIM_* rule's *write* form, given the rule constant
|
|
132
140
|
* and (for variable-shape rules like PRIM_TYPE) the rules list + cursor
|
|
@@ -210,14 +218,14 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
210
218
|
const p = prim.params;
|
|
211
219
|
switch (param) {
|
|
212
220
|
case PRIM_NAME:
|
|
213
|
-
prim.name = str(rules[cursor]);
|
|
221
|
+
prim.name = truncateUtf8(str(rules[cursor]), 63);
|
|
214
222
|
return 1;
|
|
215
223
|
case PRIM_DESC:
|
|
216
|
-
prim.description = str(rules[cursor]);
|
|
224
|
+
prim.description = truncateUtf8(str(rules[cursor]), 127);
|
|
217
225
|
prim.appearance.description = prim.description;
|
|
218
226
|
return 1;
|
|
219
227
|
case PRIM_TEXT: {
|
|
220
|
-
const text = str(rules[cursor]);
|
|
228
|
+
const text = truncateUtf8(str(rules[cursor]), 254);
|
|
221
229
|
const color = asVec(rules[cursor + 1]);
|
|
222
230
|
const alpha = num(rules[cursor + 2], 1);
|
|
223
231
|
prim.appearance.text = { text, color, alpha };
|
|
@@ -229,10 +237,10 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
229
237
|
return 1;
|
|
230
238
|
case PRIM_ROTATION:
|
|
231
239
|
case PRIM_ROT_LOCAL:
|
|
232
|
-
p.rotation = asRot(rules[cursor]);
|
|
240
|
+
p.rotation = normalizeRot(asRot(rules[cursor]));
|
|
233
241
|
return 1;
|
|
234
242
|
case PRIM_SIZE:
|
|
235
|
-
p.size = asVec(rules[cursor]);
|
|
243
|
+
p.size = clampVec(asVec(rules[cursor]), 0.01, 64);
|
|
236
244
|
return 1;
|
|
237
245
|
case PRIM_SLICE:
|
|
238
246
|
p.slice = asVec(rules[cursor]);
|
|
@@ -322,27 +330,22 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
322
330
|
case PRIM_TYPE:
|
|
323
331
|
return writePrimType(p, rules, cursor);
|
|
324
332
|
case PRIM_COLOR: {
|
|
325
|
-
const faces = facesOf(rules[cursor]);
|
|
333
|
+
const faces = facesOf(p, rules[cursor]);
|
|
326
334
|
const color = asVec(rules[cursor + 1]);
|
|
327
|
-
const alpha = num(rules[cursor + 2], 1);
|
|
335
|
+
const alpha = clamp(num(rules[cursor + 2], 1), 0, 1);
|
|
328
336
|
for (const f of faces) {
|
|
329
|
-
|
|
330
|
-
continue;
|
|
331
|
-
// Clone so faces don't alias the same vector instance.
|
|
332
|
-
p.faces[f].color = { x: color.x, y: color.y, z: color.z };
|
|
337
|
+
p.faces[f].color = clampVec(color, 0, 1);
|
|
333
338
|
p.faces[f].alpha = alpha;
|
|
334
339
|
}
|
|
335
340
|
return 3;
|
|
336
341
|
}
|
|
337
342
|
case PRIM_TEXTURE: {
|
|
338
|
-
const faces = facesOf(rules[cursor]);
|
|
343
|
+
const faces = facesOf(p, rules[cursor]);
|
|
339
344
|
const tex = str(rules[cursor + 1]);
|
|
340
345
|
const repeats = asVec(rules[cursor + 2]);
|
|
341
346
|
const offsets = asVec(rules[cursor + 3]);
|
|
342
347
|
const rot = num(rules[cursor + 4]);
|
|
343
348
|
for (const f of faces) {
|
|
344
|
-
if (!inRange(f))
|
|
345
|
-
continue;
|
|
346
349
|
p.faces[f].texture = tex;
|
|
347
350
|
p.faces[f].textureRepeats = { x: repeats.x, y: repeats.y, z: repeats.z };
|
|
348
351
|
p.faces[f].textureOffsets = { x: offsets.x, y: offsets.y, z: offsets.z };
|
|
@@ -351,66 +354,54 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
351
354
|
return 5;
|
|
352
355
|
}
|
|
353
356
|
case PRIM_RENDER_MATERIAL: {
|
|
354
|
-
const faces = facesOf(rules[cursor]);
|
|
357
|
+
const faces = facesOf(p, rules[cursor]);
|
|
355
358
|
const m = str(rules[cursor + 1]);
|
|
356
359
|
for (const f of faces) {
|
|
357
|
-
if (!inRange(f))
|
|
358
|
-
continue;
|
|
359
360
|
p.faces[f].renderMaterial = m;
|
|
360
361
|
}
|
|
361
362
|
return 2;
|
|
362
363
|
}
|
|
363
364
|
case PRIM_FULLBRIGHT: {
|
|
364
|
-
const faces = facesOf(rules[cursor]);
|
|
365
|
+
const faces = facesOf(p, rules[cursor]);
|
|
365
366
|
const v = num(rules[cursor + 1]) !== 0;
|
|
366
367
|
for (const f of faces) {
|
|
367
|
-
if (!inRange(f))
|
|
368
|
-
continue;
|
|
369
368
|
p.faces[f].fullBright = v;
|
|
370
369
|
}
|
|
371
370
|
return 2;
|
|
372
371
|
}
|
|
373
372
|
case PRIM_GLOW: {
|
|
374
|
-
const faces = facesOf(rules[cursor]);
|
|
373
|
+
const faces = facesOf(p, rules[cursor]);
|
|
375
374
|
const v = num(rules[cursor + 1]);
|
|
376
375
|
for (const f of faces) {
|
|
377
|
-
if (!inRange(f))
|
|
378
|
-
continue;
|
|
379
376
|
p.faces[f].glow = v;
|
|
380
377
|
p.glow[f] = v;
|
|
381
378
|
}
|
|
382
379
|
return 2;
|
|
383
380
|
}
|
|
384
381
|
case PRIM_BUMP_SHINY: {
|
|
385
|
-
const faces = facesOf(rules[cursor]);
|
|
382
|
+
const faces = facesOf(p, rules[cursor]);
|
|
386
383
|
const shiny = num(rules[cursor + 1]) | 0;
|
|
387
384
|
const bump = num(rules[cursor + 2]) | 0;
|
|
388
385
|
for (const f of faces) {
|
|
389
|
-
if (!inRange(f))
|
|
390
|
-
continue;
|
|
391
386
|
p.faces[f].bumpShiny = { shiny, bump };
|
|
392
387
|
}
|
|
393
388
|
return 3;
|
|
394
389
|
}
|
|
395
390
|
case PRIM_TEXGEN: {
|
|
396
|
-
const faces = facesOf(rules[cursor]);
|
|
391
|
+
const faces = facesOf(p, rules[cursor]);
|
|
397
392
|
const mode = num(rules[cursor + 1]) | 0;
|
|
398
393
|
for (const f of faces) {
|
|
399
|
-
if (!inRange(f))
|
|
400
|
-
continue;
|
|
401
394
|
p.faces[f].texgen = mode;
|
|
402
395
|
}
|
|
403
396
|
return 2;
|
|
404
397
|
}
|
|
405
398
|
case PRIM_NORMAL: {
|
|
406
|
-
const faces = facesOf(rules[cursor]);
|
|
399
|
+
const faces = facesOf(p, rules[cursor]);
|
|
407
400
|
const tex = str(rules[cursor + 1]);
|
|
408
401
|
const repeats = asVec(rules[cursor + 2]);
|
|
409
402
|
const offsets = asVec(rules[cursor + 3]);
|
|
410
403
|
const rot = num(rules[cursor + 4]);
|
|
411
404
|
for (const f of faces) {
|
|
412
|
-
if (!inRange(f))
|
|
413
|
-
continue;
|
|
414
405
|
p.faces[f].normal = {
|
|
415
406
|
texture: tex,
|
|
416
407
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -421,7 +412,7 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
421
412
|
return 5;
|
|
422
413
|
}
|
|
423
414
|
case PRIM_SPECULAR: {
|
|
424
|
-
const faces = facesOf(rules[cursor]);
|
|
415
|
+
const faces = facesOf(p, rules[cursor]);
|
|
425
416
|
const tex = str(rules[cursor + 1]);
|
|
426
417
|
const repeats = asVec(rules[cursor + 2]);
|
|
427
418
|
const offsets = asVec(rules[cursor + 3]);
|
|
@@ -430,8 +421,6 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
430
421
|
const gloss = num(rules[cursor + 6]) | 0;
|
|
431
422
|
const env = num(rules[cursor + 7]) | 0;
|
|
432
423
|
for (const f of faces) {
|
|
433
|
-
if (!inRange(f))
|
|
434
|
-
continue;
|
|
435
424
|
p.faces[f].specular = {
|
|
436
425
|
texture: tex,
|
|
437
426
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -446,18 +435,16 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
446
435
|
return 8;
|
|
447
436
|
}
|
|
448
437
|
case PRIM_ALPHA_MODE: {
|
|
449
|
-
const faces = facesOf(rules[cursor]);
|
|
438
|
+
const faces = facesOf(p, rules[cursor]);
|
|
450
439
|
const mode = num(rules[cursor + 1]) | 0;
|
|
451
440
|
const cutoff = num(rules[cursor + 2]) | 0;
|
|
452
441
|
for (const f of faces) {
|
|
453
|
-
if (!inRange(f))
|
|
454
|
-
continue;
|
|
455
442
|
p.faces[f].alphaMode = { mode, cutoff };
|
|
456
443
|
}
|
|
457
444
|
return 3;
|
|
458
445
|
}
|
|
459
446
|
case PRIM_GLTF_BASE_COLOR: {
|
|
460
|
-
const faces = facesOf(rules[cursor]);
|
|
447
|
+
const faces = facesOf(p, rules[cursor]);
|
|
461
448
|
const tex = str(rules[cursor + 1]);
|
|
462
449
|
const repeats = asVec(rules[cursor + 2]);
|
|
463
450
|
const offsets = asVec(rules[cursor + 3]);
|
|
@@ -468,8 +455,6 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
468
455
|
const aCut = num(rules[cursor + 8]);
|
|
469
456
|
const dbl = num(rules[cursor + 9]) | 0;
|
|
470
457
|
for (const f of faces) {
|
|
471
|
-
if (!inRange(f))
|
|
472
|
-
continue;
|
|
473
458
|
p.faces[f].gltf.baseColor = {
|
|
474
459
|
texture: tex,
|
|
475
460
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -485,14 +470,12 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
485
470
|
return 10;
|
|
486
471
|
}
|
|
487
472
|
case PRIM_GLTF_NORMAL: {
|
|
488
|
-
const faces = facesOf(rules[cursor]);
|
|
473
|
+
const faces = facesOf(p, rules[cursor]);
|
|
489
474
|
const tex = str(rules[cursor + 1]);
|
|
490
475
|
const repeats = asVec(rules[cursor + 2]);
|
|
491
476
|
const offsets = asVec(rules[cursor + 3]);
|
|
492
477
|
const rot = num(rules[cursor + 4]);
|
|
493
478
|
for (const f of faces) {
|
|
494
|
-
if (!inRange(f))
|
|
495
|
-
continue;
|
|
496
479
|
p.faces[f].gltf.normal = {
|
|
497
480
|
texture: tex,
|
|
498
481
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -503,7 +486,7 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
503
486
|
return 5;
|
|
504
487
|
}
|
|
505
488
|
case PRIM_GLTF_METALLIC_ROUGHNESS: {
|
|
506
|
-
const faces = facesOf(rules[cursor]);
|
|
489
|
+
const faces = facesOf(p, rules[cursor]);
|
|
507
490
|
const tex = str(rules[cursor + 1]);
|
|
508
491
|
const repeats = asVec(rules[cursor + 2]);
|
|
509
492
|
const offsets = asVec(rules[cursor + 3]);
|
|
@@ -511,8 +494,6 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
511
494
|
const metallic = num(rules[cursor + 5]);
|
|
512
495
|
const rough = num(rules[cursor + 6]);
|
|
513
496
|
for (const f of faces) {
|
|
514
|
-
if (!inRange(f))
|
|
515
|
-
continue;
|
|
516
497
|
p.faces[f].gltf.metallicRoughness = {
|
|
517
498
|
texture: tex,
|
|
518
499
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -525,15 +506,13 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
525
506
|
return 7;
|
|
526
507
|
}
|
|
527
508
|
case PRIM_GLTF_EMISSIVE: {
|
|
528
|
-
const faces = facesOf(rules[cursor]);
|
|
509
|
+
const faces = facesOf(p, rules[cursor]);
|
|
529
510
|
const tex = str(rules[cursor + 1]);
|
|
530
511
|
const repeats = asVec(rules[cursor + 2]);
|
|
531
512
|
const offsets = asVec(rules[cursor + 3]);
|
|
532
513
|
const rot = num(rules[cursor + 4]);
|
|
533
514
|
const tint = asVec(rules[cursor + 5]);
|
|
534
515
|
for (const f of faces) {
|
|
535
|
-
if (!inRange(f))
|
|
536
|
-
continue;
|
|
537
516
|
p.faces[f].gltf.emissive = {
|
|
538
517
|
texture: tex,
|
|
539
518
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -552,6 +531,7 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
552
531
|
}
|
|
553
532
|
function writePrimType(p, rules, cursor) {
|
|
554
533
|
const kind = (num(rules[cursor]) | 0);
|
|
534
|
+
const old = p.shape;
|
|
555
535
|
switch (kind) {
|
|
556
536
|
case SHAPE_BOX:
|
|
557
537
|
case SHAPE_CYLINDER:
|
|
@@ -565,7 +545,7 @@ function writePrimType(p, rules, cursor) {
|
|
|
565
545
|
topSize: asVec(rules[cursor + 5]),
|
|
566
546
|
topShear: asVec(rules[cursor + 6]),
|
|
567
547
|
};
|
|
568
|
-
|
|
548
|
+
break;
|
|
569
549
|
case SHAPE_SPHERE:
|
|
570
550
|
p.shape = {
|
|
571
551
|
kind: SHAPE_SPHERE,
|
|
@@ -575,7 +555,7 @@ function writePrimType(p, rules, cursor) {
|
|
|
575
555
|
twist: asVec(rules[cursor + 4]),
|
|
576
556
|
dimple: asVec(rules[cursor + 5]),
|
|
577
557
|
};
|
|
578
|
-
|
|
558
|
+
break;
|
|
579
559
|
case SHAPE_TORUS:
|
|
580
560
|
case SHAPE_TUBE:
|
|
581
561
|
case SHAPE_RING:
|
|
@@ -593,14 +573,14 @@ function writePrimType(p, rules, cursor) {
|
|
|
593
573
|
radiusOffset: num(rules[cursor + 10]),
|
|
594
574
|
skew: num(rules[cursor + 11]),
|
|
595
575
|
};
|
|
596
|
-
|
|
576
|
+
break;
|
|
597
577
|
case SHAPE_SCULPT:
|
|
598
578
|
p.shape = {
|
|
599
579
|
kind: SHAPE_SCULPT,
|
|
600
580
|
map: str(rules[cursor + 1]),
|
|
601
581
|
type: num(rules[cursor + 2]) | 0,
|
|
602
582
|
};
|
|
603
|
-
|
|
583
|
+
break;
|
|
604
584
|
default:
|
|
605
585
|
// Unknown PRIM_TYPE_* kind: terminate the walk rather than guessing
|
|
606
586
|
// a slot count. Matches writePrimParamSlots' default behavior so
|
|
@@ -608,6 +588,8 @@ function writePrimType(p, rules, cursor) {
|
|
|
608
588
|
// same way.
|
|
609
589
|
return null;
|
|
610
590
|
}
|
|
591
|
+
remapFaces(p, old);
|
|
592
|
+
return writePrimParamSlots(PRIM_TYPE, rules, cursor);
|
|
611
593
|
}
|
|
612
594
|
/**
|
|
613
595
|
* Read a single PRIM_* rule, returning the flat values it expands to and
|
|
@@ -627,6 +609,7 @@ export function readPrimParam(prim, param, rules, cursor) {
|
|
|
627
609
|
return { values: t ? [t.text, t.color, t.alpha] : ['', zero(), 0], consumed: 0 };
|
|
628
610
|
}
|
|
629
611
|
case PRIM_POSITION:
|
|
612
|
+
return { values: [prim.regionPosition()], consumed: 0 };
|
|
630
613
|
case PRIM_POS_LOCAL:
|
|
631
614
|
return { values: [p.position], consumed: 0 };
|
|
632
615
|
case PRIM_ROTATION:
|
|
@@ -688,147 +671,119 @@ export function readPrimParam(prim, param, rules, cursor) {
|
|
|
688
671
|
case PRIM_TYPE:
|
|
689
672
|
return { values: readPrimType(p), consumed: 0 };
|
|
690
673
|
case PRIM_COLOR: {
|
|
691
|
-
const faces = facesOf(rules[cursor]);
|
|
674
|
+
const faces = facesOf(p, rules[cursor]);
|
|
692
675
|
const out = [];
|
|
693
676
|
for (const f of faces) {
|
|
694
|
-
if (!inRange(f))
|
|
695
|
-
continue;
|
|
696
677
|
out.push(p.faces[f].color, p.faces[f].alpha);
|
|
697
678
|
}
|
|
698
679
|
return { values: out, consumed: 1 };
|
|
699
680
|
}
|
|
700
681
|
case PRIM_TEXTURE: {
|
|
701
|
-
const faces = facesOf(rules[cursor]);
|
|
682
|
+
const faces = facesOf(p, rules[cursor]);
|
|
702
683
|
const out = [];
|
|
703
684
|
for (const f of faces) {
|
|
704
|
-
if (!inRange(f))
|
|
705
|
-
continue;
|
|
706
685
|
const fa = p.faces[f];
|
|
707
686
|
out.push(fa.texture, fa.textureRepeats, fa.textureOffsets, fa.textureRotation);
|
|
708
687
|
}
|
|
709
688
|
return { values: out, consumed: 1 };
|
|
710
689
|
}
|
|
711
690
|
case PRIM_RENDER_MATERIAL: {
|
|
712
|
-
const faces = facesOf(rules[cursor]);
|
|
691
|
+
const faces = facesOf(p, rules[cursor]);
|
|
713
692
|
const out = [];
|
|
714
693
|
for (const f of faces) {
|
|
715
|
-
if (!inRange(f))
|
|
716
|
-
continue;
|
|
717
694
|
out.push(p.faces[f].renderMaterial);
|
|
718
695
|
}
|
|
719
696
|
return { values: out, consumed: 1 };
|
|
720
697
|
}
|
|
721
698
|
case PRIM_FULLBRIGHT: {
|
|
722
|
-
const faces = facesOf(rules[cursor]);
|
|
699
|
+
const faces = facesOf(p, rules[cursor]);
|
|
723
700
|
const out = [];
|
|
724
701
|
for (const f of faces) {
|
|
725
|
-
if (!inRange(f))
|
|
726
|
-
continue;
|
|
727
702
|
out.push(p.faces[f].fullBright ? 1 : 0);
|
|
728
703
|
}
|
|
729
704
|
return { values: out, consumed: 1 };
|
|
730
705
|
}
|
|
731
706
|
case PRIM_GLOW: {
|
|
732
|
-
const faces = facesOf(rules[cursor]);
|
|
707
|
+
const faces = facesOf(p, rules[cursor]);
|
|
733
708
|
const out = [];
|
|
734
709
|
for (const f of faces) {
|
|
735
|
-
if (!inRange(f))
|
|
736
|
-
continue;
|
|
737
710
|
out.push(p.faces[f].glow);
|
|
738
711
|
}
|
|
739
712
|
return { values: out, consumed: 1 };
|
|
740
713
|
}
|
|
741
714
|
case PRIM_BUMP_SHINY: {
|
|
742
|
-
const faces = facesOf(rules[cursor]);
|
|
715
|
+
const faces = facesOf(p, rules[cursor]);
|
|
743
716
|
const out = [];
|
|
744
717
|
for (const f of faces) {
|
|
745
|
-
if (!inRange(f))
|
|
746
|
-
continue;
|
|
747
718
|
out.push(p.faces[f].bumpShiny.shiny, p.faces[f].bumpShiny.bump);
|
|
748
719
|
}
|
|
749
720
|
return { values: out, consumed: 1 };
|
|
750
721
|
}
|
|
751
722
|
case PRIM_TEXGEN: {
|
|
752
|
-
const faces = facesOf(rules[cursor]);
|
|
723
|
+
const faces = facesOf(p, rules[cursor]);
|
|
753
724
|
const out = [];
|
|
754
725
|
for (const f of faces) {
|
|
755
|
-
if (!inRange(f))
|
|
756
|
-
continue;
|
|
757
726
|
out.push(p.faces[f].texgen);
|
|
758
727
|
}
|
|
759
728
|
return { values: out, consumed: 1 };
|
|
760
729
|
}
|
|
761
730
|
case PRIM_NORMAL: {
|
|
762
|
-
const faces = facesOf(rules[cursor]);
|
|
731
|
+
const faces = facesOf(p, rules[cursor]);
|
|
763
732
|
const out = [];
|
|
764
733
|
for (const f of faces) {
|
|
765
|
-
if (!inRange(f))
|
|
766
|
-
continue;
|
|
767
734
|
const n = p.faces[f].normal;
|
|
768
735
|
out.push(n.texture, n.textureRepeats, n.textureOffsets, n.textureRotation);
|
|
769
736
|
}
|
|
770
737
|
return { values: out, consumed: 1 };
|
|
771
738
|
}
|
|
772
739
|
case PRIM_SPECULAR: {
|
|
773
|
-
const faces = facesOf(rules[cursor]);
|
|
740
|
+
const faces = facesOf(p, rules[cursor]);
|
|
774
741
|
const out = [];
|
|
775
742
|
for (const f of faces) {
|
|
776
|
-
if (!inRange(f))
|
|
777
|
-
continue;
|
|
778
743
|
const s = p.faces[f].specular;
|
|
779
744
|
out.push(s.texture, s.textureRepeats, s.textureOffsets, s.textureRotation, s.color, s.glossiness, s.environment);
|
|
780
745
|
}
|
|
781
746
|
return { values: out, consumed: 1 };
|
|
782
747
|
}
|
|
783
748
|
case PRIM_ALPHA_MODE: {
|
|
784
|
-
const faces = facesOf(rules[cursor]);
|
|
749
|
+
const faces = facesOf(p, rules[cursor]);
|
|
785
750
|
const out = [];
|
|
786
751
|
for (const f of faces) {
|
|
787
|
-
if (!inRange(f))
|
|
788
|
-
continue;
|
|
789
752
|
out.push(p.faces[f].alphaMode.mode, p.faces[f].alphaMode.cutoff);
|
|
790
753
|
}
|
|
791
754
|
return { values: out, consumed: 1 };
|
|
792
755
|
}
|
|
793
756
|
case PRIM_GLTF_BASE_COLOR: {
|
|
794
|
-
const faces = facesOf(rules[cursor]);
|
|
757
|
+
const faces = facesOf(p, rules[cursor]);
|
|
795
758
|
const out = [];
|
|
796
759
|
for (const f of faces) {
|
|
797
|
-
if (!inRange(f))
|
|
798
|
-
continue;
|
|
799
760
|
const g = p.faces[f].gltf.baseColor;
|
|
800
761
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation, g.color, g.alpha, g.alphaMode, g.alphaCutoff, g.doubleSided);
|
|
801
762
|
}
|
|
802
763
|
return { values: out, consumed: 1 };
|
|
803
764
|
}
|
|
804
765
|
case PRIM_GLTF_NORMAL: {
|
|
805
|
-
const faces = facesOf(rules[cursor]);
|
|
766
|
+
const faces = facesOf(p, rules[cursor]);
|
|
806
767
|
const out = [];
|
|
807
768
|
for (const f of faces) {
|
|
808
|
-
if (!inRange(f))
|
|
809
|
-
continue;
|
|
810
769
|
const g = p.faces[f].gltf.normal;
|
|
811
770
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation);
|
|
812
771
|
}
|
|
813
772
|
return { values: out, consumed: 1 };
|
|
814
773
|
}
|
|
815
774
|
case PRIM_GLTF_METALLIC_ROUGHNESS: {
|
|
816
|
-
const faces = facesOf(rules[cursor]);
|
|
775
|
+
const faces = facesOf(p, rules[cursor]);
|
|
817
776
|
const out = [];
|
|
818
777
|
for (const f of faces) {
|
|
819
|
-
if (!inRange(f))
|
|
820
|
-
continue;
|
|
821
778
|
const g = p.faces[f].gltf.metallicRoughness;
|
|
822
779
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation, g.metallic, g.roughness);
|
|
823
780
|
}
|
|
824
781
|
return { values: out, consumed: 1 };
|
|
825
782
|
}
|
|
826
783
|
case PRIM_GLTF_EMISSIVE: {
|
|
827
|
-
const faces = facesOf(rules[cursor]);
|
|
784
|
+
const faces = facesOf(p, rules[cursor]);
|
|
828
785
|
const out = [];
|
|
829
786
|
for (const f of faces) {
|
|
830
|
-
if (!inRange(f))
|
|
831
|
-
continue;
|
|
832
787
|
const g = p.faces[f].gltf.emissive;
|
|
833
788
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation, g.tint);
|
|
834
789
|
}
|
|
@@ -921,4 +876,129 @@ export function primParamTypes(param, values) {
|
|
|
921
876
|
const pattern = param === PRIM_TYPE ? primTypeTypes(values[0]) : (PRIM_PARAM_TYPES[param] ?? []);
|
|
922
877
|
return values.map((_, i) => pattern[i % pattern.length]);
|
|
923
878
|
}
|
|
879
|
+
const PER_FACE_RULES = new Set([
|
|
880
|
+
PRIM_COLOR, PRIM_TEXTURE, PRIM_RENDER_MATERIAL, PRIM_FULLBRIGHT, PRIM_GLOW, PRIM_BUMP_SHINY,
|
|
881
|
+
PRIM_TEXGEN, PRIM_NORMAL, PRIM_SPECULAR, PRIM_ALPHA_MODE, PRIM_GLTF_BASE_COLOR,
|
|
882
|
+
PRIM_GLTF_NORMAL, PRIM_GLTF_METALLIC_ROUGHNESS, PRIM_GLTF_EMISSIVE,
|
|
883
|
+
]);
|
|
884
|
+
const RULE_CONSTANTS = {
|
|
885
|
+
PRIM_NAME, PRIM_DESC, PRIM_TEXT, PRIM_POSITION, PRIM_POS_LOCAL, PRIM_ROTATION, PRIM_ROT_LOCAL,
|
|
886
|
+
PRIM_SIZE, PRIM_SLICE, PRIM_MATERIAL, PRIM_PHYSICS, PRIM_PHANTOM, PRIM_TEMP_ON_REZ,
|
|
887
|
+
PRIM_PHYSICS_SHAPE_TYPE, PRIM_CAST_SHADOWS, PRIM_ALLOW_UNSIT, PRIM_SCRIPTED_SIT_ONLY,
|
|
888
|
+
PRIM_SIT_FLAGS, PRIM_CLICK_ACTION, PRIM_HEALTH, PRIM_DAMAGE, PRIM_OMEGA, PRIM_POINT_LIGHT,
|
|
889
|
+
PRIM_REFLECTION_PROBE, PRIM_PROJECTOR, PRIM_FLEXIBLE, PRIM_SIT_TARGET, PRIM_TYPE, PRIM_COLOR,
|
|
890
|
+
PRIM_TEXTURE, PRIM_RENDER_MATERIAL, PRIM_FULLBRIGHT, PRIM_GLOW, PRIM_BUMP_SHINY, PRIM_TEXGEN,
|
|
891
|
+
PRIM_NORMAL, PRIM_SPECULAR, PRIM_ALPHA_MODE, PRIM_GLTF_BASE_COLOR, PRIM_GLTF_NORMAL,
|
|
892
|
+
PRIM_GLTF_METALLIC_ROUGHNESS, PRIM_GLTF_EMISSIVE,
|
|
893
|
+
};
|
|
894
|
+
const RULE_NAMES = new Map(Object.entries(RULE_CONSTANTS).map(([name, value]) => [value, name]));
|
|
895
|
+
function givenType(rules, index) {
|
|
896
|
+
const known = listElementType(rules, index);
|
|
897
|
+
if (known)
|
|
898
|
+
return known;
|
|
899
|
+
const v = rules[index];
|
|
900
|
+
if (typeof v === 'string')
|
|
901
|
+
return 'string';
|
|
902
|
+
if (typeof v === 'number')
|
|
903
|
+
return Number.isInteger(v) ? 'integer' : 'float';
|
|
904
|
+
if (isRotation(v))
|
|
905
|
+
return 'rotation';
|
|
906
|
+
if (isVector(v))
|
|
907
|
+
return 'vector';
|
|
908
|
+
return 'list';
|
|
909
|
+
}
|
|
910
|
+
function typeAccepts(expected, given) {
|
|
911
|
+
if (expected === given)
|
|
912
|
+
return true;
|
|
913
|
+
const numeric = (t) => t === 'integer' || t === 'float';
|
|
914
|
+
const text = (t) => t === 'string' || t === 'key';
|
|
915
|
+
return (numeric(expected) && numeric(given)) || (text(expected) && text(given));
|
|
916
|
+
}
|
|
917
|
+
/** `%g`-style number text, as the simulator prints it in error messages. */
|
|
918
|
+
const formatG = (v) => String(Number(v.toPrecision(6)));
|
|
919
|
+
/**
|
|
920
|
+
* Check one PRIM_* rule of a set call before it is applied. Returns null if
|
|
921
|
+
* the rule can run, otherwise the error text that follows "rule #N" in the
|
|
922
|
+
* simulator's message (e.g. " (PRIM_SIZE): arg #1 vector expected but string given").
|
|
923
|
+
*/
|
|
924
|
+
/** GLTF override rules take "" in any slot after the face to mean "no override". */
|
|
925
|
+
const GLTF_RULES = new Set([PRIM_GLTF_BASE_COLOR, PRIM_GLTF_NORMAL, PRIM_GLTF_METALLIC_ROUGHNESS, PRIM_GLTF_EMISSIVE]);
|
|
926
|
+
export function checkPrimRule(param, rules, cursor) {
|
|
927
|
+
const name = RULE_NAMES.get(param);
|
|
928
|
+
if (name === undefined || writePrimParamSlots(param, rules, cursor) === null)
|
|
929
|
+
return ': unknown rule';
|
|
930
|
+
const pattern = param === PRIM_TYPE ? primTypeTypes(rules[cursor]) : PRIM_PARAM_TYPES[param];
|
|
931
|
+
const expected = PER_FACE_RULES.has(param) ? ['integer', ...pattern] : pattern;
|
|
932
|
+
for (let i = 0; i < expected.length; i++) {
|
|
933
|
+
if (cursor + i >= rules.length)
|
|
934
|
+
break;
|
|
935
|
+
if (i > 0 && GLTF_RULES.has(param) && rules[cursor + i] === '')
|
|
936
|
+
continue;
|
|
937
|
+
const given = givenType(rules, cursor + i);
|
|
938
|
+
if (!typeAccepts(expected[i], given)) {
|
|
939
|
+
return ` (${name}): arg #${i + 1} ${expected[i]} expected but ${given} given`;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (param === PRIM_GLOW) {
|
|
943
|
+
const glow = num(rules[cursor + 1]);
|
|
944
|
+
if (glow < 0 || glow > 1)
|
|
945
|
+
return ` (${name}): bounds error; ${formatG(glow)} is not in (0, 1)`;
|
|
946
|
+
}
|
|
947
|
+
return null;
|
|
948
|
+
}
|
|
949
|
+
const PROFILE_SIDES = {
|
|
950
|
+
[SHAPE_BOX]: 4, [SHAPE_CYLINDER]: 1, [SHAPE_PRISM]: 3, [SHAPE_SPHERE]: 1,
|
|
951
|
+
[SHAPE_TORUS]: 1, [SHAPE_TUBE]: 4, [SHAPE_RING]: 3,
|
|
952
|
+
};
|
|
953
|
+
const isCut = (range) => range.x > 0 || range.y < 1;
|
|
954
|
+
function faceRoles(shape) {
|
|
955
|
+
if (shape.kind === SHAPE_SCULPT)
|
|
956
|
+
return [{ from: 0, to: 1 }];
|
|
957
|
+
const looped = shape.kind === SHAPE_TORUS || shape.kind === SHAPE_TUBE || shape.kind === SHAPE_RING;
|
|
958
|
+
const profileCut = looped ? shape.advancedCut : shape.cut;
|
|
959
|
+
const pathEnds = shape.kind === SHAPE_SPHERE
|
|
960
|
+
? isCut(shape.dimple) || shape.hollow > 0
|
|
961
|
+
: !looped || isCut(shape.cut);
|
|
962
|
+
const sides = PROFILE_SIDES[shape.kind];
|
|
963
|
+
const roles = pathEnds ? ['top'] : [];
|
|
964
|
+
for (let i = 0; i < sides; i++) {
|
|
965
|
+
const from = i / sides, to = (i + 1) / sides;
|
|
966
|
+
if (from < profileCut.y && to > profileCut.x)
|
|
967
|
+
roles.push({ from, to });
|
|
968
|
+
}
|
|
969
|
+
if (shape.hollow > 0)
|
|
970
|
+
roles.push('inner');
|
|
971
|
+
if (pathEnds)
|
|
972
|
+
roles.push('bottom');
|
|
973
|
+
if (isCut(profileCut))
|
|
974
|
+
roles.push('cutStart', 'cutEnd');
|
|
975
|
+
return roles;
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Rebuild the face slots for a new shape. A face keeps the values of the old
|
|
979
|
+
* face with the same role; an outer side takes the first old outer side it
|
|
980
|
+
* overlaps, else the nearest one; any other new face copies the old last face.
|
|
981
|
+
*/
|
|
982
|
+
function remapFaces(p, oldShape) {
|
|
983
|
+
const oldRoles = faceRoles(oldShape);
|
|
984
|
+
const old = p.faces;
|
|
985
|
+
const last = old[old.length - 1];
|
|
986
|
+
const oldOuter = oldRoles.flatMap((r, i) => (typeof r === 'string' ? [] : [{ ...r, face: old[i] }]));
|
|
987
|
+
const source = (role) => {
|
|
988
|
+
if (typeof role === 'string')
|
|
989
|
+
return old[oldRoles.indexOf(role)] ?? last;
|
|
990
|
+
const gap = (o) => Math.max(o.from - role.to, role.from - o.to);
|
|
991
|
+
const overlap = oldOuter.find((o) => gap(o) < 0);
|
|
992
|
+
if (overlap)
|
|
993
|
+
return overlap.face;
|
|
994
|
+
const nearest = oldOuter.reduce((a, o) => (!a || gap(o) < gap(a) ? o : a), undefined);
|
|
995
|
+
return nearest?.face ?? last;
|
|
996
|
+
};
|
|
997
|
+
p.faces = faceRoles(p.shape).map((role) => structuredClone(source(role)));
|
|
998
|
+
p.glow = p.faces.map((f) => f.glow);
|
|
999
|
+
}
|
|
1000
|
+
/** Face count of a prim shape, as llGetNumberOfSides reports it. */
|
|
1001
|
+
export function numberOfSides(shape) {
|
|
1002
|
+
return faceRoles(shape).length;
|
|
1003
|
+
}
|
|
924
1004
|
//# sourceMappingURL=prim-params.js.map
|