@multiplekex/shallot 0.2.4 → 0.3.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/package.json +1 -1
- package/src/core/component.ts +1 -1
- package/src/core/index.ts +1 -13
- package/src/core/math.ts +186 -0
- package/src/core/state.ts +1 -1
- package/src/core/xml.ts +56 -41
- package/src/extras/arrows/index.ts +3 -3
- package/src/extras/caustic.ts +37 -0
- package/src/extras/gradient/index.ts +63 -69
- package/src/extras/index.ts +3 -0
- package/src/extras/lines/index.ts +3 -3
- package/src/extras/orbit/index.ts +1 -1
- package/src/extras/skylab/index.ts +314 -0
- package/src/extras/text/font.ts +69 -14
- package/src/extras/text/index.ts +17 -69
- package/src/extras/text/sdf.ts +13 -2
- package/src/extras/water/index.ts +119 -0
- package/src/standard/defaults.ts +2 -0
- package/src/standard/index.ts +2 -0
- package/src/standard/raster/batch.ts +149 -0
- package/src/standard/raster/forward.ts +832 -0
- package/src/standard/raster/index.ts +191 -0
- package/src/standard/raster/shadow.ts +408 -0
- package/src/standard/{render → raytracing}/bvh/blas.ts +336 -88
- package/src/standard/raytracing/bvh/radix.ts +473 -0
- package/src/standard/raytracing/bvh/refit.ts +711 -0
- package/src/standard/{render → raytracing}/bvh/structs.ts +0 -55
- package/src/standard/{render → raytracing}/bvh/tlas.ts +155 -140
- package/src/standard/{render → raytracing}/bvh/traverse.ts +72 -64
- package/src/standard/{render → raytracing}/depth.ts +9 -9
- package/src/standard/raytracing/index.ts +409 -0
- package/src/standard/{render → raytracing}/instance.ts +31 -16
- package/src/standard/{render → raytracing}/ray.ts +1 -1
- package/src/standard/raytracing/shaders.ts +798 -0
- package/src/standard/{render → raytracing}/triangle.ts +1 -1
- package/src/standard/render/camera.ts +96 -106
- package/src/standard/render/data.ts +1 -1
- package/src/standard/render/index.ts +136 -220
- package/src/standard/render/indirect.ts +9 -10
- package/src/standard/render/light.ts +2 -2
- package/src/standard/render/mesh.ts +404 -0
- package/src/standard/render/overlay.ts +8 -5
- package/src/standard/render/pass.ts +1 -1
- package/src/standard/render/postprocess.ts +263 -242
- package/src/standard/render/scene.ts +28 -16
- package/src/standard/render/surface/index.ts +81 -12
- package/src/standard/render/surface/shaders.ts +511 -0
- package/src/standard/render/surface/structs.ts +23 -6
- package/src/standard/tween/tween.ts +44 -115
- package/src/standard/render/bvh/radix.ts +0 -476
- package/src/standard/render/forward/index.ts +0 -259
- package/src/standard/render/forward/raster.ts +0 -228
- package/src/standard/render/mesh/box.ts +0 -20
- package/src/standard/render/mesh/index.ts +0 -446
- package/src/standard/render/mesh/plane.ts +0 -11
- package/src/standard/render/mesh/sphere.ts +0 -40
- package/src/standard/render/mesh/unified.ts +0 -96
- package/src/standard/render/shaders.ts +0 -484
- package/src/standard/render/surface/compile.ts +0 -67
- package/src/standard/render/surface/noise.ts +0 -45
- package/src/standard/render/surface/wgsl.ts +0 -573
- /package/src/standard/{render → raytracing}/intersection.ts +0 -0
package/package.json
CHANGED
package/src/core/component.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface FieldAccessor {
|
|
|
11
11
|
|
|
12
12
|
export interface ComponentTraits {
|
|
13
13
|
defaults?: () => Record<string, number>;
|
|
14
|
-
|
|
14
|
+
parse?: Record<string, (value: string) => number | undefined>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const traitsMap = new WeakMap<ComponentLike, ComponentTraits>();
|
package/src/core/index.ts
CHANGED
|
@@ -79,16 +79,4 @@ export { toKebabCase, toCamelCase } from "./strings";
|
|
|
79
79
|
|
|
80
80
|
export { initRuntime, getRuntime, resetRuntime, type Runtime, type RuntimeTarget } from "./runtime";
|
|
81
81
|
|
|
82
|
-
export {
|
|
83
|
-
parse,
|
|
84
|
-
serialize,
|
|
85
|
-
load,
|
|
86
|
-
registerPostLoadHook,
|
|
87
|
-
unregisterPostLoadHook,
|
|
88
|
-
type Node,
|
|
89
|
-
type Attr,
|
|
90
|
-
type Ref,
|
|
91
|
-
type ParseError,
|
|
92
|
-
type PostLoadHook,
|
|
93
|
-
type PostLoadContext,
|
|
94
|
-
} from "./xml";
|
|
82
|
+
export { parse, serialize, load, type Node, type Attr, type Ref, type ParseError } from "./xml";
|
package/src/core/math.ts
CHANGED
|
@@ -284,6 +284,192 @@ export function extractFrustumPlanes(viewProj: Float32Array): Float32Array {
|
|
|
284
284
|
return planes;
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
export function lookAtMatrix(
|
|
288
|
+
eyeX: number,
|
|
289
|
+
eyeY: number,
|
|
290
|
+
eyeZ: number,
|
|
291
|
+
targetX: number,
|
|
292
|
+
targetY: number,
|
|
293
|
+
targetZ: number,
|
|
294
|
+
upX = 0,
|
|
295
|
+
upY = 1,
|
|
296
|
+
upZ = 0
|
|
297
|
+
): Float32Array {
|
|
298
|
+
let zx = eyeX - targetX;
|
|
299
|
+
let zy = eyeY - targetY;
|
|
300
|
+
let zz = eyeZ - targetZ;
|
|
301
|
+
let zLen = Math.sqrt(zx * zx + zy * zy + zz * zz);
|
|
302
|
+
|
|
303
|
+
if (zLen < 1e-6) {
|
|
304
|
+
zx = 0;
|
|
305
|
+
zy = 0;
|
|
306
|
+
zz = 1;
|
|
307
|
+
} else {
|
|
308
|
+
zLen = 1 / zLen;
|
|
309
|
+
zx *= zLen;
|
|
310
|
+
zy *= zLen;
|
|
311
|
+
zz *= zLen;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
let xx = upY * zz - upZ * zy;
|
|
315
|
+
let xy = upZ * zx - upX * zz;
|
|
316
|
+
let xz = upX * zy - upY * zx;
|
|
317
|
+
let xLen = Math.sqrt(xx * xx + xy * xy + xz * xz);
|
|
318
|
+
|
|
319
|
+
if (xLen < 1e-6) {
|
|
320
|
+
if (Math.abs(zy) > 0.9) {
|
|
321
|
+
xx = 1;
|
|
322
|
+
xy = 0;
|
|
323
|
+
xz = 0;
|
|
324
|
+
} else {
|
|
325
|
+
xx = -zz;
|
|
326
|
+
xy = 0;
|
|
327
|
+
xz = zx;
|
|
328
|
+
}
|
|
329
|
+
xLen = Math.sqrt(xx * xx + xy * xy + xz * xz);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
xLen = 1 / xLen;
|
|
333
|
+
xx *= xLen;
|
|
334
|
+
xy *= xLen;
|
|
335
|
+
xz *= xLen;
|
|
336
|
+
|
|
337
|
+
const yx = zy * xz - zz * xy;
|
|
338
|
+
const yy = zz * xx - zx * xz;
|
|
339
|
+
const yz = zx * xy - zy * xx;
|
|
340
|
+
|
|
341
|
+
const tx = -(xx * eyeX + xy * eyeY + xz * eyeZ);
|
|
342
|
+
const ty = -(yx * eyeX + yy * eyeY + yz * eyeZ);
|
|
343
|
+
const tz = -(zx * eyeX + zy * eyeY + zz * eyeZ);
|
|
344
|
+
|
|
345
|
+
return new Float32Array([xx, yx, zx, 0, xy, yy, zy, 0, xz, yz, zz, 0, tx, ty, tz, 1]);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export function orthographicBounds(
|
|
349
|
+
left: number,
|
|
350
|
+
right: number,
|
|
351
|
+
bottom: number,
|
|
352
|
+
top: number,
|
|
353
|
+
near: number,
|
|
354
|
+
far: number
|
|
355
|
+
): Float32Array {
|
|
356
|
+
const lr = 1 / (right - left);
|
|
357
|
+
const bt = 1 / (top - bottom);
|
|
358
|
+
const nf = 1 / (near - far);
|
|
359
|
+
|
|
360
|
+
return new Float32Array([
|
|
361
|
+
2 * lr,
|
|
362
|
+
0,
|
|
363
|
+
0,
|
|
364
|
+
0,
|
|
365
|
+
0,
|
|
366
|
+
2 * bt,
|
|
367
|
+
0,
|
|
368
|
+
0,
|
|
369
|
+
0,
|
|
370
|
+
0,
|
|
371
|
+
nf,
|
|
372
|
+
0,
|
|
373
|
+
-(right + left) * lr,
|
|
374
|
+
-(top + bottom) * bt,
|
|
375
|
+
near * nf,
|
|
376
|
+
1,
|
|
377
|
+
]);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export function extractFrustumCorners(
|
|
381
|
+
invViewProj: Float32Array,
|
|
382
|
+
nearZ: number,
|
|
383
|
+
farZ: number
|
|
384
|
+
): Float32Array {
|
|
385
|
+
const corners = new Float32Array(24);
|
|
386
|
+
const ndcCorners = [
|
|
387
|
+
[-1, -1, nearZ],
|
|
388
|
+
[1, -1, nearZ],
|
|
389
|
+
[-1, 1, nearZ],
|
|
390
|
+
[1, 1, nearZ],
|
|
391
|
+
[-1, -1, farZ],
|
|
392
|
+
[1, -1, farZ],
|
|
393
|
+
[-1, 1, farZ],
|
|
394
|
+
[1, 1, farZ],
|
|
395
|
+
];
|
|
396
|
+
|
|
397
|
+
for (let i = 0; i < 8; i++) {
|
|
398
|
+
const [nx, ny, nz] = ndcCorners[i];
|
|
399
|
+
const m = invViewProj;
|
|
400
|
+
|
|
401
|
+
const wx = m[0] * nx + m[4] * ny + m[8] * nz + m[12];
|
|
402
|
+
const wy = m[1] * nx + m[5] * ny + m[9] * nz + m[13];
|
|
403
|
+
const wz = m[2] * nx + m[6] * ny + m[10] * nz + m[14];
|
|
404
|
+
const ww = m[3] * nx + m[7] * ny + m[11] * nz + m[15];
|
|
405
|
+
|
|
406
|
+
corners[i * 3] = wx / ww;
|
|
407
|
+
corners[i * 3 + 1] = wy / ww;
|
|
408
|
+
corners[i * 3 + 2] = wz / ww;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return corners;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export function invertMatrix(m: Float32Array): Float32Array {
|
|
415
|
+
const out = new Float32Array(16);
|
|
416
|
+
|
|
417
|
+
const a00 = m[0],
|
|
418
|
+
a01 = m[1],
|
|
419
|
+
a02 = m[2],
|
|
420
|
+
a03 = m[3];
|
|
421
|
+
const a10 = m[4],
|
|
422
|
+
a11 = m[5],
|
|
423
|
+
a12 = m[6],
|
|
424
|
+
a13 = m[7];
|
|
425
|
+
const a20 = m[8],
|
|
426
|
+
a21 = m[9],
|
|
427
|
+
a22 = m[10],
|
|
428
|
+
a23 = m[11];
|
|
429
|
+
const a30 = m[12],
|
|
430
|
+
a31 = m[13],
|
|
431
|
+
a32 = m[14],
|
|
432
|
+
a33 = m[15];
|
|
433
|
+
|
|
434
|
+
const b00 = a00 * a11 - a01 * a10;
|
|
435
|
+
const b01 = a00 * a12 - a02 * a10;
|
|
436
|
+
const b02 = a00 * a13 - a03 * a10;
|
|
437
|
+
const b03 = a01 * a12 - a02 * a11;
|
|
438
|
+
const b04 = a01 * a13 - a03 * a11;
|
|
439
|
+
const b05 = a02 * a13 - a03 * a12;
|
|
440
|
+
const b06 = a20 * a31 - a21 * a30;
|
|
441
|
+
const b07 = a20 * a32 - a22 * a30;
|
|
442
|
+
const b08 = a20 * a33 - a23 * a30;
|
|
443
|
+
const b09 = a21 * a32 - a22 * a31;
|
|
444
|
+
const b10 = a21 * a33 - a23 * a31;
|
|
445
|
+
const b11 = a22 * a33 - a23 * a32;
|
|
446
|
+
|
|
447
|
+
let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
|
448
|
+
if (Math.abs(det) < 1e-10) {
|
|
449
|
+
return out;
|
|
450
|
+
}
|
|
451
|
+
det = 1 / det;
|
|
452
|
+
|
|
453
|
+
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
|
|
454
|
+
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
|
|
455
|
+
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
|
|
456
|
+
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
|
|
457
|
+
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
|
|
458
|
+
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
|
|
459
|
+
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
|
|
460
|
+
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
|
|
461
|
+
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
|
|
462
|
+
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
|
|
463
|
+
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
|
|
464
|
+
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
|
|
465
|
+
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
|
|
466
|
+
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
|
|
467
|
+
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
|
|
468
|
+
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
|
|
469
|
+
|
|
470
|
+
return out;
|
|
471
|
+
}
|
|
472
|
+
|
|
287
473
|
export function lookAt(
|
|
288
474
|
eyeX: number,
|
|
289
475
|
eyeY: number,
|
package/src/core/state.ts
CHANGED
|
@@ -20,7 +20,7 @@ import type { RelationDef } from "./relation";
|
|
|
20
20
|
import type { Plugin, StateBuilder } from "./builder";
|
|
21
21
|
import { initRuntime, type Runtime } from "./runtime";
|
|
22
22
|
import { registerComponent, getTraits, type ComponentData } from "./component";
|
|
23
|
-
import {
|
|
23
|
+
import type { ResourceKey } from "./resource";
|
|
24
24
|
|
|
25
25
|
export const MAX_ENTITIES = 65536;
|
|
26
26
|
|
package/src/core/xml.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { addComponent, Pair } from "bitecs";
|
|
2
2
|
import type { State } from "./state";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getRegisteredComponent,
|
|
5
|
+
getTraits,
|
|
6
|
+
type ComponentLike,
|
|
7
|
+
type RegisteredComponent,
|
|
8
|
+
} from "./component";
|
|
4
9
|
import { getRelationDef, ChildOf } from "./relation";
|
|
5
10
|
import { toKebabCase, toCamelCase } from "./strings";
|
|
6
11
|
|
|
@@ -136,7 +141,7 @@ function tokenize(xml: string): Token[] {
|
|
|
136
141
|
|
|
137
142
|
function parseTagAttrs(tag: string): Record<string, string> {
|
|
138
143
|
const attrs: Record<string, string> = {};
|
|
139
|
-
const attrRegex = /([^\s
|
|
144
|
+
const attrRegex = /([^\s=<>/]+)(?:\s*=\s*"([^"]*)")?/g;
|
|
140
145
|
const inner = tag.replace(/^<\s*\w+/, "").replace(/\/?>$/, "");
|
|
141
146
|
let match: RegExpExecArray | null;
|
|
142
147
|
|
|
@@ -312,23 +317,6 @@ function parseNodeFromTokens(
|
|
|
312
317
|
};
|
|
313
318
|
}
|
|
314
319
|
|
|
315
|
-
export interface PostLoadContext {
|
|
316
|
-
getEntityByName(name: string): number | null;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export type PostLoadHook = (state: State, context: PostLoadContext) => void;
|
|
320
|
-
|
|
321
|
-
const postLoadHooks: PostLoadHook[] = [];
|
|
322
|
-
|
|
323
|
-
export function registerPostLoadHook(hook: PostLoadHook): void {
|
|
324
|
-
postLoadHooks.push(hook);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
export function unregisterPostLoadHook(hook: PostLoadHook): void {
|
|
328
|
-
const idx = postLoadHooks.indexOf(hook);
|
|
329
|
-
if (idx !== -1) postLoadHooks.splice(idx, 1);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
320
|
interface QueuedEntity {
|
|
333
321
|
node: Node;
|
|
334
322
|
eid: number;
|
|
@@ -376,13 +364,6 @@ export function load(nodes: Node[], state: State): Map<Node, number> {
|
|
|
376
364
|
setFieldValue(ref.component, ref.field, ref.eid, targetEid);
|
|
377
365
|
}
|
|
378
366
|
|
|
379
|
-
const context: PostLoadContext = {
|
|
380
|
-
getEntityByName: (name) => nameToEntity.get(name) ?? null,
|
|
381
|
-
};
|
|
382
|
-
for (const hook of postLoadHooks) {
|
|
383
|
-
hook(state, context);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
367
|
if (errors.length > 0) {
|
|
387
368
|
throw new Error(errors.map((e) => e.message).join("\n"));
|
|
388
369
|
}
|
|
@@ -487,24 +468,22 @@ function applyComponent(
|
|
|
487
468
|
props["_value"] = value;
|
|
488
469
|
}
|
|
489
470
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
const result = parseAttrs(def, props);
|
|
497
|
-
values = result.values;
|
|
498
|
-
entityRefs = result.entityRefs;
|
|
499
|
-
for (const err of result.errors) {
|
|
500
|
-
errors.push({ message: `<${name}> ${err}` });
|
|
501
|
-
}
|
|
471
|
+
const result = parseAttrs(def, props);
|
|
472
|
+
const values = result.values;
|
|
473
|
+
const strings = result.strings;
|
|
474
|
+
const entityRefs = result.entityRefs;
|
|
475
|
+
for (const err of result.errors) {
|
|
476
|
+
errors.push({ message: `<${name}> ${err}` });
|
|
502
477
|
}
|
|
503
478
|
|
|
504
479
|
for (const [field, val] of Object.entries(values)) {
|
|
505
480
|
setFieldValue(component, field, eid, val);
|
|
506
481
|
}
|
|
507
482
|
|
|
483
|
+
for (const [field, val] of Object.entries(strings)) {
|
|
484
|
+
setString(component, field, eid, val);
|
|
485
|
+
}
|
|
486
|
+
|
|
508
487
|
for (const ref of entityRefs) {
|
|
509
488
|
pendingFieldRefs.push({
|
|
510
489
|
eid,
|
|
@@ -520,10 +499,12 @@ function parseAttrs(
|
|
|
520
499
|
props: Record<string, string>
|
|
521
500
|
): {
|
|
522
501
|
values: Record<string, number>;
|
|
502
|
+
strings: Record<string, string>;
|
|
523
503
|
entityRefs: { field: string; targetName: string }[];
|
|
524
504
|
errors: string[];
|
|
525
505
|
} {
|
|
526
506
|
const allValues: Record<string, number> = {};
|
|
507
|
+
const allStrings: Record<string, string> = {};
|
|
527
508
|
const allEntityRefs: { field: string; targetName: string }[] = [];
|
|
528
509
|
const allErrors: string[] = [];
|
|
529
510
|
|
|
@@ -531,6 +512,7 @@ function parseAttrs(
|
|
|
531
512
|
if (isCSSAttrSyntax(props._value)) {
|
|
532
513
|
const result = parsePropertyString(def.name, props._value, def.component);
|
|
533
514
|
Object.assign(allValues, result.values);
|
|
515
|
+
Object.assign(allStrings, result.strings);
|
|
534
516
|
allEntityRefs.push(...result.entityRefs);
|
|
535
517
|
allErrors.push(...result.errors);
|
|
536
518
|
}
|
|
@@ -543,6 +525,7 @@ function parseAttrs(
|
|
|
543
525
|
if (isCSSAttrSyntax(propValue)) {
|
|
544
526
|
const result = parsePropertyString(def.name, propValue, def.component);
|
|
545
527
|
Object.assign(allValues, result.values);
|
|
528
|
+
Object.assign(allStrings, result.strings);
|
|
546
529
|
allEntityRefs.push(...result.entityRefs);
|
|
547
530
|
allErrors.push(...result.errors);
|
|
548
531
|
} else {
|
|
@@ -552,12 +535,13 @@ function parseAttrs(
|
|
|
552
535
|
def.component
|
|
553
536
|
);
|
|
554
537
|
Object.assign(allValues, result.values);
|
|
538
|
+
Object.assign(allStrings, result.strings);
|
|
555
539
|
allEntityRefs.push(...result.entityRefs);
|
|
556
540
|
allErrors.push(...result.errors);
|
|
557
541
|
}
|
|
558
542
|
}
|
|
559
543
|
|
|
560
|
-
return { values: allValues, entityRefs: allEntityRefs, errors: allErrors };
|
|
544
|
+
return { values: allValues, strings: allStrings, entityRefs: allEntityRefs, errors: allErrors };
|
|
561
545
|
}
|
|
562
546
|
|
|
563
547
|
function setFieldValue(component: ComponentLike, field: string, eid: number, value: number): void {
|
|
@@ -567,6 +551,17 @@ function setFieldValue(component: ComponentLike, field: string, eid: number, val
|
|
|
567
551
|
}
|
|
568
552
|
}
|
|
569
553
|
|
|
554
|
+
function isStringField(component: ComponentLike, field: string): boolean {
|
|
555
|
+
const val = component[field];
|
|
556
|
+
if (val == null) return false;
|
|
557
|
+
if (ArrayBuffer.isView(val) || Array.isArray(val)) return false;
|
|
558
|
+
return typeof val === "object";
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function setString(component: ComponentLike, field: string, eid: number, value: string): void {
|
|
562
|
+
(component[field] as Record<number, string>)[eid] = value;
|
|
563
|
+
}
|
|
564
|
+
|
|
570
565
|
function detectVec2(component: ComponentLike, base: string): boolean {
|
|
571
566
|
return `${base}X` in component && `${base}Y` in component;
|
|
572
567
|
}
|
|
@@ -594,7 +589,7 @@ function parseNumber(value: string): number | null {
|
|
|
594
589
|
if (value === "false") return 0;
|
|
595
590
|
|
|
596
591
|
const num = parseFloat(value);
|
|
597
|
-
return isNaN(num) ? null : num;
|
|
592
|
+
return Number.isNaN(num) ? null : num;
|
|
598
593
|
}
|
|
599
594
|
|
|
600
595
|
function parseValues(valueStr: string): (number | null)[] {
|
|
@@ -633,10 +628,12 @@ function parsePropertyString(
|
|
|
633
628
|
component: ComponentLike
|
|
634
629
|
): {
|
|
635
630
|
values: Record<string, number>;
|
|
631
|
+
strings: Record<string, string>;
|
|
636
632
|
entityRefs: { field: string; targetName: string }[];
|
|
637
633
|
errors: string[];
|
|
638
634
|
} {
|
|
639
635
|
const values: Record<string, number> = {};
|
|
636
|
+
const strings: Record<string, string> = {};
|
|
640
637
|
const entityRefs: { field: string; targetName: string }[] = [];
|
|
641
638
|
const errors: string[] = [];
|
|
642
639
|
|
|
@@ -679,6 +676,24 @@ function parsePropertyString(
|
|
|
679
676
|
const parsed = parseValues(valueStr);
|
|
680
677
|
|
|
681
678
|
if (parsed.some((v) => v === null)) {
|
|
679
|
+
const rawValue = valueStr.trim();
|
|
680
|
+
|
|
681
|
+
if (name in component && isStringField(component, name)) {
|
|
682
|
+
strings[name] = rawValue;
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
if (parsed.length === 1) {
|
|
687
|
+
const traits = getTraits(component);
|
|
688
|
+
const parseFn = traits?.parse?.[name];
|
|
689
|
+
if (parseFn) {
|
|
690
|
+
const resolved = parseFn(rawValue);
|
|
691
|
+
if (resolved !== undefined) {
|
|
692
|
+
values[name] = resolved;
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
682
697
|
errors.push(`Invalid number in "${prop}"`);
|
|
683
698
|
continue;
|
|
684
699
|
}
|
|
@@ -756,7 +771,7 @@ function parsePropertyString(
|
|
|
756
771
|
}
|
|
757
772
|
}
|
|
758
773
|
|
|
759
|
-
return { values, entityRefs, errors };
|
|
774
|
+
return { values, strings, entityRefs, errors };
|
|
760
775
|
}
|
|
761
776
|
|
|
762
777
|
function isCSSAttrSyntax(value: string): boolean {
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
type Draw,
|
|
18
18
|
type SharedPassContext,
|
|
19
19
|
} from "../../standard/render";
|
|
20
|
-
import {
|
|
21
|
-
import { SCENE_STRUCT_WGSL } from "../../standard/render/
|
|
20
|
+
import { Z_FORMAT } from "../../standard/render/scene";
|
|
21
|
+
import { SCENE_STRUCT_WGSL } from "../../standard/render/surface/structs";
|
|
22
22
|
import { Transform } from "../../standard/transforms";
|
|
23
23
|
import { Line, Lines, LinesPlugin } from "../lines";
|
|
24
24
|
|
|
@@ -198,7 +198,7 @@ export function createArrowsPipeline(
|
|
|
198
198
|
topology: "triangle-list",
|
|
199
199
|
},
|
|
200
200
|
depthStencil: {
|
|
201
|
-
format:
|
|
201
|
+
format: Z_FORMAT,
|
|
202
202
|
depthCompare: "less",
|
|
203
203
|
depthWriteEnabled: false,
|
|
204
204
|
},
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { surface } from "../standard/render/surface";
|
|
2
|
+
|
|
3
|
+
export const Caustic = surface({
|
|
4
|
+
fragment: `
|
|
5
|
+
let uv = (*surface).worldPos.xz;
|
|
6
|
+
let t = scene.time * 0.5;
|
|
7
|
+
|
|
8
|
+
// Fine caustic network
|
|
9
|
+
let f1 = sin(uv.x * 4.0 + t * 1.3 + sin(uv.y * 3.0 + t * 0.9) * 0.6);
|
|
10
|
+
let f2 = sin(uv.y * 5.0 - t * 1.1 + sin(uv.x * 3.5 - t * 0.7) * 0.5);
|
|
11
|
+
let f3 = sin((uv.x + uv.y) * 3.5 + t * 0.8);
|
|
12
|
+
let f4 = sin((uv.x - uv.y) * 4.0 - t * 1.2);
|
|
13
|
+
let f5 = sin(uv.x * 6.0 - uv.y * 2.5 + t * 1.5);
|
|
14
|
+
let f6 = sin(uv.y * 6.5 + uv.x * 2.0 - t * 1.0);
|
|
15
|
+
|
|
16
|
+
// Medium detail layer
|
|
17
|
+
let m1 = sin(uv.x * 2.5 + t * 0.7 + sin(uv.y * 1.5 + t * 0.5) * 0.4);
|
|
18
|
+
let m2 = sin(uv.y * 2.8 - t * 0.6 + sin(uv.x * 2.0 - t * 0.4) * 0.3);
|
|
19
|
+
|
|
20
|
+
// Sharp caustic lines using high power
|
|
21
|
+
let c1 = pow(max(0.0, 1.0 - abs(f1)), 12.0);
|
|
22
|
+
let c2 = pow(max(0.0, 1.0 - abs(f2)), 12.0);
|
|
23
|
+
let c3 = pow(max(0.0, 1.0 - abs(f3)), 10.0);
|
|
24
|
+
let c4 = pow(max(0.0, 1.0 - abs(f4)), 10.0);
|
|
25
|
+
let c5 = pow(max(0.0, 1.0 - abs(f5)), 14.0);
|
|
26
|
+
let c6 = pow(max(0.0, 1.0 - abs(f6)), 14.0);
|
|
27
|
+
let c7 = pow(max(0.0, 1.0 - abs(m1)), 8.0);
|
|
28
|
+
let c8 = pow(max(0.0, 1.0 - abs(m2)), 8.0);
|
|
29
|
+
|
|
30
|
+
// Combine layers with variation
|
|
31
|
+
let fine = (c1 + c2 + c3 + c4 + c5 + c6) * 0.12;
|
|
32
|
+
let medium = (c7 + c8) * 0.15;
|
|
33
|
+
let caustic = fine + medium;
|
|
34
|
+
|
|
35
|
+
let light = scene.sunColor.rgb * caustic * 0.3;
|
|
36
|
+
(*surface).baseColor += light;`,
|
|
37
|
+
});
|