reze-engine 0.2.17 → 0.2.19
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/README.md +1 -2
- package/dist/engine.d.ts +16 -5
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +604 -722
- package/dist/model.d.ts +36 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +156 -1
- package/dist/pmx-loader.d.ts +3 -1
- package/dist/pmx-loader.d.ts.map +1 -1
- package/dist/pmx-loader.js +161 -94
- package/package.json +1 -1
- package/src/engine.ts +2267 -2392
- package/src/model.ts +649 -421
- package/src/pmx-loader.ts +180 -89
package/dist/model.d.ts
CHANGED
|
@@ -41,6 +41,24 @@ export interface Skinning {
|
|
|
41
41
|
joints: Uint16Array;
|
|
42
42
|
weights: Uint8Array;
|
|
43
43
|
}
|
|
44
|
+
export interface VertexMorphOffset {
|
|
45
|
+
vertexIndex: number;
|
|
46
|
+
positionOffset: [number, number, number];
|
|
47
|
+
}
|
|
48
|
+
export interface GroupMorphReference {
|
|
49
|
+
morphIndex: number;
|
|
50
|
+
ratio: number;
|
|
51
|
+
}
|
|
52
|
+
export interface Morph {
|
|
53
|
+
name: string;
|
|
54
|
+
type: number;
|
|
55
|
+
vertexOffsets: VertexMorphOffset[];
|
|
56
|
+
groupReferences?: GroupMorphReference[];
|
|
57
|
+
}
|
|
58
|
+
export interface Morphing {
|
|
59
|
+
morphs: Morph[];
|
|
60
|
+
offsetsBuffer: Float32Array;
|
|
61
|
+
}
|
|
44
62
|
export interface SkeletonRuntime {
|
|
45
63
|
nameIndex: Record<string, number>;
|
|
46
64
|
localRotations: Float32Array;
|
|
@@ -48,24 +66,35 @@ export interface SkeletonRuntime {
|
|
|
48
66
|
worldMatrices: Float32Array;
|
|
49
67
|
computedBones: boolean[];
|
|
50
68
|
}
|
|
69
|
+
export interface MorphRuntime {
|
|
70
|
+
nameIndex: Record<string, number>;
|
|
71
|
+
weights: Float32Array;
|
|
72
|
+
}
|
|
51
73
|
export declare class Model {
|
|
52
74
|
private vertexData;
|
|
75
|
+
private baseVertexData;
|
|
53
76
|
private vertexCount;
|
|
54
77
|
private indexData;
|
|
55
78
|
private textures;
|
|
56
79
|
private materials;
|
|
57
80
|
private skeleton;
|
|
58
81
|
private skinning;
|
|
82
|
+
private morphing;
|
|
59
83
|
private rigidbodies;
|
|
60
84
|
private joints;
|
|
61
85
|
private runtimeSkeleton;
|
|
86
|
+
private runtimeMorph;
|
|
62
87
|
private cachedIdentityMat1;
|
|
63
88
|
private cachedIdentityMat2;
|
|
64
89
|
private rotTweenState;
|
|
65
|
-
|
|
90
|
+
private morphTweenState;
|
|
91
|
+
constructor(vertexData: Float32Array<ArrayBuffer>, indexData: Uint32Array<ArrayBuffer>, textures: Texture[], materials: Material[], skeleton: Skeleton, skinning: Skinning, morphing: Morphing, rigidbodies?: Rigidbody[], joints?: Joint[]);
|
|
66
92
|
private initializeRuntimeSkeleton;
|
|
67
93
|
private initializeRotTweenBuffers;
|
|
94
|
+
private initializeMorphTweenBuffers;
|
|
95
|
+
private initializeRuntimeMorph;
|
|
68
96
|
private updateRotationTweens;
|
|
97
|
+
private updateMorphWeightTweens;
|
|
69
98
|
getVertices(): Float32Array<ArrayBuffer>;
|
|
70
99
|
getTextures(): Texture[];
|
|
71
100
|
getMaterials(): Material[];
|
|
@@ -75,11 +104,16 @@ export declare class Model {
|
|
|
75
104
|
getSkinning(): Skinning;
|
|
76
105
|
getRigidbodies(): Rigidbody[];
|
|
77
106
|
getJoints(): Joint[];
|
|
107
|
+
getMorphing(): Morphing;
|
|
108
|
+
getMorphWeights(): Float32Array;
|
|
78
109
|
getBoneNames(): string[];
|
|
79
110
|
rotateBones(names: string[], quats: Quat[], durationMs?: number): void;
|
|
80
111
|
getBoneWorldMatrices(): Float32Array;
|
|
81
112
|
getBoneInverseBindMatrices(): Float32Array;
|
|
82
|
-
|
|
113
|
+
getMorphNames(): string[];
|
|
114
|
+
setMorphWeight(name: string, weight: number, durationMs?: number): void;
|
|
115
|
+
private applyMorphs;
|
|
116
|
+
evaluatePose(): boolean;
|
|
83
117
|
private computeWorldMatrices;
|
|
84
118
|
}
|
|
85
119
|
//# sourceMappingURL=model.d.ts.map
|
package/dist/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,IAAI,EAAa,MAAM,QAAQ,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAI5C,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACzC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,mBAAmB,EAAE,YAAY,CAAA;CAClC;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,UAAU,CAAA;CACpB;AAGD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,cAAc,EAAE,YAAY,CAAA;IAC5B,iBAAiB,EAAE,YAAY,CAAA;IAC/B,aAAa,EAAE,YAAY,CAAA;IAC3B,aAAa,EAAE,OAAO,EAAE,CAAA;CACzB;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
|
package/dist/model.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Mat4, Quat, easeInOut } from "./math";
|
|
2
2
|
const VERTEX_STRIDE = 8;
|
|
3
3
|
export class Model {
|
|
4
|
-
constructor(vertexData, indexData, textures, materials, skeleton, skinning, rigidbodies = [], joints = []) {
|
|
4
|
+
constructor(vertexData, indexData, textures, materials, skeleton, skinning, morphing, rigidbodies = [], joints = []) {
|
|
5
5
|
this.textures = [];
|
|
6
6
|
this.materials = [];
|
|
7
7
|
// Physics data from PMX
|
|
@@ -10,6 +10,8 @@ export class Model {
|
|
|
10
10
|
// Cached identity matrices to avoid allocations in computeWorldMatrices
|
|
11
11
|
this.cachedIdentityMat1 = Mat4.identity();
|
|
12
12
|
this.cachedIdentityMat2 = Mat4.identity();
|
|
13
|
+
// Store base vertex data (original positions before morphing)
|
|
14
|
+
this.baseVertexData = new Float32Array(vertexData);
|
|
13
15
|
this.vertexData = vertexData;
|
|
14
16
|
this.vertexCount = vertexData.length / VERTEX_STRIDE;
|
|
15
17
|
this.indexData = indexData;
|
|
@@ -17,6 +19,7 @@ export class Model {
|
|
|
17
19
|
this.materials = materials;
|
|
18
20
|
this.skeleton = skeleton;
|
|
19
21
|
this.skinning = skinning;
|
|
22
|
+
this.morphing = morphing;
|
|
20
23
|
this.rigidbodies = rigidbodies;
|
|
21
24
|
this.joints = joints;
|
|
22
25
|
if (this.skeleton.bones.length == 0) {
|
|
@@ -24,6 +27,9 @@ export class Model {
|
|
|
24
27
|
}
|
|
25
28
|
this.initializeRuntimeSkeleton();
|
|
26
29
|
this.initializeRotTweenBuffers();
|
|
30
|
+
this.initializeRuntimeMorph();
|
|
31
|
+
this.initializeMorphTweenBuffers();
|
|
32
|
+
this.applyMorphs(); // Apply initial morphs (all weights are 0, so no change)
|
|
27
33
|
}
|
|
28
34
|
initializeRuntimeSkeleton() {
|
|
29
35
|
const boneCount = this.skeleton.bones.length;
|
|
@@ -58,6 +64,26 @@ export class Model {
|
|
|
58
64
|
durationMs: new Float32Array(n),
|
|
59
65
|
};
|
|
60
66
|
}
|
|
67
|
+
initializeMorphTweenBuffers() {
|
|
68
|
+
const n = this.morphing.morphs.length;
|
|
69
|
+
this.morphTweenState = {
|
|
70
|
+
active: new Uint8Array(n),
|
|
71
|
+
startWeight: new Float32Array(n),
|
|
72
|
+
targetWeight: new Float32Array(n),
|
|
73
|
+
startTimeMs: new Float32Array(n),
|
|
74
|
+
durationMs: new Float32Array(n),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
initializeRuntimeMorph() {
|
|
78
|
+
const morphCount = this.morphing.morphs.length;
|
|
79
|
+
this.runtimeMorph = {
|
|
80
|
+
nameIndex: this.morphing.morphs.reduce((acc, morph, index) => {
|
|
81
|
+
acc[morph.name] = index;
|
|
82
|
+
return acc;
|
|
83
|
+
}, {}),
|
|
84
|
+
weights: new Float32Array(morphCount),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
61
87
|
updateRotationTweens() {
|
|
62
88
|
const state = this.rotTweenState;
|
|
63
89
|
const now = performance.now();
|
|
@@ -82,6 +108,28 @@ export class Model {
|
|
|
82
108
|
state.active[i] = 0;
|
|
83
109
|
}
|
|
84
110
|
}
|
|
111
|
+
updateMorphWeightTweens() {
|
|
112
|
+
const state = this.morphTweenState;
|
|
113
|
+
const now = performance.now();
|
|
114
|
+
const weights = this.runtimeMorph.weights;
|
|
115
|
+
const morphCount = this.morphing.morphs.length;
|
|
116
|
+
let hasActiveTweens = false;
|
|
117
|
+
for (let i = 0; i < morphCount; i++) {
|
|
118
|
+
if (state.active[i] !== 1)
|
|
119
|
+
continue;
|
|
120
|
+
hasActiveTweens = true;
|
|
121
|
+
const startMs = state.startTimeMs[i];
|
|
122
|
+
const durMs = Math.max(1, state.durationMs[i]);
|
|
123
|
+
const t = Math.max(0, Math.min(1, (now - startMs) / durMs));
|
|
124
|
+
const e = easeInOut(t);
|
|
125
|
+
weights[i] = state.startWeight[i] + (state.targetWeight[i] - state.startWeight[i]) * e;
|
|
126
|
+
if (t >= 1) {
|
|
127
|
+
weights[i] = state.targetWeight[i];
|
|
128
|
+
state.active[i] = 0;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return hasActiveTweens;
|
|
132
|
+
}
|
|
85
133
|
// Get interleaved vertex data for GPU upload
|
|
86
134
|
// Format: [x,y,z, nx,ny,nz, u,v, x,y,z, nx,ny,nz, u,v, ...]
|
|
87
135
|
getVertices() {
|
|
@@ -117,6 +165,13 @@ export class Model {
|
|
|
117
165
|
getJoints() {
|
|
118
166
|
return this.joints;
|
|
119
167
|
}
|
|
168
|
+
// Accessors for morphing
|
|
169
|
+
getMorphing() {
|
|
170
|
+
return this.morphing;
|
|
171
|
+
}
|
|
172
|
+
getMorphWeights() {
|
|
173
|
+
return this.runtimeMorph.weights;
|
|
174
|
+
}
|
|
120
175
|
// ------- Bone helpers (public API) -------
|
|
121
176
|
getBoneNames() {
|
|
122
177
|
return this.skeleton.bones.map((b) => b.name);
|
|
@@ -182,9 +237,109 @@ export class Model {
|
|
|
182
237
|
getBoneInverseBindMatrices() {
|
|
183
238
|
return this.skeleton.inverseBindMatrices;
|
|
184
239
|
}
|
|
240
|
+
getMorphNames() {
|
|
241
|
+
return this.morphing.morphs.map((m) => m.name);
|
|
242
|
+
}
|
|
243
|
+
setMorphWeight(name, weight, durationMs) {
|
|
244
|
+
const idx = this.runtimeMorph.nameIndex[name] ?? -1;
|
|
245
|
+
if (idx < 0 || idx >= this.runtimeMorph.weights.length)
|
|
246
|
+
return;
|
|
247
|
+
const clampedWeight = Math.max(0, Math.min(1, weight));
|
|
248
|
+
const dur = durationMs && durationMs > 0 ? durationMs : 0;
|
|
249
|
+
if (dur === 0) {
|
|
250
|
+
// Instant change
|
|
251
|
+
this.runtimeMorph.weights[idx] = clampedWeight;
|
|
252
|
+
this.morphTweenState.active[idx] = 0;
|
|
253
|
+
this.applyMorphs();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
// Animated change
|
|
257
|
+
const state = this.morphTweenState;
|
|
258
|
+
const now = performance.now();
|
|
259
|
+
const currentWeight = this.runtimeMorph.weights[idx];
|
|
260
|
+
// If already tweening, start from current interpolated value
|
|
261
|
+
let startWeight = currentWeight;
|
|
262
|
+
if (state.active[idx] === 1) {
|
|
263
|
+
const startMs = state.startTimeMs[idx];
|
|
264
|
+
const prevDur = Math.max(1, state.durationMs[idx]);
|
|
265
|
+
const t = Math.max(0, Math.min(1, (now - startMs) / prevDur));
|
|
266
|
+
const e = easeInOut(t);
|
|
267
|
+
startWeight = state.startWeight[idx] + (state.targetWeight[idx] - state.startWeight[idx]) * e;
|
|
268
|
+
}
|
|
269
|
+
state.startWeight[idx] = startWeight;
|
|
270
|
+
state.targetWeight[idx] = clampedWeight;
|
|
271
|
+
state.startTimeMs[idx] = now;
|
|
272
|
+
state.durationMs[idx] = dur;
|
|
273
|
+
state.active[idx] = 1;
|
|
274
|
+
// Immediately apply morphs with current weight
|
|
275
|
+
this.runtimeMorph.weights[idx] = startWeight;
|
|
276
|
+
this.applyMorphs();
|
|
277
|
+
}
|
|
278
|
+
applyMorphs() {
|
|
279
|
+
// Reset vertex data to base positions
|
|
280
|
+
this.vertexData.set(this.baseVertexData);
|
|
281
|
+
const vertexCount = this.vertexCount;
|
|
282
|
+
const morphCount = this.morphing.morphs.length;
|
|
283
|
+
const weights = this.runtimeMorph.weights;
|
|
284
|
+
// First pass: Compute effective weights for all morphs (handling group morphs)
|
|
285
|
+
const effectiveWeights = new Float32Array(morphCount);
|
|
286
|
+
effectiveWeights.set(weights); // Start with direct weights
|
|
287
|
+
// Apply group morphs: group morph weight * ratio affects referenced morphs
|
|
288
|
+
for (let morphIdx = 0; morphIdx < morphCount; morphIdx++) {
|
|
289
|
+
const morph = this.morphing.morphs[morphIdx];
|
|
290
|
+
if (morph.type === 0 && morph.groupReferences) {
|
|
291
|
+
const groupWeight = weights[morphIdx];
|
|
292
|
+
if (groupWeight > 0.0001) {
|
|
293
|
+
for (const ref of morph.groupReferences) {
|
|
294
|
+
if (ref.morphIndex >= 0 && ref.morphIndex < morphCount) {
|
|
295
|
+
// Add group morph's contribution to the referenced morph
|
|
296
|
+
effectiveWeights[ref.morphIndex] += groupWeight * ref.ratio;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// Clamp effective weights to [0, 1]
|
|
303
|
+
for (let i = 0; i < morphCount; i++) {
|
|
304
|
+
effectiveWeights[i] = Math.max(0, Math.min(1, effectiveWeights[i]));
|
|
305
|
+
}
|
|
306
|
+
// Second pass: Apply vertex morphs with their effective weights
|
|
307
|
+
for (let morphIdx = 0; morphIdx < morphCount; morphIdx++) {
|
|
308
|
+
const effectiveWeight = effectiveWeights[morphIdx];
|
|
309
|
+
if (effectiveWeight === 0 || effectiveWeight < 0.0001)
|
|
310
|
+
continue;
|
|
311
|
+
const morph = this.morphing.morphs[morphIdx];
|
|
312
|
+
if (morph.type !== 1)
|
|
313
|
+
continue; // Only process vertex morphs
|
|
314
|
+
// For vertex morphs, iterate through vertices that have offsets
|
|
315
|
+
for (const vertexOffset of morph.vertexOffsets) {
|
|
316
|
+
const vIdx = vertexOffset.vertexIndex;
|
|
317
|
+
if (vIdx < 0 || vIdx >= vertexCount)
|
|
318
|
+
continue;
|
|
319
|
+
// Get morph offset for this vertex
|
|
320
|
+
const offsetX = vertexOffset.positionOffset[0];
|
|
321
|
+
const offsetY = vertexOffset.positionOffset[1];
|
|
322
|
+
const offsetZ = vertexOffset.positionOffset[2];
|
|
323
|
+
// Skip if offset is zero
|
|
324
|
+
if (Math.abs(offsetX) < 0.0001 && Math.abs(offsetY) < 0.0001 && Math.abs(offsetZ) < 0.0001) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
// Apply weighted offset to vertex position (positions are at stride 0, 8, 16, ...)
|
|
328
|
+
const vertexIdx = vIdx * VERTEX_STRIDE;
|
|
329
|
+
this.vertexData[vertexIdx] += offsetX * effectiveWeight;
|
|
330
|
+
this.vertexData[vertexIdx + 1] += offsetY * effectiveWeight;
|
|
331
|
+
this.vertexData[vertexIdx + 2] += offsetZ * effectiveWeight;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
185
335
|
evaluatePose() {
|
|
186
336
|
this.updateRotationTweens();
|
|
337
|
+
const hasActiveMorphTweens = this.updateMorphWeightTweens();
|
|
338
|
+
if (hasActiveMorphTweens) {
|
|
339
|
+
this.applyMorphs();
|
|
340
|
+
}
|
|
187
341
|
this.computeWorldMatrices();
|
|
342
|
+
return hasActiveMorphTweens;
|
|
188
343
|
}
|
|
189
344
|
computeWorldMatrices() {
|
|
190
345
|
const bones = this.skeleton.bones;
|
package/dist/pmx-loader.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export declare class PmxLoader {
|
|
|
17
17
|
private inverseBindMatrices;
|
|
18
18
|
private joints0;
|
|
19
19
|
private weights0;
|
|
20
|
+
private morphs;
|
|
21
|
+
private vertexCount;
|
|
20
22
|
private rigidbodies;
|
|
21
23
|
private joints;
|
|
22
24
|
private constructor();
|
|
@@ -28,7 +30,7 @@ export declare class PmxLoader {
|
|
|
28
30
|
private parseTextures;
|
|
29
31
|
private parseMaterials;
|
|
30
32
|
private parseBones;
|
|
31
|
-
private
|
|
33
|
+
private parseMorphs;
|
|
32
34
|
private skipDisplayFrames;
|
|
33
35
|
private parseRigidbodies;
|
|
34
36
|
private parseJoints;
|
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,
|
|
1
|
+
{"version":3,"file":"pmx-loader.d.ts","sourceRoot":"","sources":["../src/pmx-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAUN,MAAM,SAAS,CAAA;AAIhB,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,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAc;IAE5B,OAAO;WAIM,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAK9C,OAAO,CAAC,KAAK;IAiBb,OAAO,CAAC,WAAW;IA+CnB,OAAO,CAAC,aAAa;IA+FrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,cAAc;IAyFtB,OAAO,CAAC,UAAU;IA2IlB,OAAO,CAAC,WAAW;IA+InB,OAAO,CAAC,iBAAiB;IAgDzB,OAAO,CAAC,gBAAgB;IAyFxB,OAAO,CAAC,WAAW;IAmGnB,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,OAAO;IAkLf,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;IAMjB,OAAO,CAAC,OAAO;IAmBf,OAAO,CAAC,QAAQ;CAIjB"}
|