@rezless/vm 0.3.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/NOTICE +26 -14
- 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/hash.js +1 -1
- package/dist/builtins/hash.js.map +1 -1
- 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 +1 -1
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +12 -5
- package/dist/dispatch.js.map +1 -1
- package/dist/generated/constants.d.ts +130 -18
- package/dist/generated/constants.d.ts.map +1 -1
- package/dist/generated/constants.js +254 -142
- package/dist/generated/constants.js.map +1 -1
- package/dist/generated/constants_table.d.ts +1 -1
- package/dist/generated/constants_table.d.ts.map +1 -1
- package/dist/generated/constants_table.js +247 -135
- package/dist/generated/constants_table.js.map +1 -1
- package/dist/generated/events.d.ts +22 -22
- package/dist/generated/events.d.ts.map +1 -1
- package/dist/generated/events.js +10 -10
- package/dist/generated/events.js.map +1 -1
- package/dist/generated/functions.d.ts +292 -187
- package/dist/generated/functions.d.ts.map +1 -1
- package/dist/generated/functions.js +149 -140
- package/dist/generated/functions.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.d.ts +1 -1
- package/dist/interpreter.d.ts.map +1 -1
- package/dist/interpreter.js +2 -2
- package/dist/interpreter.js.map +1 -1
- package/dist/inventory.d.ts +4 -2
- package/dist/inventory.d.ts.map +1 -1
- package/dist/inventory.js +6 -2
- 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 +9 -2
- package/dist/prim-params.d.ts.map +1 -1
- package/dist/prim-params.js +198 -113
- 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 +30 -5
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +94 -32
- package/dist/script.js.map +1 -1
- package/dist/typecheck.d.ts +1 -1
- package/dist/typecheck.js +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,10 +1,12 @@
|
|
|
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
|
-
* Typed-literal aliases for the
|
|
6
|
+
* Typed-literal aliases for the PRIM_TYPE_* constants. The
|
|
5
7
|
* generated module exports them as `: number` so TS can't narrow on
|
|
6
8
|
* them; we re-pin them to their literal values here. The `as` assertions
|
|
7
|
-
* are runtime-asserted below so a future
|
|
9
|
+
* are runtime-asserted below so a future upstream renumber would surface as
|
|
8
10
|
* a load-time failure rather than silent corruption.
|
|
9
11
|
*/
|
|
10
12
|
const SHAPE_BOX = PRIM_TYPE_BOX;
|
|
@@ -15,11 +17,16 @@ const SHAPE_TORUS = PRIM_TYPE_TORUS;
|
|
|
15
17
|
const SHAPE_TUBE = PRIM_TYPE_TUBE;
|
|
16
18
|
const SHAPE_RING = PRIM_TYPE_RING;
|
|
17
19
|
const SHAPE_SCULPT = PRIM_TYPE_SCULPT;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
/** Throws unless `shapes` lists PRIM_TYPE_BOX..PRIM_TYPE_SCULPT as 0..7 in order. */
|
|
21
|
+
export function assertShapeAliases(shapes) {
|
|
22
|
+
if (shapes.length !== 8 || shapes.some((v, i) => v !== i)) {
|
|
23
|
+
throw new Error('PRIM_TYPE_* constants disagree with PrimShape literal aliases');
|
|
24
|
+
}
|
|
22
25
|
}
|
|
26
|
+
assertShapeAliases([
|
|
27
|
+
SHAPE_BOX, SHAPE_CYLINDER, SHAPE_PRISM, SHAPE_SPHERE,
|
|
28
|
+
SHAPE_TORUS, SHAPE_TUBE, SHAPE_RING, SHAPE_SCULPT,
|
|
29
|
+
]);
|
|
23
30
|
const zero = () => ({ x: 0, y: 0, z: 0 });
|
|
24
31
|
const one = () => ({ x: 1, y: 1, z: 1 });
|
|
25
32
|
const identityRot = () => ({ x: 0, y: 0, z: 0, s: 1 });
|
|
@@ -75,7 +82,7 @@ export function defaultPrimParams() {
|
|
|
75
82
|
sculpt: { textureKey: '', type: PRIM_SCULPT_TYPE_SPHERE },
|
|
76
83
|
slice: { x: 0, y: 1, z: 0 },
|
|
77
84
|
shape: defaultShape(),
|
|
78
|
-
material:
|
|
85
|
+
material: PRIM_MATERIAL_WOOD,
|
|
79
86
|
tempOnRez: false,
|
|
80
87
|
castShadows: false,
|
|
81
88
|
allowUnsit: true,
|
|
@@ -87,7 +94,7 @@ export function defaultPrimParams() {
|
|
|
87
94
|
damage: { amount: 0, type: 0 },
|
|
88
95
|
health: 1,
|
|
89
96
|
reflectionProbe: { enabled: false, ambiance: 0, clipDistance: 0, flags: 0 },
|
|
90
|
-
physicsMaterial: { gravityMultiplier: 1, restitution: 0, friction: 0, density: 1000 },
|
|
97
|
+
physicsMaterial: { gravityMultiplier: 1, restitution: 0.5, friction: Math.fround(0.6), density: 1000 },
|
|
91
98
|
textureAnim: { mode: 0, face: 0, sizex: 0, sizey: 0, start: 0, length: 0, rate: 0 },
|
|
92
99
|
passCollisions: 0,
|
|
93
100
|
passTouches: 0,
|
|
@@ -113,15 +120,21 @@ const asRot = (v) => {
|
|
|
113
120
|
return identityRot();
|
|
114
121
|
};
|
|
115
122
|
const toByteChannel = (c) => Math.floor(Math.min(1, Math.max(0, c)) * 255) / 255;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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 };
|
|
121
130
|
}
|
|
122
|
-
|
|
123
|
-
|
|
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] : [];
|
|
124
136
|
}
|
|
137
|
+
const facesOf = (p, faceArg) => faceIndices(p, num(faceArg, 0) | 0);
|
|
125
138
|
/**
|
|
126
139
|
* Slot count for a PRIM_* rule's *write* form, given the rule constant
|
|
127
140
|
* and (for variable-shape rules like PRIM_TYPE) the rules list + cursor
|
|
@@ -205,14 +218,14 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
205
218
|
const p = prim.params;
|
|
206
219
|
switch (param) {
|
|
207
220
|
case PRIM_NAME:
|
|
208
|
-
prim.name = str(rules[cursor]);
|
|
221
|
+
prim.name = truncateUtf8(str(rules[cursor]), 63);
|
|
209
222
|
return 1;
|
|
210
223
|
case PRIM_DESC:
|
|
211
|
-
prim.description = str(rules[cursor]);
|
|
224
|
+
prim.description = truncateUtf8(str(rules[cursor]), 127);
|
|
212
225
|
prim.appearance.description = prim.description;
|
|
213
226
|
return 1;
|
|
214
227
|
case PRIM_TEXT: {
|
|
215
|
-
const text = str(rules[cursor]);
|
|
228
|
+
const text = truncateUtf8(str(rules[cursor]), 254);
|
|
216
229
|
const color = asVec(rules[cursor + 1]);
|
|
217
230
|
const alpha = num(rules[cursor + 2], 1);
|
|
218
231
|
prim.appearance.text = { text, color, alpha };
|
|
@@ -224,10 +237,10 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
224
237
|
return 1;
|
|
225
238
|
case PRIM_ROTATION:
|
|
226
239
|
case PRIM_ROT_LOCAL:
|
|
227
|
-
p.rotation = asRot(rules[cursor]);
|
|
240
|
+
p.rotation = normalizeRot(asRot(rules[cursor]));
|
|
228
241
|
return 1;
|
|
229
242
|
case PRIM_SIZE:
|
|
230
|
-
p.size = asVec(rules[cursor]);
|
|
243
|
+
p.size = clampVec(asVec(rules[cursor]), 0.01, 64);
|
|
231
244
|
return 1;
|
|
232
245
|
case PRIM_SLICE:
|
|
233
246
|
p.slice = asVec(rules[cursor]);
|
|
@@ -317,27 +330,22 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
317
330
|
case PRIM_TYPE:
|
|
318
331
|
return writePrimType(p, rules, cursor);
|
|
319
332
|
case PRIM_COLOR: {
|
|
320
|
-
const faces = facesOf(rules[cursor]);
|
|
333
|
+
const faces = facesOf(p, rules[cursor]);
|
|
321
334
|
const color = asVec(rules[cursor + 1]);
|
|
322
|
-
const alpha = num(rules[cursor + 2], 1);
|
|
335
|
+
const alpha = clamp(num(rules[cursor + 2], 1), 0, 1);
|
|
323
336
|
for (const f of faces) {
|
|
324
|
-
|
|
325
|
-
continue;
|
|
326
|
-
// Clone so faces don't alias the same vector instance.
|
|
327
|
-
p.faces[f].color = { x: color.x, y: color.y, z: color.z };
|
|
337
|
+
p.faces[f].color = clampVec(color, 0, 1);
|
|
328
338
|
p.faces[f].alpha = alpha;
|
|
329
339
|
}
|
|
330
340
|
return 3;
|
|
331
341
|
}
|
|
332
342
|
case PRIM_TEXTURE: {
|
|
333
|
-
const faces = facesOf(rules[cursor]);
|
|
343
|
+
const faces = facesOf(p, rules[cursor]);
|
|
334
344
|
const tex = str(rules[cursor + 1]);
|
|
335
345
|
const repeats = asVec(rules[cursor + 2]);
|
|
336
346
|
const offsets = asVec(rules[cursor + 3]);
|
|
337
347
|
const rot = num(rules[cursor + 4]);
|
|
338
348
|
for (const f of faces) {
|
|
339
|
-
if (!inRange(f))
|
|
340
|
-
continue;
|
|
341
349
|
p.faces[f].texture = tex;
|
|
342
350
|
p.faces[f].textureRepeats = { x: repeats.x, y: repeats.y, z: repeats.z };
|
|
343
351
|
p.faces[f].textureOffsets = { x: offsets.x, y: offsets.y, z: offsets.z };
|
|
@@ -346,66 +354,54 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
346
354
|
return 5;
|
|
347
355
|
}
|
|
348
356
|
case PRIM_RENDER_MATERIAL: {
|
|
349
|
-
const faces = facesOf(rules[cursor]);
|
|
357
|
+
const faces = facesOf(p, rules[cursor]);
|
|
350
358
|
const m = str(rules[cursor + 1]);
|
|
351
359
|
for (const f of faces) {
|
|
352
|
-
if (!inRange(f))
|
|
353
|
-
continue;
|
|
354
360
|
p.faces[f].renderMaterial = m;
|
|
355
361
|
}
|
|
356
362
|
return 2;
|
|
357
363
|
}
|
|
358
364
|
case PRIM_FULLBRIGHT: {
|
|
359
|
-
const faces = facesOf(rules[cursor]);
|
|
365
|
+
const faces = facesOf(p, rules[cursor]);
|
|
360
366
|
const v = num(rules[cursor + 1]) !== 0;
|
|
361
367
|
for (const f of faces) {
|
|
362
|
-
if (!inRange(f))
|
|
363
|
-
continue;
|
|
364
368
|
p.faces[f].fullBright = v;
|
|
365
369
|
}
|
|
366
370
|
return 2;
|
|
367
371
|
}
|
|
368
372
|
case PRIM_GLOW: {
|
|
369
|
-
const faces = facesOf(rules[cursor]);
|
|
373
|
+
const faces = facesOf(p, rules[cursor]);
|
|
370
374
|
const v = num(rules[cursor + 1]);
|
|
371
375
|
for (const f of faces) {
|
|
372
|
-
if (!inRange(f))
|
|
373
|
-
continue;
|
|
374
376
|
p.faces[f].glow = v;
|
|
375
377
|
p.glow[f] = v;
|
|
376
378
|
}
|
|
377
379
|
return 2;
|
|
378
380
|
}
|
|
379
381
|
case PRIM_BUMP_SHINY: {
|
|
380
|
-
const faces = facesOf(rules[cursor]);
|
|
382
|
+
const faces = facesOf(p, rules[cursor]);
|
|
381
383
|
const shiny = num(rules[cursor + 1]) | 0;
|
|
382
384
|
const bump = num(rules[cursor + 2]) | 0;
|
|
383
385
|
for (const f of faces) {
|
|
384
|
-
if (!inRange(f))
|
|
385
|
-
continue;
|
|
386
386
|
p.faces[f].bumpShiny = { shiny, bump };
|
|
387
387
|
}
|
|
388
388
|
return 3;
|
|
389
389
|
}
|
|
390
390
|
case PRIM_TEXGEN: {
|
|
391
|
-
const faces = facesOf(rules[cursor]);
|
|
391
|
+
const faces = facesOf(p, rules[cursor]);
|
|
392
392
|
const mode = num(rules[cursor + 1]) | 0;
|
|
393
393
|
for (const f of faces) {
|
|
394
|
-
if (!inRange(f))
|
|
395
|
-
continue;
|
|
396
394
|
p.faces[f].texgen = mode;
|
|
397
395
|
}
|
|
398
396
|
return 2;
|
|
399
397
|
}
|
|
400
398
|
case PRIM_NORMAL: {
|
|
401
|
-
const faces = facesOf(rules[cursor]);
|
|
399
|
+
const faces = facesOf(p, rules[cursor]);
|
|
402
400
|
const tex = str(rules[cursor + 1]);
|
|
403
401
|
const repeats = asVec(rules[cursor + 2]);
|
|
404
402
|
const offsets = asVec(rules[cursor + 3]);
|
|
405
403
|
const rot = num(rules[cursor + 4]);
|
|
406
404
|
for (const f of faces) {
|
|
407
|
-
if (!inRange(f))
|
|
408
|
-
continue;
|
|
409
405
|
p.faces[f].normal = {
|
|
410
406
|
texture: tex,
|
|
411
407
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -416,7 +412,7 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
416
412
|
return 5;
|
|
417
413
|
}
|
|
418
414
|
case PRIM_SPECULAR: {
|
|
419
|
-
const faces = facesOf(rules[cursor]);
|
|
415
|
+
const faces = facesOf(p, rules[cursor]);
|
|
420
416
|
const tex = str(rules[cursor + 1]);
|
|
421
417
|
const repeats = asVec(rules[cursor + 2]);
|
|
422
418
|
const offsets = asVec(rules[cursor + 3]);
|
|
@@ -425,8 +421,6 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
425
421
|
const gloss = num(rules[cursor + 6]) | 0;
|
|
426
422
|
const env = num(rules[cursor + 7]) | 0;
|
|
427
423
|
for (const f of faces) {
|
|
428
|
-
if (!inRange(f))
|
|
429
|
-
continue;
|
|
430
424
|
p.faces[f].specular = {
|
|
431
425
|
texture: tex,
|
|
432
426
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -441,18 +435,16 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
441
435
|
return 8;
|
|
442
436
|
}
|
|
443
437
|
case PRIM_ALPHA_MODE: {
|
|
444
|
-
const faces = facesOf(rules[cursor]);
|
|
438
|
+
const faces = facesOf(p, rules[cursor]);
|
|
445
439
|
const mode = num(rules[cursor + 1]) | 0;
|
|
446
440
|
const cutoff = num(rules[cursor + 2]) | 0;
|
|
447
441
|
for (const f of faces) {
|
|
448
|
-
if (!inRange(f))
|
|
449
|
-
continue;
|
|
450
442
|
p.faces[f].alphaMode = { mode, cutoff };
|
|
451
443
|
}
|
|
452
444
|
return 3;
|
|
453
445
|
}
|
|
454
446
|
case PRIM_GLTF_BASE_COLOR: {
|
|
455
|
-
const faces = facesOf(rules[cursor]);
|
|
447
|
+
const faces = facesOf(p, rules[cursor]);
|
|
456
448
|
const tex = str(rules[cursor + 1]);
|
|
457
449
|
const repeats = asVec(rules[cursor + 2]);
|
|
458
450
|
const offsets = asVec(rules[cursor + 3]);
|
|
@@ -463,8 +455,6 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
463
455
|
const aCut = num(rules[cursor + 8]);
|
|
464
456
|
const dbl = num(rules[cursor + 9]) | 0;
|
|
465
457
|
for (const f of faces) {
|
|
466
|
-
if (!inRange(f))
|
|
467
|
-
continue;
|
|
468
458
|
p.faces[f].gltf.baseColor = {
|
|
469
459
|
texture: tex,
|
|
470
460
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -480,14 +470,12 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
480
470
|
return 10;
|
|
481
471
|
}
|
|
482
472
|
case PRIM_GLTF_NORMAL: {
|
|
483
|
-
const faces = facesOf(rules[cursor]);
|
|
473
|
+
const faces = facesOf(p, rules[cursor]);
|
|
484
474
|
const tex = str(rules[cursor + 1]);
|
|
485
475
|
const repeats = asVec(rules[cursor + 2]);
|
|
486
476
|
const offsets = asVec(rules[cursor + 3]);
|
|
487
477
|
const rot = num(rules[cursor + 4]);
|
|
488
478
|
for (const f of faces) {
|
|
489
|
-
if (!inRange(f))
|
|
490
|
-
continue;
|
|
491
479
|
p.faces[f].gltf.normal = {
|
|
492
480
|
texture: tex,
|
|
493
481
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -498,7 +486,7 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
498
486
|
return 5;
|
|
499
487
|
}
|
|
500
488
|
case PRIM_GLTF_METALLIC_ROUGHNESS: {
|
|
501
|
-
const faces = facesOf(rules[cursor]);
|
|
489
|
+
const faces = facesOf(p, rules[cursor]);
|
|
502
490
|
const tex = str(rules[cursor + 1]);
|
|
503
491
|
const repeats = asVec(rules[cursor + 2]);
|
|
504
492
|
const offsets = asVec(rules[cursor + 3]);
|
|
@@ -506,8 +494,6 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
506
494
|
const metallic = num(rules[cursor + 5]);
|
|
507
495
|
const rough = num(rules[cursor + 6]);
|
|
508
496
|
for (const f of faces) {
|
|
509
|
-
if (!inRange(f))
|
|
510
|
-
continue;
|
|
511
497
|
p.faces[f].gltf.metallicRoughness = {
|
|
512
498
|
texture: tex,
|
|
513
499
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -520,15 +506,13 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
520
506
|
return 7;
|
|
521
507
|
}
|
|
522
508
|
case PRIM_GLTF_EMISSIVE: {
|
|
523
|
-
const faces = facesOf(rules[cursor]);
|
|
509
|
+
const faces = facesOf(p, rules[cursor]);
|
|
524
510
|
const tex = str(rules[cursor + 1]);
|
|
525
511
|
const repeats = asVec(rules[cursor + 2]);
|
|
526
512
|
const offsets = asVec(rules[cursor + 3]);
|
|
527
513
|
const rot = num(rules[cursor + 4]);
|
|
528
514
|
const tint = asVec(rules[cursor + 5]);
|
|
529
515
|
for (const f of faces) {
|
|
530
|
-
if (!inRange(f))
|
|
531
|
-
continue;
|
|
532
516
|
p.faces[f].gltf.emissive = {
|
|
533
517
|
texture: tex,
|
|
534
518
|
textureRepeats: { x: repeats.x, y: repeats.y, z: repeats.z },
|
|
@@ -547,6 +531,7 @@ export function writePrimParam(prim, param, rules, cursor) {
|
|
|
547
531
|
}
|
|
548
532
|
function writePrimType(p, rules, cursor) {
|
|
549
533
|
const kind = (num(rules[cursor]) | 0);
|
|
534
|
+
const old = p.shape;
|
|
550
535
|
switch (kind) {
|
|
551
536
|
case SHAPE_BOX:
|
|
552
537
|
case SHAPE_CYLINDER:
|
|
@@ -560,7 +545,7 @@ function writePrimType(p, rules, cursor) {
|
|
|
560
545
|
topSize: asVec(rules[cursor + 5]),
|
|
561
546
|
topShear: asVec(rules[cursor + 6]),
|
|
562
547
|
};
|
|
563
|
-
|
|
548
|
+
break;
|
|
564
549
|
case SHAPE_SPHERE:
|
|
565
550
|
p.shape = {
|
|
566
551
|
kind: SHAPE_SPHERE,
|
|
@@ -570,7 +555,7 @@ function writePrimType(p, rules, cursor) {
|
|
|
570
555
|
twist: asVec(rules[cursor + 4]),
|
|
571
556
|
dimple: asVec(rules[cursor + 5]),
|
|
572
557
|
};
|
|
573
|
-
|
|
558
|
+
break;
|
|
574
559
|
case SHAPE_TORUS:
|
|
575
560
|
case SHAPE_TUBE:
|
|
576
561
|
case SHAPE_RING:
|
|
@@ -588,14 +573,14 @@ function writePrimType(p, rules, cursor) {
|
|
|
588
573
|
radiusOffset: num(rules[cursor + 10]),
|
|
589
574
|
skew: num(rules[cursor + 11]),
|
|
590
575
|
};
|
|
591
|
-
|
|
576
|
+
break;
|
|
592
577
|
case SHAPE_SCULPT:
|
|
593
578
|
p.shape = {
|
|
594
579
|
kind: SHAPE_SCULPT,
|
|
595
580
|
map: str(rules[cursor + 1]),
|
|
596
581
|
type: num(rules[cursor + 2]) | 0,
|
|
597
582
|
};
|
|
598
|
-
|
|
583
|
+
break;
|
|
599
584
|
default:
|
|
600
585
|
// Unknown PRIM_TYPE_* kind: terminate the walk rather than guessing
|
|
601
586
|
// a slot count. Matches writePrimParamSlots' default behavior so
|
|
@@ -603,6 +588,8 @@ function writePrimType(p, rules, cursor) {
|
|
|
603
588
|
// same way.
|
|
604
589
|
return null;
|
|
605
590
|
}
|
|
591
|
+
remapFaces(p, old);
|
|
592
|
+
return writePrimParamSlots(PRIM_TYPE, rules, cursor);
|
|
606
593
|
}
|
|
607
594
|
/**
|
|
608
595
|
* Read a single PRIM_* rule, returning the flat values it expands to and
|
|
@@ -622,6 +609,7 @@ export function readPrimParam(prim, param, rules, cursor) {
|
|
|
622
609
|
return { values: t ? [t.text, t.color, t.alpha] : ['', zero(), 0], consumed: 0 };
|
|
623
610
|
}
|
|
624
611
|
case PRIM_POSITION:
|
|
612
|
+
return { values: [prim.regionPosition()], consumed: 0 };
|
|
625
613
|
case PRIM_POS_LOCAL:
|
|
626
614
|
return { values: [p.position], consumed: 0 };
|
|
627
615
|
case PRIM_ROTATION:
|
|
@@ -683,147 +671,119 @@ export function readPrimParam(prim, param, rules, cursor) {
|
|
|
683
671
|
case PRIM_TYPE:
|
|
684
672
|
return { values: readPrimType(p), consumed: 0 };
|
|
685
673
|
case PRIM_COLOR: {
|
|
686
|
-
const faces = facesOf(rules[cursor]);
|
|
674
|
+
const faces = facesOf(p, rules[cursor]);
|
|
687
675
|
const out = [];
|
|
688
676
|
for (const f of faces) {
|
|
689
|
-
if (!inRange(f))
|
|
690
|
-
continue;
|
|
691
677
|
out.push(p.faces[f].color, p.faces[f].alpha);
|
|
692
678
|
}
|
|
693
679
|
return { values: out, consumed: 1 };
|
|
694
680
|
}
|
|
695
681
|
case PRIM_TEXTURE: {
|
|
696
|
-
const faces = facesOf(rules[cursor]);
|
|
682
|
+
const faces = facesOf(p, rules[cursor]);
|
|
697
683
|
const out = [];
|
|
698
684
|
for (const f of faces) {
|
|
699
|
-
if (!inRange(f))
|
|
700
|
-
continue;
|
|
701
685
|
const fa = p.faces[f];
|
|
702
686
|
out.push(fa.texture, fa.textureRepeats, fa.textureOffsets, fa.textureRotation);
|
|
703
687
|
}
|
|
704
688
|
return { values: out, consumed: 1 };
|
|
705
689
|
}
|
|
706
690
|
case PRIM_RENDER_MATERIAL: {
|
|
707
|
-
const faces = facesOf(rules[cursor]);
|
|
691
|
+
const faces = facesOf(p, rules[cursor]);
|
|
708
692
|
const out = [];
|
|
709
693
|
for (const f of faces) {
|
|
710
|
-
if (!inRange(f))
|
|
711
|
-
continue;
|
|
712
694
|
out.push(p.faces[f].renderMaterial);
|
|
713
695
|
}
|
|
714
696
|
return { values: out, consumed: 1 };
|
|
715
697
|
}
|
|
716
698
|
case PRIM_FULLBRIGHT: {
|
|
717
|
-
const faces = facesOf(rules[cursor]);
|
|
699
|
+
const faces = facesOf(p, rules[cursor]);
|
|
718
700
|
const out = [];
|
|
719
701
|
for (const f of faces) {
|
|
720
|
-
if (!inRange(f))
|
|
721
|
-
continue;
|
|
722
702
|
out.push(p.faces[f].fullBright ? 1 : 0);
|
|
723
703
|
}
|
|
724
704
|
return { values: out, consumed: 1 };
|
|
725
705
|
}
|
|
726
706
|
case PRIM_GLOW: {
|
|
727
|
-
const faces = facesOf(rules[cursor]);
|
|
707
|
+
const faces = facesOf(p, rules[cursor]);
|
|
728
708
|
const out = [];
|
|
729
709
|
for (const f of faces) {
|
|
730
|
-
if (!inRange(f))
|
|
731
|
-
continue;
|
|
732
710
|
out.push(p.faces[f].glow);
|
|
733
711
|
}
|
|
734
712
|
return { values: out, consumed: 1 };
|
|
735
713
|
}
|
|
736
714
|
case PRIM_BUMP_SHINY: {
|
|
737
|
-
const faces = facesOf(rules[cursor]);
|
|
715
|
+
const faces = facesOf(p, rules[cursor]);
|
|
738
716
|
const out = [];
|
|
739
717
|
for (const f of faces) {
|
|
740
|
-
if (!inRange(f))
|
|
741
|
-
continue;
|
|
742
718
|
out.push(p.faces[f].bumpShiny.shiny, p.faces[f].bumpShiny.bump);
|
|
743
719
|
}
|
|
744
720
|
return { values: out, consumed: 1 };
|
|
745
721
|
}
|
|
746
722
|
case PRIM_TEXGEN: {
|
|
747
|
-
const faces = facesOf(rules[cursor]);
|
|
723
|
+
const faces = facesOf(p, rules[cursor]);
|
|
748
724
|
const out = [];
|
|
749
725
|
for (const f of faces) {
|
|
750
|
-
if (!inRange(f))
|
|
751
|
-
continue;
|
|
752
726
|
out.push(p.faces[f].texgen);
|
|
753
727
|
}
|
|
754
728
|
return { values: out, consumed: 1 };
|
|
755
729
|
}
|
|
756
730
|
case PRIM_NORMAL: {
|
|
757
|
-
const faces = facesOf(rules[cursor]);
|
|
731
|
+
const faces = facesOf(p, rules[cursor]);
|
|
758
732
|
const out = [];
|
|
759
733
|
for (const f of faces) {
|
|
760
|
-
if (!inRange(f))
|
|
761
|
-
continue;
|
|
762
734
|
const n = p.faces[f].normal;
|
|
763
735
|
out.push(n.texture, n.textureRepeats, n.textureOffsets, n.textureRotation);
|
|
764
736
|
}
|
|
765
737
|
return { values: out, consumed: 1 };
|
|
766
738
|
}
|
|
767
739
|
case PRIM_SPECULAR: {
|
|
768
|
-
const faces = facesOf(rules[cursor]);
|
|
740
|
+
const faces = facesOf(p, rules[cursor]);
|
|
769
741
|
const out = [];
|
|
770
742
|
for (const f of faces) {
|
|
771
|
-
if (!inRange(f))
|
|
772
|
-
continue;
|
|
773
743
|
const s = p.faces[f].specular;
|
|
774
744
|
out.push(s.texture, s.textureRepeats, s.textureOffsets, s.textureRotation, s.color, s.glossiness, s.environment);
|
|
775
745
|
}
|
|
776
746
|
return { values: out, consumed: 1 };
|
|
777
747
|
}
|
|
778
748
|
case PRIM_ALPHA_MODE: {
|
|
779
|
-
const faces = facesOf(rules[cursor]);
|
|
749
|
+
const faces = facesOf(p, rules[cursor]);
|
|
780
750
|
const out = [];
|
|
781
751
|
for (const f of faces) {
|
|
782
|
-
if (!inRange(f))
|
|
783
|
-
continue;
|
|
784
752
|
out.push(p.faces[f].alphaMode.mode, p.faces[f].alphaMode.cutoff);
|
|
785
753
|
}
|
|
786
754
|
return { values: out, consumed: 1 };
|
|
787
755
|
}
|
|
788
756
|
case PRIM_GLTF_BASE_COLOR: {
|
|
789
|
-
const faces = facesOf(rules[cursor]);
|
|
757
|
+
const faces = facesOf(p, rules[cursor]);
|
|
790
758
|
const out = [];
|
|
791
759
|
for (const f of faces) {
|
|
792
|
-
if (!inRange(f))
|
|
793
|
-
continue;
|
|
794
760
|
const g = p.faces[f].gltf.baseColor;
|
|
795
761
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation, g.color, g.alpha, g.alphaMode, g.alphaCutoff, g.doubleSided);
|
|
796
762
|
}
|
|
797
763
|
return { values: out, consumed: 1 };
|
|
798
764
|
}
|
|
799
765
|
case PRIM_GLTF_NORMAL: {
|
|
800
|
-
const faces = facesOf(rules[cursor]);
|
|
766
|
+
const faces = facesOf(p, rules[cursor]);
|
|
801
767
|
const out = [];
|
|
802
768
|
for (const f of faces) {
|
|
803
|
-
if (!inRange(f))
|
|
804
|
-
continue;
|
|
805
769
|
const g = p.faces[f].gltf.normal;
|
|
806
770
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation);
|
|
807
771
|
}
|
|
808
772
|
return { values: out, consumed: 1 };
|
|
809
773
|
}
|
|
810
774
|
case PRIM_GLTF_METALLIC_ROUGHNESS: {
|
|
811
|
-
const faces = facesOf(rules[cursor]);
|
|
775
|
+
const faces = facesOf(p, rules[cursor]);
|
|
812
776
|
const out = [];
|
|
813
777
|
for (const f of faces) {
|
|
814
|
-
if (!inRange(f))
|
|
815
|
-
continue;
|
|
816
778
|
const g = p.faces[f].gltf.metallicRoughness;
|
|
817
779
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation, g.metallic, g.roughness);
|
|
818
780
|
}
|
|
819
781
|
return { values: out, consumed: 1 };
|
|
820
782
|
}
|
|
821
783
|
case PRIM_GLTF_EMISSIVE: {
|
|
822
|
-
const faces = facesOf(rules[cursor]);
|
|
784
|
+
const faces = facesOf(p, rules[cursor]);
|
|
823
785
|
const out = [];
|
|
824
786
|
for (const f of faces) {
|
|
825
|
-
if (!inRange(f))
|
|
826
|
-
continue;
|
|
827
787
|
const g = p.faces[f].gltf.emissive;
|
|
828
788
|
out.push(g.texture, g.textureRepeats, g.textureOffsets, g.textureRotation, g.tint);
|
|
829
789
|
}
|
|
@@ -916,4 +876,129 @@ export function primParamTypes(param, values) {
|
|
|
916
876
|
const pattern = param === PRIM_TYPE ? primTypeTypes(values[0]) : (PRIM_PARAM_TYPES[param] ?? []);
|
|
917
877
|
return values.map((_, i) => pattern[i % pattern.length]);
|
|
918
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
|
+
}
|
|
919
1004
|
//# sourceMappingURL=prim-params.js.map
|