@forgeax/engine-render 0.1.24 → 0.1.26

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.
Files changed (167) hide show
  1. package/README.md +118 -1
  2. package/dist/assembly/factory.d.ts +1 -1
  3. package/dist/assembly/factory.d.ts.map +1 -1
  4. package/dist/assembly/material/assembly.d.ts +4 -17
  5. package/dist/assembly/material/assembly.d.ts.map +1 -1
  6. package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -1
  7. package/dist/assembly/material/surface-projection.d.ts +24 -0
  8. package/dist/assembly/material/surface-projection.d.ts.map +1 -0
  9. package/dist/assembly/material-shader-policy.d.ts +20 -0
  10. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  11. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  12. package/dist/assembly/webgpu-renderer.d.ts +1 -2
  13. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  14. package/dist/assembly/webgpu-vertex-layouts.d.ts +89 -0
  15. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -0
  16. package/dist/assets/asset-decoders.d.ts.map +1 -1
  17. package/dist/authoring.mjs +1 -1
  18. package/dist/{chunk-Q752SHI5.mjs → chunk-ADHHVYLW.mjs} +3 -3
  19. package/dist/chunk-ADHHVYLW.mjs.map +1 -0
  20. package/dist/{chunk-TFH5I7JJ.mjs → chunk-E34VL5VI.mjs} +3 -3
  21. package/dist/{chunk-TFH5I7JJ.mjs.map → chunk-E34VL5VI.mjs.map} +1 -1
  22. package/dist/{chunk-YKB5DQV7.mjs → chunk-GF523LHF.mjs} +89 -21
  23. package/dist/chunk-GF523LHF.mjs.map +1 -0
  24. package/dist/{chunk-KZFTK6DO.mjs → chunk-HKXTW355.mjs} +7 -4
  25. package/dist/chunk-HKXTW355.mjs.map +1 -0
  26. package/dist/{chunk-UQYS7FRM.mjs → chunk-KM2NOX2I.mjs} +4 -4
  27. package/dist/{chunk-UQYS7FRM.mjs.map → chunk-KM2NOX2I.mjs.map} +1 -1
  28. package/dist/{chunk-YRUYGA4A.mjs → chunk-TMIASV2N.mjs} +944 -577
  29. package/dist/chunk-TMIASV2N.mjs.map +1 -0
  30. package/dist/{chunk-Z3YYH2MB.mjs → chunk-YUQXSEHG.mjs} +160 -73
  31. package/dist/chunk-YUQXSEHG.mjs.map +1 -0
  32. package/dist/{chunk-RR5L4SRS.mjs → chunk-ZZ4YQ474.mjs} +2 -2
  33. package/dist/{chunk-RR5L4SRS.mjs.map → chunk-ZZ4YQ474.mjs.map} +1 -1
  34. package/dist/components/instances.d.ts +13 -31
  35. package/dist/components/instances.d.ts.map +1 -1
  36. package/dist/construct-renderer.mjs +1012 -149
  37. package/dist/construct-renderer.mjs.map +1 -1
  38. package/dist/extract/contracts.d.ts +6 -6
  39. package/dist/extract/contracts.d.ts.map +1 -1
  40. package/dist/gpu-driven/production-raster.d.ts +6 -1
  41. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  42. package/dist/gpu-scene.d.ts +4 -0
  43. package/dist/gpu-scene.d.ts.map +1 -1
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.mjs +27 -9
  47. package/dist/index.mjs.map +1 -1
  48. package/dist/instance-buffer-cache.d.ts +7 -1
  49. package/dist/instance-buffer-cache.d.ts.map +1 -1
  50. package/dist/instances.d.ts +101 -0
  51. package/dist/instances.d.ts.map +1 -0
  52. package/dist/internal.mjs +5 -5
  53. package/dist/materials.d.ts +63 -2
  54. package/dist/materials.d.ts.map +1 -1
  55. package/dist/pipeline-builder.d.ts.map +1 -1
  56. package/dist/pipeline-spec-types.d.ts +2 -0
  57. package/dist/pipeline-spec-types.d.ts.map +1 -1
  58. package/dist/pipeline-spec.d.ts.map +1 -1
  59. package/dist/record/frame-snapshot.d.ts +13 -2
  60. package/dist/record/frame-snapshot.d.ts.map +1 -1
  61. package/dist/record/frame.d.ts.map +1 -1
  62. package/dist/record/main-pass-geometry.d.ts +23 -4
  63. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  64. package/dist/record/main-pass-material.d.ts +20 -2
  65. package/dist/record/main-pass-material.d.ts.map +1 -1
  66. package/dist/record/main-pass-sprite-draws.d.ts +3 -3
  67. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  68. package/dist/record/main-pass.d.ts.map +1 -1
  69. package/dist/record/material-uniforms.d.ts +4 -0
  70. package/dist/record/material-uniforms.d.ts.map +1 -0
  71. package/dist/record/render-context.d.ts +4 -3
  72. package/dist/record/render-context.d.ts.map +1 -1
  73. package/dist/record/shadow-pass.d.ts +10 -1
  74. package/dist/record/shadow-pass.d.ts.map +1 -1
  75. package/dist/recovery/render-system-candidate.d.ts +1 -1
  76. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  77. package/dist/render-contract.d.ts +4 -0
  78. package/dist/render-contract.d.ts.map +1 -1
  79. package/dist/render-system-extract-tail.d.ts +6 -0
  80. package/dist/render-system-extract-tail.d.ts.map +1 -1
  81. package/dist/render-system-extract.d.ts +44 -9
  82. package/dist/render-system-extract.d.ts.map +1 -1
  83. package/dist/render-system.d.ts +4 -1
  84. package/dist/render-system.d.ts.map +1 -1
  85. package/dist/scene/render-scene-types.d.ts +2 -0
  86. package/dist/scene/render-scene-types.d.ts.map +1 -1
  87. package/dist/scene/render-scene.d.ts +12 -1
  88. package/dist/scene/render-scene.d.ts.map +1 -1
  89. package/dist/systems/skin-palette-allocator.d.ts +6 -0
  90. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  91. package/dist/temporal/index.mjs +5 -5
  92. package/package.json +20 -20
  93. package/src/__tests__/fixtures/ai-weapon-spirit/README.md +20 -0
  94. package/src/__tests__/fixtures/ai-weapon-spirit/low-poly-toon.wgsl +178 -0
  95. package/src/__tests__/fixtures/ai-weapon-spirit/material.json +97 -0
  96. package/src/__tests__/fixtures/ai-weapon-spirit/painterly-surface.wgsl +55 -0
  97. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +3 -3
  98. package/src/__tests__/gpu-driven-view.browser.test.ts +11 -3
  99. package/src/__tests__/gpu-scene.unit.test.ts +38 -2
  100. package/src/__tests__/instances-store.unit.test.ts +46 -0
  101. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  102. package/src/__tests__/material-contract-inventory.unit.test.ts +48 -13
  103. package/src/__tests__/{material-static-dynamic-route.unit.test.ts → material-layer-projection.unit.test.ts} +30 -47
  104. package/src/__tests__/material-pass-policy.unit.test.ts +69 -0
  105. package/src/__tests__/material-program-dispatch.unit.test.ts +48 -0
  106. package/src/__tests__/material-snapshot-mutation.integration.test.ts +69 -0
  107. package/src/__tests__/material-surface-authoring.test-d.ts +62 -0
  108. package/src/__tests__/materials-transmission-validation.unit.test.ts +24 -0
  109. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +0 -4
  110. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +44 -2
  111. package/src/__tests__/skin-motion-regression.unit.test.ts +33 -0
  112. package/src/__tests__/skinned-shadow-caster.test.ts +30 -2
  113. package/src/__tests__/surface-adjacent-regressions.integration.test.ts +60 -0
  114. package/src/__tests__/surface-standard-pipeline.browser.test.ts +20 -0
  115. package/src/__tests__/surface-standard-pipeline.dawn.test.ts +20 -0
  116. package/src/__tests__/surface-standard-pipeline.fixture.ts +132 -0
  117. package/src/__tests__/surface-variant-provenance.integration.test.ts +33 -0
  118. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +1 -1
  119. package/src/assembly/factory.ts +2 -3
  120. package/src/assembly/material/__tests__/standard-layer-plan-projection.integration.test.ts +18 -0
  121. package/src/assembly/material/__tests__/surface-pass-projection.integration.test.ts +62 -0
  122. package/src/assembly/material/assembly.ts +8 -40
  123. package/src/assembly/material/standard-layer-projection.ts +3 -1
  124. package/src/assembly/material/surface-projection.ts +91 -0
  125. package/src/assembly/material-shader-policy.ts +88 -10
  126. package/src/assembly/recovery/renderer-recover.ts +1 -1
  127. package/src/assembly/webgpu-ready.ts +3 -16
  128. package/src/assembly/webgpu-renderer.ts +106 -166
  129. package/src/assembly/webgpu-vertex-layouts.ts +132 -0
  130. package/src/assets/asset-decoders.ts +27 -4
  131. package/src/components/instances.ts +14 -197
  132. package/src/extract/contracts.ts +6 -6
  133. package/src/gpu-driven/production-raster.ts +34 -1
  134. package/src/gpu-scene.ts +84 -29
  135. package/src/index.ts +1 -0
  136. package/src/instance-buffer-cache.ts +14 -1
  137. package/src/instances.ts +288 -0
  138. package/src/materials.ts +109 -14
  139. package/src/pipeline-builder.ts +14 -10
  140. package/src/pipeline-spec-types.ts +2 -0
  141. package/src/pipeline-spec.ts +13 -17
  142. package/src/record/frame-snapshot.ts +19 -2
  143. package/src/record/frame.ts +38 -3
  144. package/src/record/main-pass-geometry.ts +837 -337
  145. package/src/record/main-pass-material.ts +87 -2
  146. package/src/record/main-pass-sprite-draws.ts +66 -169
  147. package/src/record/main-pass.ts +24 -246
  148. package/src/record/material-uniforms.ts +186 -0
  149. package/src/record/render-context.ts +8 -0
  150. package/src/record/shadow-pass.ts +120 -115
  151. package/src/recovery/render-system-candidate.ts +46 -5
  152. package/src/render-contract.ts +4 -0
  153. package/src/render-system-extract-tail.ts +153 -57
  154. package/src/render-system-extract.ts +110 -73
  155. package/src/render-system.ts +59 -5
  156. package/src/scene/render-scene-types.ts +2 -0
  157. package/src/scene/render-scene.ts +579 -36
  158. package/src/systems/skin-palette-allocator.ts +129 -7
  159. package/src/transmission/__tests__/surface-compatibility.integration.test.ts +32 -0
  160. package/dist/assembly/material/pipeline-projection.d.ts +0 -30
  161. package/dist/assembly/material/pipeline-projection.d.ts.map +0 -1
  162. package/dist/chunk-KZFTK6DO.mjs.map +0 -1
  163. package/dist/chunk-Q752SHI5.mjs.map +0 -1
  164. package/dist/chunk-YKB5DQV7.mjs.map +0 -1
  165. package/dist/chunk-YRUYGA4A.mjs.map +0 -1
  166. package/dist/chunk-Z3YYH2MB.mjs.map +0 -1
  167. package/src/assembly/material/pipeline-projection.ts +0 -63
@@ -98,6 +98,12 @@ export interface SkinPaletteAllocator {
98
98
  * `device.limits.maxStorageBufferBindingSize`
99
99
  */
100
100
  allocateSlice(jointCount: number): SkinPaletteSlice;
101
+ /** Allocate one stable slice for a retained render source. */
102
+ allocateSliceFor(key: string, jointCount: number): SkinPaletteSlice;
103
+ /** Release a stable slice when its render source leaves the scene. */
104
+ releaseSliceFor(key: string): void;
105
+ /** Reconcile stable slices after a full render-source extraction. */
106
+ retainSliceKeys(keys: ReadonlySet<string>): void;
101
107
  /**
102
108
  * Write joint matrices into the slice's buffer at the slice's offset.
103
109
  * Computes M_i = jointWorldTransforms[i] * ibm[i] per joint.
@@ -129,6 +135,16 @@ export function createSkinPaletteAllocator(
129
135
  let storageBuffer: Buffer | null = null;
130
136
  let storageCapacity = 0;
131
137
  let storageCursor = 0;
138
+ let stableStorageCursor = 0;
139
+ const stableSlices = new Map<string, SkinPaletteSlice>();
140
+ const stableUniformBuffers = new Map<string, Buffer>();
141
+ const storageBufferCapacities = new WeakMap<Buffer, number>();
142
+ const stableFreeRanges: Array<{
143
+ start: number;
144
+ count: number;
145
+ buffer: Buffer;
146
+ capacity: number;
147
+ }> = [];
132
148
 
133
149
  // Uniform path: per-entity buffer pool. `pool` is the pre-allocated
134
150
  // 16320 B UBO ring; `poolCursor` advances per allocateSlice within a
@@ -158,14 +174,10 @@ export function createSkinPaletteAllocator(
158
174
  if (!bufRes.ok) throw bufRes.error;
159
175
  storageBuffer = bufRes.value;
160
176
  storageCapacity = newCapacity;
177
+ storageBufferCapacities.set(storageBuffer, newCapacity);
161
178
  }
162
179
 
163
- function acquirePoolBuffer(): Buffer {
164
- if (poolCursor < pool.length) {
165
- const reused = pool[poolCursor];
166
- // biome-ignore lint/style/noNonNullAssertion: poolCursor < pool.length guarantees the slot is set
167
- return reused!;
168
- }
180
+ function createUniformBuffer(): Buffer {
169
181
  if (BINDING_WINDOW_BYTES > maxBindingSize) {
170
182
  throw new SkinPaletteOverflowError(BINDING_WINDOW_BYTES, maxBindingSize);
171
183
  }
@@ -176,10 +188,20 @@ export function createSkinPaletteAllocator(
176
188
  mappedAtCreation: false,
177
189
  });
178
190
  if (!bufRes.ok) throw bufRes.error;
179
- pool.push(bufRes.value);
180
191
  return bufRes.value;
181
192
  }
182
193
 
194
+ function acquirePoolBuffer(): Buffer {
195
+ if (poolCursor < pool.length) {
196
+ const reused = pool[poolCursor];
197
+ // biome-ignore lint/style/noNonNullAssertion: poolCursor < pool.length guarantees the slot is set
198
+ return reused!;
199
+ }
200
+ const buffer = createUniformBuffer();
201
+ pool.push(buffer);
202
+ return buffer;
203
+ }
204
+
183
205
  function allocateSlice(jointCount: number): SkinPaletteSlice {
184
206
  if (useStorageBuffer) {
185
207
  // Storage path: shared buffer + dynOffset window.
@@ -209,6 +231,103 @@ export function createSkinPaletteAllocator(
209
231
  return { jointCount, byteOffset: 0, buffer };
210
232
  }
211
233
 
234
+ function allocateSliceFor(key: string, jointCount: number): SkinPaletteSlice {
235
+ const existing = stableSlices.get(key);
236
+ if (existing !== undefined && existing.jointCount === jointCount) return existing;
237
+ if (existing !== undefined) releaseSliceFor(key);
238
+ if (useStorageBuffer) {
239
+ const span =
240
+ (jointCount * MAT4_BYTES + (PALETTE_OFFSET_ALIGN - 1)) & ~(PALETTE_OFFSET_ALIGN - 1);
241
+ const freeIndex = stableFreeRanges.findIndex(
242
+ (range) =>
243
+ range.buffer === storageBuffer &&
244
+ range.count >= span &&
245
+ range.start + BINDING_WINDOW_BYTES <= range.capacity,
246
+ );
247
+ let offset: number;
248
+ let buffer: Buffer;
249
+ if (freeIndex >= 0) {
250
+ const range = stableFreeRanges[freeIndex];
251
+ if (range === undefined) throw new Error('Skin palette free range disappeared.');
252
+ offset = range.start;
253
+ buffer = range.buffer;
254
+ if (range.count === span) stableFreeRanges.splice(freeIndex, 1);
255
+ else {
256
+ stableFreeRanges[freeIndex] = {
257
+ ...range,
258
+ start: range.start + span,
259
+ count: range.count - span,
260
+ };
261
+ }
262
+ } else {
263
+ offset = stableStorageCursor;
264
+ ensureStorageCapacity(offset + BINDING_WINDOW_BYTES);
265
+ const currentBuffer = storageBuffer;
266
+ if (currentBuffer === null) throw new Error('Skin palette storage buffer was not created.');
267
+ buffer = currentBuffer;
268
+ stableStorageCursor = offset + span;
269
+ }
270
+ const slice = { jointCount, byteOffset: offset, buffer };
271
+ stableSlices.set(key, slice);
272
+ return slice;
273
+ }
274
+ let buffer = stableUniformBuffers.get(key);
275
+ if (buffer === undefined) {
276
+ // Stable slices have a lifetime longer than the frame pool. Allocate a
277
+ // dedicated UBO so resetForFrame() can never hand it to another entity.
278
+ buffer = createUniformBuffer();
279
+ stableUniformBuffers.set(key, buffer);
280
+ }
281
+ const slice = { jointCount, byteOffset: 0, buffer };
282
+ stableSlices.set(key, slice);
283
+ return slice;
284
+ }
285
+
286
+ function releaseSliceFor(key: string): void {
287
+ const slice = stableSlices.get(key);
288
+ if (slice === undefined) return;
289
+ stableSlices.delete(key);
290
+ if (!useStorageBuffer) {
291
+ stableUniformBuffers.delete(key);
292
+ device.destroyBuffer(slice.buffer);
293
+ return;
294
+ }
295
+ const count =
296
+ (slice.jointCount * MAT4_BYTES + (PALETTE_OFFSET_ALIGN - 1)) & ~(PALETTE_OFFSET_ALIGN - 1);
297
+ stableFreeRanges.push({
298
+ start: slice.byteOffset,
299
+ count,
300
+ buffer: slice.buffer,
301
+ capacity: storageBufferCapacities.get(slice.buffer) ?? storageCapacity,
302
+ });
303
+ stableFreeRanges.sort((left, right) => left.start - right.start);
304
+ for (let index = stableFreeRanges.length - 1; index > 0; index -= 1) {
305
+ const current = stableFreeRanges[index];
306
+ const previous = stableFreeRanges[index - 1];
307
+ if (
308
+ current === undefined ||
309
+ previous === undefined ||
310
+ current.buffer !== previous.buffer ||
311
+ previous.start + previous.count !== current.start
312
+ ) {
313
+ continue;
314
+ }
315
+ stableFreeRanges[index - 1] = {
316
+ start: previous.start,
317
+ count: previous.count + current.count,
318
+ buffer: previous.buffer,
319
+ capacity: previous.capacity,
320
+ };
321
+ stableFreeRanges.splice(index, 1);
322
+ }
323
+ }
324
+
325
+ function retainSliceKeys(keys: ReadonlySet<string>): void {
326
+ for (const key of stableSlices.keys()) {
327
+ if (!keys.has(key)) releaseSliceFor(key);
328
+ }
329
+ }
330
+
212
331
  function writeJointPalette(
213
332
  slice: SkinPaletteSlice,
214
333
  ibms: readonly Float32Array[],
@@ -245,6 +364,9 @@ export function createSkinPaletteAllocator(
245
364
  bindingWindowBytes: BINDING_WINDOW_BYTES,
246
365
  useStorageBuffer,
247
366
  allocateSlice,
367
+ allocateSliceFor,
368
+ releaseSliceFor,
369
+ retainSliceKeys,
248
370
  writeJointPalette,
249
371
  resetForFrame,
250
372
  };
@@ -0,0 +1,32 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { Materials } from '../../materials';
5
+
6
+ function shaderSource(name: string): string {
7
+ return readFileSync(
8
+ fileURLToPath(new URL(`../../../../shader/src/${name}`, import.meta.url)),
9
+ 'utf8',
10
+ );
11
+ }
12
+
13
+ describe('Surface compatibility boundaries', () => {
14
+ it('keeps transmission on its existing forward shading route', () => {
15
+ const material = Materials.standard({ baseColor: [1, 1, 1, 1], transmission: 1 });
16
+ expect(material.passes?.map((pass) => pass.name)).toEqual(['forward', 'shadow-caster']);
17
+ expect(material.passes?.map((pass) => pass.name)).not.toContain('deferred');
18
+ });
19
+
20
+ it('keeps the unlit sibling outside the Surface ABI', () => {
21
+ const unlit = shaderSource('unlit.wgsl');
22
+ expect(unlit).not.toContain('surface_v1');
23
+ expect(unlit).not.toContain('fs_gbuffer');
24
+ expect(unlit).toContain('fn fs_main');
25
+ });
26
+
27
+ it('keeps transmission fields out of the v1 Surface contract', () => {
28
+ const surface = shaderSource('surface_v1.wgsl');
29
+ expect(surface).not.toMatch(/transmission|thickness|attenuation/i);
30
+ expect(surface).not.toMatch(/@(vertex|fragment|compute)/);
31
+ });
32
+ });
@@ -1,30 +0,0 @@
1
- import type { MaterialRuntimeArtifact } from '@forgeax/engine-shader';
2
- import type { MaterialValue } from '@forgeax/engine-types';
3
- import type { MaterialRenderProjection } from './assembly.js';
4
- export interface MaterialPipelineProjection {
5
- readonly specializationKey: string;
6
- readonly artifactHash: string;
7
- readonly passes: MaterialRenderProjection['passes'];
8
- }
9
- export interface MaterialPipelineReady extends MaterialPipelineProjection {
10
- readonly kind: 'ready';
11
- readonly artifact: MaterialRuntimeArtifact;
12
- }
13
- export interface MaterialPipelineMiss {
14
- readonly kind: 'error';
15
- readonly error: {
16
- readonly code: 'material-specialization-not-cooked';
17
- readonly expected: string;
18
- readonly hint: string;
19
- readonly detail: {
20
- readonly specializationKey: string;
21
- };
22
- };
23
- }
24
- export declare function projectMaterialPipeline(projection: MaterialRenderProjection): MaterialPipelineProjection;
25
- export declare function updateMaterialRuntimeValues(projection: MaterialRenderProjection, values: Readonly<Record<string, MaterialValue | null>>): MaterialRenderProjection;
26
- export declare function routeMaterialPipeline(args: {
27
- readonly projection: MaterialRenderProjection;
28
- readonly lookupArtifact: (key: string) => MaterialRuntimeArtifact | undefined;
29
- }): MaterialPipelineReady | MaterialPipelineMiss;
30
- //# sourceMappingURL=pipeline-projection.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pipeline-projection.d.ts","sourceRoot":"","sources":["../../../src/assembly/material/pipeline-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,qBAAsB,SAAQ,0BAA0B;IACvE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;CAC5C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,oCAAoC,CAAC;QACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;SAAE,CAAC;KACzD,CAAC;CACH;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,wBAAwB,GACnC,0BAA0B,CAM5B;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,wBAAwB,EACpC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC,CAAC,GACrD,wBAAwB,CAK1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,uBAAuB,GAAG,SAAS,CAAC;CAC/E,GAAG,qBAAqB,GAAG,oBAAoB,CAc/C"}