reze-engine 0.65.0 → 0.66.1
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/engine.d.ts +156 -42
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +876 -186
- package/dist/graph/compile.d.ts.map +1 -1
- package/dist/graph/compile.js +5 -0
- package/dist/graph/presets/body.d.ts.map +1 -1
- package/dist/graph/presets/body.js +26 -24
- package/dist/graph/presets/cloth_rough.js +8 -8
- package/dist/graph/presets/cloth_smooth.js +8 -8
- package/dist/graph/presets/default.js +4 -4
- package/dist/graph/presets/eye.js +10 -10
- package/dist/graph/presets/face.d.ts.map +1 -1
- package/dist/graph/presets/face.js +28 -26
- package/dist/graph/presets/hair.js +6 -6
- package/dist/graph/presets/metal.js +8 -8
- package/dist/graph/presets/stockings.d.ts.map +1 -1
- package/dist/graph/presets/stockings.js +4 -11
- package/dist/graph/presets/unlit.d.ts.map +1 -1
- package/dist/graph/presets/unlit.js +9 -13
- package/dist/graph/registry.d.ts.map +1 -1
- package/dist/graph/registry.js +128 -157
- package/dist/graph/render-class.d.ts +5 -2
- package/dist/graph/render-class.d.ts.map +1 -1
- package/dist/graph/slots.d.ts.map +1 -1
- package/dist/graph/slots.js +5 -1
- package/dist/model.d.ts +14 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +27 -1
- package/dist/pmx-loader.d.ts +4 -0
- package/dist/pmx-loader.d.ts.map +1 -1
- package/dist/pmx-loader.js +11 -2
- package/dist/shaders/anchor-table.d.ts +11 -0
- package/dist/shaders/anchor-table.d.ts.map +1 -1
- package/dist/shaders/anchor-table.js +9 -3
- package/dist/shaders/directives.d.ts +42 -5
- package/dist/shaders/directives.d.ts.map +1 -1
- package/dist/shaders/directives.js +51 -4
- package/dist/shaders/lights.d.ts +11 -7
- package/dist/shaders/lights.d.ts.map +1 -1
- package/dist/shaders/lights.js +315 -271
- package/dist/shaders/materials/common.d.ts.map +1 -1
- package/dist/shaders/materials/common.js +26 -3
- package/dist/shaders/materials/nodes.d.ts +1 -1
- package/dist/shaders/materials/nodes.d.ts.map +1 -1
- package/dist/shaders/materials/nodes.js +191 -271
- package/dist/shaders/passes/composite.d.ts +1 -1
- package/dist/shaders/passes/composite.d.ts.map +1 -1
- package/dist/shaders/passes/composite.js +3 -5
- package/dist/shaders/passes/ground.js +1 -1
- package/dist/shaders/passes/particles.d.ts.map +1 -1
- package/dist/shaders/passes/particles.js +9 -3
- package/dist/shaders/passes/probe.d.ts +45 -0
- package/dist/shaders/passes/probe.d.ts.map +1 -0
- package/dist/shaders/passes/probe.js +230 -0
- package/dist/shaders/passes/scene-contract.d.ts +13 -0
- package/dist/shaders/passes/scene-contract.d.ts.map +1 -1
- package/dist/shaders/passes/scene-contract.js +4 -0
- package/dist/shaders/scene-light-api.d.ts.map +1 -1
- package/dist/shaders/scene-light-api.js +1 -0
- package/dist/unity/globals.d.ts +7 -0
- package/dist/unity/globals.d.ts.map +1 -1
- package/dist/unity/globals.js +4 -3
- package/dist/unity/host.d.ts +3 -0
- package/dist/unity/host.d.ts.map +1 -1
- package/dist/unity/host.js +41 -7
- package/dist/unity/looks.d.ts +42 -0
- package/dist/unity/looks.d.ts.map +1 -1
- package/dist/unity/looks.js +131 -4
- package/dist/unity/stage.d.ts +17 -0
- package/dist/unity/stage.d.ts.map +1 -1
- package/dist/unity/stage.js +22 -5
- package/package.json +1 -1
- package/src/engine.ts +949 -215
- package/src/graph/compile.ts +4 -0
- package/src/graph/presets/body.ts +26 -24
- package/src/graph/presets/cloth_rough.ts +8 -8
- package/src/graph/presets/cloth_smooth.ts +8 -8
- package/src/graph/presets/default.ts +4 -4
- package/src/graph/presets/eye.ts +10 -10
- package/src/graph/presets/face.ts +28 -26
- package/src/graph/presets/hair.ts +6 -6
- package/src/graph/presets/metal.ts +8 -8
- package/src/graph/presets/stockings.ts +4 -11
- package/src/graph/presets/unlit.ts +9 -13
- package/src/graph/registry.ts +133 -158
- package/src/graph/render-class.ts +5 -2
- package/src/graph/slots.ts +5 -1
- package/src/model.ts +33 -1
- package/src/pmx-loader.ts +11 -2
- package/src/shaders/anchor-table.ts +15 -3
- package/src/shaders/directives.ts +88 -6
- package/src/shaders/lights.ts +464 -415
- package/src/shaders/materials/common.ts +26 -3
- package/src/shaders/materials/nodes.ts +191 -271
- package/src/shaders/passes/composite.ts +3 -5
- package/src/shaders/passes/ground.ts +1 -1
- package/src/shaders/passes/particles.ts +9 -3
- package/src/shaders/passes/probe.ts +240 -0
- package/src/shaders/passes/scene-contract.ts +17 -0
- package/src/shaders/scene-light-api.ts +1 -0
- package/src/unity/globals.ts +7 -3
- package/src/unity/host.ts +36 -6
- package/src/unity/looks.ts +161 -7
- package/src/unity/stage.ts +28 -5
- package/dist/physics-debug.d.ts +0 -30
- package/dist/physics-debug.d.ts.map +0 -1
- package/dist/physics-debug.js +0 -526
- package/dist/shaders/agx-lut.d.ts +0 -11
- package/dist/shaders/agx-lut.d.ts.map +0 -1
- package/dist/shaders/agx-lut.js +0 -29
- package/dist/shaders/dfg_lut.d.ts +0 -3
- package/dist/shaders/dfg_lut.d.ts.map +0 -1
- package/dist/shaders/dfg_lut.js +0 -129
- package/dist/shaders/ltc_mag_lut.d.ts +0 -3
- package/dist/shaders/ltc_mag_lut.d.ts.map +0 -1
- package/dist/shaders/ltc_mag_lut.js +0 -1033
- package/dist/shaders/materials/body.d.ts +0 -2
- package/dist/shaders/materials/body.d.ts.map +0 -1
- package/dist/shaders/materials/body.js +0 -95
- package/dist/shaders/materials/cloth_rough.d.ts +0 -2
- package/dist/shaders/materials/cloth_rough.d.ts.map +0 -1
- package/dist/shaders/materials/cloth_rough.js +0 -69
- package/dist/shaders/materials/cloth_smooth.d.ts +0 -2
- package/dist/shaders/materials/cloth_smooth.d.ts.map +0 -1
- package/dist/shaders/materials/cloth_smooth.js +0 -61
- package/dist/shaders/materials/default.d.ts +0 -2
- package/dist/shaders/materials/default.d.ts.map +0 -1
- package/dist/shaders/materials/default.js +0 -43
- package/dist/shaders/materials/eye.d.ts +0 -2
- package/dist/shaders/materials/eye.d.ts.map +0 -1
- package/dist/shaders/materials/eye.js +0 -60
- package/dist/shaders/materials/face.d.ts +0 -2
- package/dist/shaders/materials/face.d.ts.map +0 -1
- package/dist/shaders/materials/face.js +0 -95
- package/dist/shaders/materials/hair.d.ts +0 -2
- package/dist/shaders/materials/hair.d.ts.map +0 -1
- package/dist/shaders/materials/hair.js +0 -90
- package/dist/shaders/materials/metal.d.ts +0 -2
- package/dist/shaders/materials/metal.d.ts.map +0 -1
- package/dist/shaders/materials/metal.js +0 -77
- package/dist/shaders/materials/mmd_classic.d.ts +0 -2
- package/dist/shaders/materials/mmd_classic.d.ts.map +0 -1
- package/dist/shaders/materials/mmd_classic.js +0 -66
- package/dist/shaders/materials/stockings.d.ts +0 -2
- package/dist/shaders/materials/stockings.d.ts.map +0 -1
- package/dist/shaders/materials/stockings.js +0 -122
- package/dist/shaders/passes/physics-debug.d.ts +0 -2
- package/dist/shaders/passes/physics-debug.d.ts.map +0 -1
- package/dist/shaders/passes/physics-debug.js +0 -69
- package/src/shaders/dfg_lut.ts +0 -131
- package/src/shaders/ltc_mag_lut.ts +0 -1035
package/dist/model.js
CHANGED
|
@@ -124,7 +124,7 @@ export class Model {
|
|
|
124
124
|
this.assetReader = reader;
|
|
125
125
|
this.assetBasePath = basePath;
|
|
126
126
|
}
|
|
127
|
-
constructor(vertexData, indexData, textures, materials, skeleton, skinning, morphing, rigidbodies = [], joints = [], loadWarnings = [], edgeScales = null) {
|
|
127
|
+
constructor(vertexData, indexData, textures, materials, skeleton, skinning, morphing, rigidbodies = [], joints = [], loadWarnings = [], edgeScales = null, additionalUvs = []) {
|
|
128
128
|
this._name = "";
|
|
129
129
|
this.morphPrevMinVert = -1; // vertices touched by last applyMorphs (reset to base this pass)
|
|
130
130
|
this.morphPrevMaxVert = -1;
|
|
@@ -271,6 +271,7 @@ export class Model {
|
|
|
271
271
|
// Cached set to track which bones are being computed in current IK pass (to avoid infinite recursion)
|
|
272
272
|
this.ikComputedSet = new Set();
|
|
273
273
|
this.edgeScales = edgeScales;
|
|
274
|
+
this.additionalUvs = additionalUvs;
|
|
274
275
|
// Store base vertex data (original positions before morphing)
|
|
275
276
|
this.baseVertexData = new Float32Array(vertexData);
|
|
276
277
|
this.vertexData = vertexData;
|
|
@@ -676,6 +677,12 @@ export class Model {
|
|
|
676
677
|
getVertices() {
|
|
677
678
|
return this.vertexData;
|
|
678
679
|
}
|
|
680
|
+
/** A PMX additional UV channel (1–4) as loaded, four floats a vertex — or
|
|
681
|
+
* null when the file has fewer. Its morphs (types 4–7) are in getMorphing(),
|
|
682
|
+
* with uvOffsets; the engine applies neither, a native look reads both. */
|
|
683
|
+
getAdditionalUv(channel) {
|
|
684
|
+
return this.additionalUvs[channel - 1] ?? null;
|
|
685
|
+
}
|
|
679
686
|
/**
|
|
680
687
|
* The outline hull's own vertex stream: per vertex, the smoothed rest-pose
|
|
681
688
|
* normal (xyz) and the PMX edge scale (w). See outline-normals.ts. Built on
|
|
@@ -785,6 +792,25 @@ export class Model {
|
|
|
785
792
|
return null;
|
|
786
793
|
return this.runtimeSkeleton.worldMatrices[idx].getPosition();
|
|
787
794
|
}
|
|
795
|
+
/**
|
|
796
|
+
* The point `distance` model units down a bone's own axis, posed — where
|
|
797
|
+
* `#anchor <bone> along <d>` puts an effect. The axis is the bone's rest tail
|
|
798
|
+
* direction (the way a PMX editor draws it pointing) turned by the bone's
|
|
799
|
+
* pose, the same mapping the named-points tips use. Model space, like
|
|
800
|
+
* getBoneWorldPosition. A bone with no tail has no axis: the joint itself.
|
|
801
|
+
*/
|
|
802
|
+
getBonePointAlong(boneName, distance) {
|
|
803
|
+
const idx = this.runtimeSkeleton.nameIndex[boneName];
|
|
804
|
+
if (idx === undefined || idx < 0)
|
|
805
|
+
return null;
|
|
806
|
+
const w = this.runtimeSkeleton.worldMatrices[idx].values;
|
|
807
|
+
const t = this.skeleton.bones[idx]?.tail;
|
|
808
|
+
const len = t ? Math.hypot(t[0], t[1], t[2]) : 0;
|
|
809
|
+
if (!t || len < 1e-6)
|
|
810
|
+
return new Vec3(w[12], w[13], w[14]);
|
|
811
|
+
const k = distance / len;
|
|
812
|
+
return new Vec3(w[12] + (w[0] * t[0] + w[4] * t[1] + w[8] * t[2]) * k, w[13] + (w[1] * t[0] + w[5] * t[1] + w[9] * t[2]) * k, w[14] + (w[2] * t[0] + w[6] * t[1] + w[10] * t[2]) * k);
|
|
813
|
+
}
|
|
788
814
|
/**
|
|
789
815
|
* A bone's forward axis, normalised — which way a foot points, where a head
|
|
790
816
|
* looks. Model space, like getBoneWorldPosition: the caller composes the model
|
package/dist/pmx-loader.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export declare class PmxLoader {
|
|
|
18
18
|
private inverseBindMatrices;
|
|
19
19
|
private joints0;
|
|
20
20
|
private weights0;
|
|
21
|
+
/** The PMX's additional UV channels (1–4), each four floats a vertex. The
|
|
22
|
+
* engine's own shading reads none of them; a native look can name one as
|
|
23
|
+
* the carrier of a game vertex stream (NativeLook.streams). */
|
|
24
|
+
private additionalUvs;
|
|
21
25
|
/** PMX per-vertex edge scale — the outline's width multiplier, as the
|
|
22
26
|
* game's outline takes vertex colour alpha. */
|
|
23
27
|
private edgeScales;
|
package/dist/pmx-loader.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pmx-loader.d.ts","sourceRoot":"","sources":["../src/pmx-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAcN,MAAM,SAAS,CAAA;AAGhB,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEzE,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,mBAAmB,CAAI;IAC/B,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,kBAAkB,CAAI;IAC9B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,QAAQ,CAA0B;IAC1C;oDACgD;IAChD,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAe;IAE/B,OAAO;IAQP,OAAO,CAAC,IAAI;WAMC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAI9C,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK;WAIpC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAKxF,OAAO,CAAC,KAAK;IAiBb,OAAO,CAAC,WAAW;IAwDnB,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"pmx-loader.d.ts","sourceRoot":"","sources":["../src/pmx-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAcN,MAAM,SAAS,CAAA;AAGhB,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEzE,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,mBAAmB,CAAI;IAC/B,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,kBAAkB,CAAI;IAC9B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,QAAQ,CAA0B;IAC1C;;oEAEgE;IAChE,OAAO,CAAC,aAAa,CAAqB;IAC1C;oDACgD;IAChD,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAe;IAE/B,OAAO;IAQP,OAAO,CAAC,IAAI;WAMC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAI9C,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK;WAIpC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAKxF,OAAO,CAAC,KAAK;IAiBb,OAAO,CAAC,WAAW;IAwDnB,OAAO,CAAC,aAAa;IAgHrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,cAAc;IAsEtB,OAAO,CAAC,UAAU;IAkLlB,OAAO,CAAC,WAAW;IAgMnB,OAAO,CAAC,iBAAiB;IAgDzB,OAAO,CAAC,gBAAgB;IA+FxB,OAAO,CAAC,WAAW;IAmGnB,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,OAAO;IAoJf,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,OAAO;IAwBf,OAAO,CAAC,QAAQ;CAIjB"}
|
package/dist/pmx-loader.js
CHANGED
|
@@ -19,6 +19,10 @@ export class PmxLoader {
|
|
|
19
19
|
this.inverseBindMatrices = null;
|
|
20
20
|
this.joints0 = null;
|
|
21
21
|
this.weights0 = null;
|
|
22
|
+
/** The PMX's additional UV channels (1–4), each four floats a vertex. The
|
|
23
|
+
* engine's own shading reads none of them; a native look can name one as
|
|
24
|
+
* the carrier of a game vertex stream (NativeLook.streams). */
|
|
25
|
+
this.additionalUvs = [];
|
|
22
26
|
/** PMX per-vertex edge scale — the outline's width multiplier, as the
|
|
23
27
|
* game's outline takes vertex colour alpha. */
|
|
24
28
|
this.edgeScales = null;
|
|
@@ -121,6 +125,7 @@ export class PmxLoader {
|
|
|
121
125
|
const joints = new Uint16Array(count * 4);
|
|
122
126
|
const weights = new Uint8Array(count * 4); // UNORM8, will be normalized to 255
|
|
123
127
|
const edgeScales = new Float32Array(count);
|
|
128
|
+
this.additionalUvs = Array.from({ length: this.additionalVec4Count }, () => new Float32Array(count * 4));
|
|
124
129
|
for (let i = 0; i < count; i++) {
|
|
125
130
|
const px = this.getFloat32();
|
|
126
131
|
const py = this.getFloat32();
|
|
@@ -134,7 +139,11 @@ export class PmxLoader {
|
|
|
134
139
|
const v = this.getFloat32();
|
|
135
140
|
// PMX UVs are in the same orientation as WebGPU sampling; no flip
|
|
136
141
|
uvs.push(u, v);
|
|
137
|
-
|
|
142
|
+
for (let k = 0; k < this.additionalVec4Count; k++) {
|
|
143
|
+
const a = this.additionalUvs[k];
|
|
144
|
+
for (let c = 0; c < 4; c++)
|
|
145
|
+
a[i * 4 + c] = this.getFloat32();
|
|
146
|
+
}
|
|
138
147
|
const type = this.getUint8();
|
|
139
148
|
const base = i * 4;
|
|
140
149
|
// Initialize defaults
|
|
@@ -1029,7 +1038,7 @@ export class PmxLoader {
|
|
|
1029
1038
|
const morphing = {
|
|
1030
1039
|
morphs: this.morphs,
|
|
1031
1040
|
};
|
|
1032
|
-
return new Model(vertexData, indexData, this.textures, this.materials, skeleton, skinning, morphing, this.rigidbodies, this.joints, this.warnings, this.edgeScales);
|
|
1041
|
+
return new Model(vertexData, indexData, this.textures, this.materials, skeleton, skinning, morphing, this.rigidbodies, this.joints, this.warnings, this.edgeScales, this.additionalUvs);
|
|
1033
1042
|
}
|
|
1034
1043
|
getUint8() {
|
|
1035
1044
|
if (this.offset >= this.view.buffer.byteLength) {
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
interface AnchorRequest {
|
|
2
2
|
bone: string;
|
|
3
3
|
trail: boolean;
|
|
4
|
+
/** Model units down the bone's own axis (`#anchor ... along d`); absent = 0,
|
|
5
|
+
* the joint itself. */
|
|
6
|
+
along?: number;
|
|
7
|
+
/** World units the bone must move before its trail keeps a point
|
|
8
|
+
* (`trail step d`); absent = every 60 Hz tick. */
|
|
9
|
+
step?: number;
|
|
4
10
|
}
|
|
5
11
|
/** The empty table — a scene with no effect installed asks for no bones. */
|
|
6
12
|
export declare const EMPTY_ANCHOR_TABLE: AnchorTable;
|
|
@@ -26,6 +32,11 @@ export interface AnchorTable {
|
|
|
26
32
|
* Order is first-come, so a single effect gets the identity alias and the whole
|
|
27
33
|
* mechanism is a no-op until a second effect exists — which is what makes this
|
|
28
34
|
* safe to land before setEffects does.
|
|
35
|
+
*
|
|
36
|
+
* A point ALONG a bone is a different point: `#anchor 右手首 trail along 0.9`
|
|
37
|
+
* and a bare `#anchor 右手首` are two entries, keyed by bone and distance, since
|
|
38
|
+
* sharing one ring would hand one of them the other's path. So is a trail
|
|
39
|
+
* recorded at a different `step`: its ring keeps different points.
|
|
29
40
|
*/
|
|
30
41
|
export declare function buildAnchorTable(requests: AnchorRequest[][], max: number): AnchorTable;
|
|
31
42
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor-table.d.ts","sourceRoot":"","sources":["../../src/shaders/anchor-table.ts"],"names":[],"mappings":"AAsBA,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"anchor-table.d.ts","sourceRoot":"","sources":["../../src/shaders/anchor-table.ts"],"names":[],"mappings":"AAsBA,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd;4BACwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;uDACmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,EAAE,WAAqD,CAAA;AAEtF,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,EAAE,EAAE,CAAA;IACjB,6EAA6E;IAC7E,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC5C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAkCtF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAkB3D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAmCvD"}
|
|
@@ -32,6 +32,11 @@ export const EMPTY_ANCHOR_TABLE = { entries: [], alias: [], dropped: [] };
|
|
|
32
32
|
* Order is first-come, so a single effect gets the identity alias and the whole
|
|
33
33
|
* mechanism is a no-op until a second effect exists — which is what makes this
|
|
34
34
|
* safe to land before setEffects does.
|
|
35
|
+
*
|
|
36
|
+
* A point ALONG a bone is a different point: `#anchor 右手首 trail along 0.9`
|
|
37
|
+
* and a bare `#anchor 右手首` are two entries, keyed by bone and distance, since
|
|
38
|
+
* sharing one ring would hand one of them the other's path. So is a trail
|
|
39
|
+
* recorded at a different `step`: its ring keeps different points.
|
|
35
40
|
*/
|
|
36
41
|
export function buildAnchorTable(requests, max) {
|
|
37
42
|
const entries = [];
|
|
@@ -41,7 +46,8 @@ export function buildAnchorTable(requests, max) {
|
|
|
41
46
|
for (let e = 0; e < requests.length; e++) {
|
|
42
47
|
const local = [];
|
|
43
48
|
for (const req of requests[e]) {
|
|
44
|
-
|
|
49
|
+
const key = req.along || req.step ? `${req.bone}\u0000${req.along ?? 0}\u0000${req.step ?? 0}` : req.bone;
|
|
50
|
+
let g = index.get(key);
|
|
45
51
|
if (g === undefined) {
|
|
46
52
|
if (entries.length >= max) {
|
|
47
53
|
// Refused, and the effect still installs: an effect that loses one of
|
|
@@ -52,8 +58,8 @@ export function buildAnchorTable(requests, max) {
|
|
|
52
58
|
continue;
|
|
53
59
|
}
|
|
54
60
|
g = entries.length;
|
|
55
|
-
index.set(
|
|
56
|
-
entries.push({ bone: req.bone, trail: req.trail });
|
|
61
|
+
index.set(key, g);
|
|
62
|
+
entries.push({ bone: req.bone, trail: req.trail, ...(req.along ? { along: req.along } : {}), ...(req.step ? { step: req.step } : {}) });
|
|
57
63
|
}
|
|
58
64
|
else if (req.trail) {
|
|
59
65
|
// A later request for the same bone can only ever ADD the trail — the
|
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bone an effect follows: `#anchor <bone> [trail] [along <d>]`.
|
|
3
|
+
*
|
|
4
|
+
* `along` is for an effect that comes off a point ON the bone rather than at its
|
|
5
|
+
* joint — threads leaving the knuckles, not the wrist; a flame at a sword's tip.
|
|
6
|
+
* The point is `d` model units down the bone's own axis: the direction a PMX
|
|
7
|
+
* editor draws the bone pointing (its tail, as an offset or as the bone it
|
|
8
|
+
* points at), turned by the bone's pose, scaled with the model. A left and a
|
|
9
|
+
* right wrist point opposite ways, so one number mirrors itself. A bone with no
|
|
10
|
+
* tail has no axis, and the point stays at the joint.
|
|
11
|
+
*
|
|
12
|
+
* Everything the anchor feeds reads the moved point: rzAnchor, the trail, the
|
|
13
|
+
* ribbon. Two effects naming the same bone at different `along` are two anchors.
|
|
14
|
+
*
|
|
15
|
+
* `trail step d` records the path the way a game's trail does (Unity's
|
|
16
|
+
* minVertexDistance): the newest point follows the bone every frame, and a
|
|
17
|
+
* point is only LEFT BEHIND once the bone is `d` world units from the last one.
|
|
18
|
+
* Sampled on the clock alone, a slowing hand leaves a knot of tiny segments
|
|
19
|
+
* whose directions jitter, and a wide ribbon fans across them into a starburst;
|
|
20
|
+
* a stepped path has no segment shorter than `d`. Ages stay true — each point
|
|
21
|
+
* keeps the time it was left. Different steps are different anchors.
|
|
22
|
+
*/
|
|
23
|
+
export type EffectAnchor = {
|
|
24
|
+
bone: string;
|
|
25
|
+
trail: boolean;
|
|
26
|
+
along?: number;
|
|
27
|
+
step?: number;
|
|
28
|
+
};
|
|
1
29
|
/** A knob an effect exposes, for a host to build a control from. */
|
|
2
30
|
export type EffectParamDecl = {
|
|
3
31
|
name: string;
|
|
@@ -9,11 +37,10 @@ export type EffectParamDecl = {
|
|
|
9
37
|
max?: number;
|
|
10
38
|
};
|
|
11
39
|
export type EffectDirectives = {
|
|
12
|
-
/** Bones this effect follows, in declaration order — slot 0 is the first.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}[];
|
|
40
|
+
/** Bones this effect follows, in declaration order — slot 0 is the first.
|
|
41
|
+
* `along` (model units, absent = 0) moves the point down the bone's own
|
|
42
|
+
* axis, its rest tail direction posed with it: see EffectAnchor. */
|
|
43
|
+
anchors: EffectAnchor[];
|
|
17
44
|
params: EffectParamDecl[];
|
|
18
45
|
/** Field layer: 0 full, 1 half. Full unless `#halfres` says otherwise. */
|
|
19
46
|
fieldLayer: 0 | 1;
|
|
@@ -26,6 +53,16 @@ export type EffectDirectives = {
|
|
|
26
53
|
* every real grass renderer does, and the only thing that bounds a dense
|
|
27
54
|
* lawn's cost by the pixels it covers rather than by how deep it stacks. */
|
|
28
55
|
particleBlend: "alpha" | "additive" | "cutout";
|
|
56
|
+
/** How RIBBONS land, a separate axis from the particles': additive unless
|
|
57
|
+
* the file says `#blend over`. Ribbons ignored #blend until that keyword,
|
|
58
|
+
* and every shipped ribbon was tuned additive — so the default stays, and
|
|
59
|
+
* `over` is the opt-in. The same line sets particles to plain alpha, which
|
|
60
|
+
* already IS premultiplied over for them. */
|
|
61
|
+
trailBlend: "additive" | "over";
|
|
62
|
+
/** `#depth always`: the particles are drawn over the scene, not depth
|
|
63
|
+
* tested — a game glow its material draws with ZTest Always (a moon's halo
|
|
64
|
+
* in front of the sky dome it sits behind). Depth tested otherwise. */
|
|
65
|
+
depthAlways: boolean;
|
|
29
66
|
particles: number;
|
|
30
67
|
lights: number;
|
|
31
68
|
grid: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../../src/shaders/directives.ts"],"names":[],"mappings":"AA8BA,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;IAChC,+EAA+E;IAC/E,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAA;IACjD,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B
|
|
1
|
+
{"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../../src/shaders/directives.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1F,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;IAChC,+EAA+E;IAC/E,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAA;IACjD,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;yEAEqE;IACrE,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,0EAA0E;IAC1E,UAAU,EAAE,CAAC,GAAG,CAAC,CAAA;IACjB,8DAA8D;IAC9D,aAAa,EAAE,OAAO,CAAA;IACtB,wEAAwE;IACxE;;;;iFAI6E;IAC7E,aAAa,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAA;IAC9C;;;;kDAI8C;IAC9C,UAAU,EAAE,UAAU,GAAG,MAAM,CAAA;IAC/B;;4EAEwE;IACxE,WAAW,EAAE,OAAO,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ;kFAC8E;IAC9E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,oEAAoE;IACpE,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;;;;4CAOwC;IACxC,MAAM,EAAE;QAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACjE;;;;;;;;;;;;;OAaG;IACH,MAAM,EAAE,OAAO,CAAA;IACf;;;;;;;OAOG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAuBD;;;+BAG+B;AAC/B,eAAO,MAAM,cAAc,QAAmC,CAAA;AAG9D;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,QAA8B,CAAA;AAmBzD,MAAM,MAAM,eAAe,GAAG;IAAE,UAAU,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAEhF,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CA0O7D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKpD"}
|
|
@@ -34,6 +34,7 @@ const SPEC = {
|
|
|
34
34
|
halfres: 0,
|
|
35
35
|
layer: 1,
|
|
36
36
|
blend: 1,
|
|
37
|
+
depth: 1,
|
|
37
38
|
particles: 1,
|
|
38
39
|
lights: 1,
|
|
39
40
|
grid: 1,
|
|
@@ -88,6 +89,8 @@ export function parseDirectives(wgsl) {
|
|
|
88
89
|
fieldLayer: 0,
|
|
89
90
|
additiveLayer: false,
|
|
90
91
|
particleBlend: "alpha",
|
|
92
|
+
trailBlend: "additive",
|
|
93
|
+
depthAlways: false,
|
|
91
94
|
particles: 0,
|
|
92
95
|
lights: 0,
|
|
93
96
|
grid: 0,
|
|
@@ -120,11 +123,41 @@ export function parseDirectives(wgsl) {
|
|
|
120
123
|
}
|
|
121
124
|
switch (tag) {
|
|
122
125
|
case "anchor": {
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
// <bone> [trail [step <d>]] [along <d>], in that order.
|
|
127
|
+
const usage = `${at}: #anchor takes a bone name, optionally "trail" (and "step" with a distance), then optionally "along" and a distance`;
|
|
128
|
+
if (args.length < 1) {
|
|
129
|
+
errors.push(usage);
|
|
125
130
|
return;
|
|
126
131
|
}
|
|
127
|
-
|
|
132
|
+
let k = 1;
|
|
133
|
+
const trail = args[k] === "trail";
|
|
134
|
+
if (trail)
|
|
135
|
+
k++;
|
|
136
|
+
let step;
|
|
137
|
+
if (trail && args[k] === "step") {
|
|
138
|
+
const v = num(args[k + 1]);
|
|
139
|
+
if (v === null || v <= 0) {
|
|
140
|
+
errors.push(`${at}: #anchor ... trail step needs a positive distance in world units, like "step 0.24"`);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
step = v;
|
|
144
|
+
k += 2;
|
|
145
|
+
}
|
|
146
|
+
let along;
|
|
147
|
+
if (args[k] === "along") {
|
|
148
|
+
const v = num(args[k + 1]);
|
|
149
|
+
if (v === null) {
|
|
150
|
+
errors.push(`${at}: #anchor ... along needs a distance in model units, like "along 0.9"`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
along = v;
|
|
154
|
+
k += 2;
|
|
155
|
+
}
|
|
156
|
+
if (k !== args.length) {
|
|
157
|
+
errors.push(usage);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
d.anchors.push({ bone: args[0], trail, ...(step ? { step } : {}), ...(along ? { along } : {}) });
|
|
128
161
|
return;
|
|
129
162
|
}
|
|
130
163
|
case "param": {
|
|
@@ -181,8 +214,15 @@ export function parseDirectives(wgsl) {
|
|
|
181
214
|
d.additiveLayer = true;
|
|
182
215
|
return;
|
|
183
216
|
case "blend":
|
|
217
|
+
// `over` is for ribbons: laid over the scene by their alpha instead of
|
|
218
|
+
// added. For particles it is the default alpha, which is already over.
|
|
219
|
+
if (args[0] === "over") {
|
|
220
|
+
d.trailBlend = "over";
|
|
221
|
+
d.particleBlend = "alpha";
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
184
224
|
if (args[0] !== "additive" && args[0] !== "cutout") {
|
|
185
|
-
errors.push(`${at}: #blend takes "additive" or "
|
|
225
|
+
errors.push(`${at}: #blend takes "additive", "cutout" or "over" — alpha is the default`);
|
|
186
226
|
return;
|
|
187
227
|
}
|
|
188
228
|
d.particleBlend = args[0];
|
|
@@ -190,6 +230,13 @@ export function parseDirectives(wgsl) {
|
|
|
190
230
|
case "bloom":
|
|
191
231
|
d.bloom = true;
|
|
192
232
|
return;
|
|
233
|
+
case "depth":
|
|
234
|
+
if (args[0] !== "always") {
|
|
235
|
+
errors.push(`${at}: #depth takes "always" — depth tested is the default`);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
d.depthAlways = true;
|
|
239
|
+
return;
|
|
193
240
|
case "ground": {
|
|
194
241
|
const m = /^#([0-9a-fA-F]{6})$/.exec(args[0] ?? "");
|
|
195
242
|
const noise = args[1] === undefined ? 0 : num(args[1]);
|
package/dist/shaders/lights.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Words before the first record: the counts, the grid's placement and the
|
|
2
|
-
* outside mask,
|
|
3
|
-
export declare const LIGHT_HEADER =
|
|
2
|
+
* outside mask, five vec4s — see the layout above. */
|
|
3
|
+
export declare const LIGHT_HEADER = 20;
|
|
4
4
|
/** Floats per light — see the layout above. */
|
|
5
5
|
export declare const LIGHT_STRIDE = 16;
|
|
6
6
|
/**
|
|
@@ -15,10 +15,11 @@ export declare const LIGHT_STRIDE = 16;
|
|
|
15
15
|
* forty-eight each cut a real scene in half. Past this the extras are dropped.
|
|
16
16
|
*
|
|
17
17
|
* A fragment pays for the document lamps its grid cell names, so the cost
|
|
18
|
-
* follows how many reach a place rather than how many the scene holds.
|
|
19
|
-
*
|
|
18
|
+
* follows how many reach a place rather than how many the scene holds. 256,
|
|
19
|
+
* two vec4u of bits per cell, is URP's own Forward+ budget for visible lights
|
|
20
|
+
* — and holds a lit interior's whole rig (X317's 153).
|
|
20
21
|
*/
|
|
21
|
-
export declare const MAX_LIGHTS =
|
|
22
|
+
export declare const MAX_LIGHTS = 256;
|
|
22
23
|
/** Words of lamp bits per grid cell — one bit per lamp the cap allows. */
|
|
23
24
|
export declare const LIGHT_MASK_WORDS: number;
|
|
24
25
|
/** The grid's cell budget. 32k cells over a stage a couple of hundred units
|
|
@@ -37,7 +38,7 @@ export declare const LIGHTS_FLOATS: number;
|
|
|
37
38
|
* out of those modules is a compile error on a function the author was right to
|
|
38
39
|
* write, which is the same trap the grid's step-only half documents.
|
|
39
40
|
*/
|
|
40
|
-
export declare const RZ_LIGHT_STRUCT_WGSL = "\n/** What an effect returns for one of its lights. */\nstruct RzLight {\n pos: vec3f,\n color: vec3f,\n intensity: f32,\n radius: f32,\n}\n";
|
|
41
|
+
export declare const RZ_LIGHT_STRUCT_WGSL = "\n/** What an effect returns for one of its lights. */\nstruct RzLight {\n pos: vec3f,\n color: vec3f,\n intensity: f32,\n radius: f32,\n /** Its bulb: the distance inside which it stops getting brighter. 0 is the\n * engine's default; a glow worn on a hand wants one the size of the glow. */\n near: f32,\n}\n";
|
|
41
42
|
/** rzWorldAmbient against the materials' and the ground's `light` uniform. */
|
|
42
43
|
export declare const WORLD_AMBIENT_WGSL: string;
|
|
43
44
|
/** Does this source define the emit mount? */
|
|
@@ -74,5 +75,8 @@ export declare function buildLightEmitShader(wgsl: string, sceneApi: string, cas
|
|
|
74
75
|
}, paramsDecl?: string): string;
|
|
75
76
|
/** The rz*Light accessors, with the buffer declared at the given binding.
|
|
76
77
|
* `layers` is the WGSL expression for the drawing's rendering-layer bits. */
|
|
77
|
-
export declare function lightsApi(group: number, binding: number, layers: string
|
|
78
|
+
export declare function lightsApi(group: number, binding: number, layers: string, cookies: {
|
|
79
|
+
binding: number;
|
|
80
|
+
sampler: string;
|
|
81
|
+
}): string;
|
|
78
82
|
//# sourceMappingURL=lights.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lights.d.ts","sourceRoot":"","sources":["../../src/shaders/lights.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lights.d.ts","sourceRoot":"","sources":["../../src/shaders/lights.ts"],"names":[],"mappings":"AA8DA;uDACuD;AACvD,eAAO,MAAM,YAAY,KAAK,CAAA;AAC9B,+CAA+C;AAC/C,eAAO,MAAM,YAAY,KAAK,CAAA;AAC9B;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,UAAU,MAAM,CAAA;AAC7B,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,QAAkB,CAAA;AAC/C;0EAC0E;AAC1E,eAAO,MAAM,gBAAgB,QAAQ,CAAA;AACrC,uCAAuC;AACvC,eAAO,MAAM,eAAe,QAA2C,CAAA;AACvE,wDAAwD;AACxD,eAAO,MAAM,aAAa,QAAwD,CAAA;AAElF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,oUAWhC,CAAA;AAED,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,QAA4B,CAAA;AAE3D,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,EAC5B,UAAU,SAAK,GACd,MAAM,CAoGR;AAED;8EAC8E;AAC9E,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC5C,MAAM,CAsMR"}
|