@woosh/meep-engine 3.18.0 → 3.20.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/build/bundle-worker-image-decoder.js +1 -1
- package/build/bundle-worker-terrain.js +1 -1
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleCurveEditorView.js +303 -120
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleGradientEditorView.js +108 -63
- package/editor/view/particles/effect/ParticleGraphEditorView.js +2 -2
- package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleNodeParametersView.js +7 -46
- package/editor/view/particles/effect/particle-editor.css +60 -30
- package/package.json +1 -2
- package/samples/engine/README.md +1 -1
- package/src/core/binary/compression/decompress_bytes.d.ts +13 -0
- package/src/core/binary/compression/decompress_bytes.d.ts.map +1 -0
- package/src/core/binary/compression/decompress_bytes.js +28 -0
- package/src/core/collection/array/array_group_by.d.ts.map +1 -1
- package/src/core/collection/array/array_group_by.js +2 -11
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.js +4 -9
- package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +67 -22
- package/src/core/model/object/optional_clone.d.ts +7 -0
- package/src/core/model/object/optional_clone.d.ts.map +1 -0
- package/src/core/model/object/optional_equality.d.ts +10 -0
- package/src/core/model/object/optional_equality.d.ts.map +1 -0
- package/src/{shade/descriptor/util → core/model/object}/optional_equality.js +2 -2
- package/src/core/model/object/optional_hash.d.ts +9 -0
- package/src/core/model/object/optional_hash.d.ts.map +1 -0
- package/src/{shade/descriptor/util → core/model/object}/optional_hash.js +3 -3
- package/src/engine/asset/Asset.d.ts +1 -1
- package/src/engine/asset/Asset.d.ts.map +1 -1
- package/src/engine/asset/Asset.js +3 -1
- package/src/engine/asset/loaders/image/ImageDecoderWorker.js +12 -27
- package/src/engine/asset/loaders/image/prototypePNG.js +8 -7
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.d.ts.map +1 -1
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +9 -10
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +266 -0
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -0
- package/src/engine/graphics/ecs/particles/ParticleEffect.js +439 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts +58 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts.map +1 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.js +219 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +178 -25
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +809 -310
- package/src/format/image/png/PNGReader.d.ts +7 -6
- package/src/format/image/png/PNGReader.d.ts.map +1 -1
- package/src/format/image/png/PNGReader.js +13 -12
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts +3 -2
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts.map +1 -1
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.js +5 -4
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts +3 -2
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts.map +1 -1
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.js +5 -4
- package/src/format/image/png/png_inflate.d.ts +3 -3
- package/src/format/image/png/png_inflate.d.ts.map +1 -1
- package/src/format/image/png/png_inflate.js +29 -39
- package/src/format/texture/ktx2/ktx2_read.d.ts +4 -4
- package/src/format/texture/ktx2/ktx2_read.d.ts.map +1 -1
- package/src/format/texture/ktx2/ktx2_read.js +18 -21
- package/src/shade/descriptor/binding/BindGroupLayoutDescriptor.js +1 -1
- package/src/shade/descriptor/binding/BindGroupLayoutEntry.js +3 -3
- package/src/shade/descriptor/pipeline/PipelineDescriptorBase.js +1 -1
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +1 -1
- package/src/shade/descriptor/pipeline/render/ColorTargetState.js +3 -3
- package/src/shade/descriptor/pipeline/render/FragmentState.js +1 -1
- package/src/shade/descriptor/pipeline/render/RenderPipelineDescriptor.js +3 -3
- package/src/shade/playground/particle_ecs/README.md +203 -0
- package/src/shade/playground/particle_ecs/bonfire_editor.d.ts +39 -0
- package/src/shade/playground/particle_ecs/bonfire_editor.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_editor.js +315 -0
- package/src/shade/playground/particle_ecs/bonfire_effects.d.ts +145 -0
- package/src/shade/playground/particle_ecs/bonfire_effects.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_effects.js +202 -0
- package/src/shade/playground/particle_ecs/bonfire_sprites.d.ts +23 -0
- package/src/shade/playground/particle_ecs/bonfire_sprites.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_sprites.js +315 -0
- package/src/shade/playground/particle_ecs/bonfire_world.d.ts +86 -0
- package/src/shade/playground/particle_ecs/bonfire_world.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/bonfire_world.js +303 -0
- package/src/shade/playground/particle_ecs/effects/embers.json +1634 -0
- package/src/shade/playground/particle_ecs/effects/flame.json +1882 -0
- package/src/shade/playground/particle_ecs/effects/smoke.json +1860 -0
- package/src/shade/playground/particle_ecs/effects/soot.json +1606 -0
- package/src/shade/playground/particle_ecs/index.html +330 -0
- package/src/shade/playground/particle_ecs/main.d.ts +2 -0
- package/src/shade/playground/particle_ecs/main.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/main.js +566 -0
- package/src/shade/playground/particle_ecs/moonlit_environment.d.ts +16 -0
- package/src/shade/playground/particle_ecs/moonlit_environment.d.ts.map +1 -0
- package/src/shade/playground/particle_ecs/moonlit_environment.js +144 -0
- package/src/shade/playground/particle_editor/README.md +5 -4
- package/src/shade/playground/particle_system/particle_prototype.d.ts +7 -9
- package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
- package/src/shade/playground/particle_system/particle_prototype.js +7 -9
- package/src/shade/playground/profile_hotkey.d.ts +58 -0
- package/src/shade/playground/profile_hotkey.d.ts.map +1 -0
- package/src/shade/playground/profile_hotkey.js +325 -0
- package/src/shade/playground/ssr_motion/README.md +22 -0
- package/src/shade/playground/ssr_motion/index.html +18 -0
- package/src/shade/playground/ssr_motion/main.d.ts +2 -0
- package/src/shade/playground/ssr_motion/main.d.ts.map +1 -0
- package/src/shade/playground/ssr_motion/main.js +149 -0
- package/src/shade/playground/ssr_variance/README.md +105 -0
- package/src/shade/playground/ssr_variance/capture.d.ts +16 -0
- package/src/shade/playground/ssr_variance/capture.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/capture.js +96 -0
- package/src/shade/playground/ssr_variance/index.html +23 -0
- package/src/shade/playground/ssr_variance/main.d.ts +2 -0
- package/src/shade/playground/ssr_variance/main.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/main.js +246 -0
- package/src/shade/playground/ssr_variance/reference.d.ts +18 -0
- package/src/shade/playground/ssr_variance/reference.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/reference.js +78 -0
- package/src/shade/playground/ssr_variance/scene.d.ts +11 -0
- package/src/shade/playground/ssr_variance/scene.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/scene.js +61 -0
- package/src/shade/playground/ssr_variance/statistics.d.ts +44 -0
- package/src/shade/playground/ssr_variance/statistics.d.ts.map +1 -0
- package/src/shade/playground/ssr_variance/statistics.js +51 -0
- package/src/shade/renderer/geometry/Geometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/Geometry.js +4 -7
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts.map +1 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.js +9 -3
- package/src/shade/renderer/loader/usd/usd_decode_image.d.ts +4 -4
- package/src/shade/renderer/loader/usd/usd_decode_image.d.ts.map +1 -1
- package/src/shade/renderer/loader/usd/usd_decode_image.js +4 -4
- package/src/shade/renderer/material/StandardShadeMaterial.js +2 -2
- package/src/shade/renderer/particles/DESIGN.md +745 -702
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +3 -1
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +1 -1
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +9 -15
- package/src/shade/renderer/particles/graph/particle_group_library.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_group_library.js +8 -3
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +0 -2
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_parameters.js +0 -9
- package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_presentation.js +0 -10
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts +2 -8
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_ramp.js +2 -8
- package/src/shade/renderer/particles/graph/validate_particle_graph.js +0 -6
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles_avboit.js +13 -4
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +1 -12
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/InstructionStream.js +1 -12
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +54 -60
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleVMISA.js +9 -17
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts +0 -1
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/particle_assembly.js +2 -16
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +1 -1
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +1 -1
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +0 -14
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +3 -17
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +15 -36
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +1 -5
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +1 -8
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +2 -11
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +2 -11
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +11 -4
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ParticleEmitter.js +431 -424
- package/src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.js +13 -0
- package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts +3 -6
- package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +49 -17
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +0 -2
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +0 -2
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +1 -5
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +0 -2
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +1 -3
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/ParticleVMReference.js +4 -20
- package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/chunk_particle_vm.js +2 -5
- package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.d.ts.map +1 -1
- package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js +0 -2
- package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.d.ts.map +1 -1
- package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js +0 -2
- package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/SSR.js +2 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js +20 -5
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.js +19 -5
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts +4 -0
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +137 -0
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +0 -8
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +18 -114
- package/src/shade/renderer/scene/Mesh.js +1 -1
- package/src/shade/renderer/texture/ShadeTexture.js +1 -1
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts +2 -2
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts.map +1 -1
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.js +3 -3
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts +0 -19
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +0 -30
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.d.ts +0 -11
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.js +0 -13
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts +0 -20
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.d.ts +0 -14
- package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts +0 -50
- package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts.map +0 -1
- package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts +0 -17
- package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts.map +0 -1
- /package/src/{shade/descriptor/util → core/model/object}/optional_clone.js +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { ParticleProgram } from "../../../../shade/renderer/particles/isa/ParticleProgram.js";
|
|
2
|
+
import { ParticleLayout } from "../../../../shade/renderer/particles/layout/ParticleLayout.js";
|
|
3
|
+
import { BinaryClassSerializationAdapter } from "../../../ecs/storage/binary/BinaryClassSerializationAdapter.js";
|
|
4
|
+
import { ParticleEffect } from "./ParticleEffect.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Binary serialization for {@link ParticleEffect}.
|
|
8
|
+
*
|
|
9
|
+
* **The compiled effect is written, not a reference to one.** The VM's instruction set was designed
|
|
10
|
+
* to be a durable format — a fixed-width opcode encoding with a constant pool beside it — so a
|
|
11
|
+
* compiled program is content in exactly the way a mesh's index buffer is content, and a level that
|
|
12
|
+
* carries one needs neither the graph it came from nor a compiler at runtime. Authoring is an
|
|
13
|
+
* editor's job; a shipped build opens a save, reads instruction words, and runs them.
|
|
14
|
+
*
|
|
15
|
+
* That is also what makes the format's stability a real obligation. Two things here are wire format
|
|
16
|
+
* and cannot be renumbered without a version bump and an upgrader:
|
|
17
|
+
*
|
|
18
|
+
* - **opcodes**, whose numbers are `../../../../shade/renderer/particles/isa/ParticleVMISA.js`, and
|
|
19
|
+
* - **attribute order in the layout**, because a layout assigns word offsets sequentially from the
|
|
20
|
+
* order it is built in, and the render bindings below are those offsets. Offsets are therefore not
|
|
21
|
+
* written: they are recomputed on load from the same order, and a change to how
|
|
22
|
+
* {@link ParticleLayout} packs would silently repoint every binding in every save.
|
|
23
|
+
*
|
|
24
|
+
* ## The constant pool is written as bits
|
|
25
|
+
*
|
|
26
|
+
* The pool holds constants, not measurements, and two of them can be the same number: `-0` and `+0`
|
|
27
|
+
* are distinct pool words because a `DIV` by each disagrees about the sign of the infinity it
|
|
28
|
+
* produces, and the assembler interns with `Object.is` to keep them apart. `ParticleProgram` compares
|
|
29
|
+
* and hashes the pool through its bit view (`constant_words`) for exactly that reason.
|
|
30
|
+
*
|
|
31
|
+
* So does this. Not because a float path is known to lose something — measured on V8 it does not,
|
|
32
|
+
* `-0` survives `setFloat32` and so does a NaN's payload — but because whether a NaN survives a
|
|
33
|
+
* round trip through a JS `number` is **implementation-defined**: the language permits an engine to
|
|
34
|
+
* canonicalize, and the one this runs on is not the only one it will ever run on. Writing the words
|
|
35
|
+
* the program is already compared by makes the reload exact by construction rather than by an
|
|
36
|
+
* engine's discretion, and it means there is one representation of the pool rather than two.
|
|
37
|
+
*
|
|
38
|
+
* ## Nothing device-shaped is written
|
|
39
|
+
*
|
|
40
|
+
* There is nothing here that a device assigned: no table row, no generation, no program-heap
|
|
41
|
+
* placement, no atlas patch. Those belong to the registry that registered the emitter and are
|
|
42
|
+
* rebuilt on load like every other GPU resource. What is written is what an author typed.
|
|
43
|
+
*
|
|
44
|
+
* @author Alex Goldring
|
|
45
|
+
* @copyright Company Named Limited (c) 2026
|
|
46
|
+
*/
|
|
47
|
+
export class ParticleEffectSerializationAdapter extends BinaryClassSerializationAdapter {
|
|
48
|
+
|
|
49
|
+
klass = ParticleEffect;
|
|
50
|
+
version = 1;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {BinaryBuffer} buffer
|
|
54
|
+
* @param {ParticleEffect} value
|
|
55
|
+
*/
|
|
56
|
+
serialize(buffer, value) {
|
|
57
|
+
buffer.writeUTF8String(value.texture);
|
|
58
|
+
|
|
59
|
+
buffer.writeUintVar(value.seed);
|
|
60
|
+
buffer.writeFloat32(value.spawn_rate);
|
|
61
|
+
buffer.writeFloat32(value.prewarm);
|
|
62
|
+
buffer.writeUint8(value.emitting ? 1 : 0);
|
|
63
|
+
buffer.writeUint32(value.flags);
|
|
64
|
+
|
|
65
|
+
buffer.writeFloat32(value.flipbook[0]);
|
|
66
|
+
buffer.writeFloat32(value.flipbook[1]);
|
|
67
|
+
|
|
68
|
+
buffer.writeUint32(value.render_position);
|
|
69
|
+
buffer.writeUint32(value.render_size);
|
|
70
|
+
buffer.writeUint32(value.render_color);
|
|
71
|
+
buffer.writeUint32(value.render_rotation);
|
|
72
|
+
buffer.writeUint32(value.render_frame);
|
|
73
|
+
buffer.writeUint32(value.render_velocity);
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
A component with no effect is an ordinary state, not a half-built one: an entity whose
|
|
77
|
+
effect is still compiling, or one whose effect was cleared. It saves and loads as itself.
|
|
78
|
+
*/
|
|
79
|
+
const present = value.layout !== null && value.program !== null;
|
|
80
|
+
|
|
81
|
+
buffer.writeUint8(present ? 1 : 0);
|
|
82
|
+
|
|
83
|
+
if (!present) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
write_layout(buffer, value.layout);
|
|
88
|
+
write_program(buffer, value.program);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {BinaryBuffer} buffer
|
|
93
|
+
* @param {ParticleEffect} value
|
|
94
|
+
*/
|
|
95
|
+
deserialize(buffer, value) {
|
|
96
|
+
value.texture = buffer.readUTF8String();
|
|
97
|
+
|
|
98
|
+
value.seed = buffer.readUintVar();
|
|
99
|
+
value.spawn_rate = buffer.readFloat32();
|
|
100
|
+
value.prewarm = buffer.readFloat32();
|
|
101
|
+
value.emitting = buffer.readUint8() === 1;
|
|
102
|
+
value.flags = buffer.readUint32();
|
|
103
|
+
|
|
104
|
+
value.flipbook[0] = buffer.readFloat32();
|
|
105
|
+
value.flipbook[1] = buffer.readFloat32();
|
|
106
|
+
|
|
107
|
+
value.render_position = buffer.readUint32();
|
|
108
|
+
value.render_size = buffer.readUint32();
|
|
109
|
+
value.render_color = buffer.readUint32();
|
|
110
|
+
value.render_rotation = buffer.readUint32();
|
|
111
|
+
value.render_frame = buffer.readUint32();
|
|
112
|
+
value.render_velocity = buffer.readUint32();
|
|
113
|
+
|
|
114
|
+
if (buffer.readUint8() !== 1) {
|
|
115
|
+
value.layout = null;
|
|
116
|
+
value.program = null;
|
|
117
|
+
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
value.layout = read_layout(buffer);
|
|
122
|
+
value.program = read_program(buffer);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {BinaryBuffer} buffer
|
|
128
|
+
* @param {ParticleLayout} layout
|
|
129
|
+
*/
|
|
130
|
+
function write_layout(buffer, layout) {
|
|
131
|
+
buffer.writeUintVar(layout.attributes.size);
|
|
132
|
+
|
|
133
|
+
// Insertion order, which is the order the offsets were assigned in and therefore the order they
|
|
134
|
+
// have to be rebuilt in. A Map iterates in insertion order by specification, so this is not an
|
|
135
|
+
// assumption about the implementation.
|
|
136
|
+
for (const attribute of layout.attributes.values()) {
|
|
137
|
+
buffer.writeUTF8String(attribute.name);
|
|
138
|
+
buffer.writeUint8(attribute.components);
|
|
139
|
+
|
|
140
|
+
// The semantic tag, and `null` where there is none. An effect saved with a tag this build
|
|
141
|
+
// has never heard of has to load as the plain vector it is rather than fail, which is why
|
|
142
|
+
// the tag is a string here as it is on the layout.
|
|
143
|
+
buffer.writeUTF8String(attribute.type ?? null);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @param {BinaryBuffer} buffer
|
|
149
|
+
* @returns {ParticleLayout}
|
|
150
|
+
*/
|
|
151
|
+
function read_layout(buffer) {
|
|
152
|
+
const count = buffer.readUintVar();
|
|
153
|
+
const attributes = [];
|
|
154
|
+
|
|
155
|
+
for (let i = 0; i < count; i++) {
|
|
156
|
+
const name = buffer.readUTF8String();
|
|
157
|
+
const components = buffer.readUint8();
|
|
158
|
+
const type = buffer.readUTF8String();
|
|
159
|
+
|
|
160
|
+
attributes.push(type === null ? { name, components } : { name, components, type });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return new ParticleLayout(attributes);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @param {BinaryBuffer} buffer
|
|
168
|
+
* @param {ParticleProgram} program
|
|
169
|
+
*/
|
|
170
|
+
function write_program(buffer, program) {
|
|
171
|
+
buffer.writeUint8(program.register_count);
|
|
172
|
+
|
|
173
|
+
write_words(buffer, program.init);
|
|
174
|
+
write_words(buffer, program.update);
|
|
175
|
+
// bits rather than floats — see the class note
|
|
176
|
+
write_words(buffer, program.constant_words);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @param {BinaryBuffer} buffer
|
|
181
|
+
* @returns {ParticleProgram}
|
|
182
|
+
*/
|
|
183
|
+
function read_program(buffer) {
|
|
184
|
+
const register_count = buffer.readUint8();
|
|
185
|
+
|
|
186
|
+
const init = read_words(buffer);
|
|
187
|
+
const update = read_words(buffer);
|
|
188
|
+
const constant_words = read_words(buffer);
|
|
189
|
+
|
|
190
|
+
return new ParticleProgram({
|
|
191
|
+
init,
|
|
192
|
+
update,
|
|
193
|
+
// the same bytes read as floats: `read_words` allocates its own buffer, so this view owns it
|
|
194
|
+
constants: new Float32Array(constant_words.buffer, constant_words.byteOffset, constant_words.length),
|
|
195
|
+
register_count,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @param {BinaryBuffer} buffer
|
|
201
|
+
* @param {Uint32Array} words
|
|
202
|
+
*/
|
|
203
|
+
function write_words(buffer, words) {
|
|
204
|
+
buffer.writeUintVar(words.length);
|
|
205
|
+
buffer.writeUint32Array(words, 0, words.length);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param {BinaryBuffer} buffer
|
|
210
|
+
* @returns {Uint32Array}
|
|
211
|
+
*/
|
|
212
|
+
function read_words(buffer) {
|
|
213
|
+
const length = buffer.readUintVar();
|
|
214
|
+
const words = new Uint32Array(length);
|
|
215
|
+
|
|
216
|
+
buffer.readUint32Array(words, 0, length);
|
|
217
|
+
|
|
218
|
+
return words;
|
|
219
|
+
}
|
|
@@ -1,38 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy a component onto the scene node built for it, reporting whether anything actually moved.
|
|
3
|
+
*
|
|
4
|
+
* Comparing while assigning rather than in a pass of its own is what makes change detection cost
|
|
5
|
+
* nothing extra: the fields have to be read to be written, and the only addition is an `||` per
|
|
6
|
+
* field. What it answers is whether the emitter's GPU row has to be restaged, and restaging one that
|
|
7
|
+
* has not changed is an upload per emitter per frame.
|
|
8
|
+
*
|
|
9
|
+
* `spawn_rate` comes from {@link ParticleEffect#effective_spawn_rate}, so an effect switched off
|
|
10
|
+
* with `emitting = false` reaches the GPU as a rate of zero and keeps its authored rate to come back
|
|
11
|
+
* to. Layout and program are shared by reference, never copied — two entities of one effect belong
|
|
12
|
+
* on one program id in the heap.
|
|
13
|
+
*
|
|
14
|
+
* @param {ParticleEmitter} node
|
|
15
|
+
* @param {ParticleEffect} effect
|
|
16
|
+
* @returns {boolean} whether the node differs from what it held before
|
|
17
|
+
*/
|
|
18
|
+
export function apply_particle_effect(node: ParticleEmitter, effect: ParticleEffect): boolean;
|
|
1
19
|
/**
|
|
2
20
|
* @typedef {object} ParticleAtlasTexture
|
|
3
|
-
* @property {number} references Number of
|
|
21
|
+
* @property {number} references Number of entities using this URL.
|
|
4
22
|
* @property {import("../graphics/texture/atlas/AtlasPatch.js").AtlasPatch|null} patch Null while loading or after failure.
|
|
5
23
|
*/
|
|
6
24
|
/**
|
|
7
|
-
* @typedef {object}
|
|
8
|
-
* @property {
|
|
9
|
-
* @property {
|
|
10
|
-
* @property {
|
|
25
|
+
* @typedef {object} ParticleEmitterEntry
|
|
26
|
+
* @property {number} entity
|
|
27
|
+
* @property {ParticleEffect} effect the entity's component — what to emit
|
|
28
|
+
* @property {Transform64} transform the entity's transform — where to emit it
|
|
29
|
+
* @property {ParticleEmitter|null} node the scene node, once the effect has a program to run
|
|
30
|
+
* @property {function():void} on_transform_changed
|
|
31
|
+
* @property {string|null} url last observed {@link ParticleEffect#texture}
|
|
32
|
+
* @property {ParticleAtlasTexture|null} texture shared image record, or null for an untextured effect
|
|
11
33
|
*/
|
|
12
34
|
/**
|
|
13
|
-
*
|
|
35
|
+
* Draws the game's GPU particle effects: one emitter per entity carrying
|
|
36
|
+
* {@link ../graphics/ecs/particles/ParticleEffect.js ParticleEffect} and
|
|
37
|
+
* {@link ../ecs/transform/Transform64.js Transform64}.
|
|
38
|
+
*
|
|
39
|
+
* ```js
|
|
40
|
+
* entityManager.addSystem(new GPUParticleEmitterSystem(graphics, scene, assetManager));
|
|
41
|
+
*
|
|
42
|
+
* new Entity()
|
|
43
|
+
* .add(new Transform64())
|
|
44
|
+
* .add(ParticleEffect.from({ ...create_particle_effect({ layout, init, update }), spawn_rate: 400 }))
|
|
45
|
+
* .build(dataset);
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* **The entity is the emitter.** The component says what it emits and the transform says where, the
|
|
49
|
+
* same division every other placed thing in this engine uses — a `Decal`, an `SGMesh`, a `Light`.
|
|
50
|
+
* Which means an emitter is spawned, moved, parented, attached to a bone, saved and destroyed by
|
|
51
|
+
* exactly the machinery that does those things for everything else, and a particle effect stops
|
|
52
|
+
* being a special case that needs its own scene-graph call.
|
|
53
|
+
*
|
|
54
|
+
* ## What this system does with the pair
|
|
55
|
+
*
|
|
56
|
+
* It builds a {@link ParticleEmitter} scene node per entity and owns it: the node is added to
|
|
57
|
+
* {@link scene} when the component has a compiled effect, follows the entity's transform, carries
|
|
58
|
+
* whatever the component currently says, and leaves the scene when the entity does. The node is not
|
|
59
|
+
* hidden — {@link node_of} hands it out — but it is not the interface either: write to the
|
|
60
|
+
* component and the next frame carries it.
|
|
14
61
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
62
|
+
* Changes are found by **comparison** rather than announced. Once a frame each entity's
|
|
63
|
+
* fields are compared against what was last written to its node, and the node is marked dirty only
|
|
64
|
+
* where they differ; `EmitterRegistry` then restages exactly the rows that moved. A component nobody
|
|
65
|
+
* touched costs a run of integer comparisons and no upload, so there is no change signal to fire and
|
|
66
|
+
* none to forget. What that buys is that gameplay can write `effect.spawn_rate = 0` anywhere,
|
|
67
|
+
* including from code that has never heard of this system.
|
|
18
68
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
69
|
+
* ## It owns the scene's sprite atlas
|
|
70
|
+
*
|
|
71
|
+
* Every {@link ParticleEffect#texture} is loaded through the supplied `AssetManager` and packed into
|
|
72
|
+
* one {@link TextureAtlas} shared by the scene, one patch per distinct URL however many entities
|
|
73
|
+
* name it, reference-counted so the last entity to let go is what unpacks it. A `FrameStart`
|
|
74
|
+
* extension publishes the pixels and every current patch region before the renderer records the
|
|
75
|
+
* particle passes — every repack moves UVs that nothing else changed, so the regions are rewritten
|
|
76
|
+
* whole rather than when a URL changes. Pending and failed images sample a transparent texel;
|
|
77
|
+
* effects with no image sample a white one.
|
|
78
|
+
*
|
|
79
|
+
* An emitter node in this scene that this system did not build — one added to the `Scene` directly —
|
|
80
|
+
* gets the white texel. The atlas is the scene's and that emitter has nothing in it, so the
|
|
81
|
+
* alternative is not "its own texture" but a UV rectangle from somebody else's image.
|
|
82
|
+
*
|
|
83
|
+
* ## What it is not
|
|
84
|
+
*
|
|
85
|
+
* It does not simulate anything and does not record a particle pass. `GPUParticleSystem` does both,
|
|
86
|
+
* inside the renderer, driven from the emitter table these rows are in — see
|
|
87
|
+
* `shade/renderer/particles/DESIGN.md`. This system's whole contribution is membership, placement,
|
|
88
|
+
* the fields, and the sprite sheet.
|
|
89
|
+
*
|
|
90
|
+
* It also does not retire the CPU `ParticleEmitterSystem`, which serves the `particular` effects the
|
|
91
|
+
* game still ships. The two coexist and share nothing.
|
|
23
92
|
*/
|
|
24
93
|
export class GPUParticleEmitterSystem extends System<any> {
|
|
25
94
|
/**
|
|
26
95
|
* @param {import("./GraphicsEngine.js").GraphicsEngine} graphics
|
|
27
|
-
* @param {import("../../shade/renderer/scene/Scene.js").Scene} scene scene
|
|
96
|
+
* @param {import("../../shade/renderer/scene/Scene.js").Scene} scene scene the emitters are put
|
|
97
|
+
* in, and whose particle atlas this system owns
|
|
28
98
|
* @param {import("../asset/AssetManager.js").AssetManager} assets
|
|
29
99
|
*/
|
|
30
100
|
constructor(graphics: import("./GraphicsEngine.js").GraphicsEngine, scene: import("../../shade/renderer/scene/Scene.js").Scene, assets: import("../asset/AssetManager.js").AssetManager<any>);
|
|
101
|
+
dependencies: (typeof Transform64 | typeof ParticleEffect)[];
|
|
31
102
|
/**
|
|
32
103
|
* CPU atlas, exposed for inspection. Owned by this system.
|
|
33
104
|
* @type {TextureAtlas}
|
|
34
105
|
*/
|
|
35
106
|
atlas: TextureAtlas;
|
|
107
|
+
/**
|
|
108
|
+
* The scene the emitters are put in. Received rather than created: meshes and lights come from
|
|
109
|
+
* systems of their own, and all of them have to be writing into one scene for any of it to be
|
|
110
|
+
* visible together.
|
|
111
|
+
*
|
|
112
|
+
* @returns {import("../../shade/renderer/scene/Scene.js").Scene}
|
|
113
|
+
*/
|
|
114
|
+
get scene(): import("../../shade/renderer/scene/Scene.js").Scene;
|
|
115
|
+
/**
|
|
116
|
+
* The emitter nodes this system currently has in the scene, in no particular order. Read-only —
|
|
117
|
+
* they follow the entities.
|
|
118
|
+
*
|
|
119
|
+
* @returns {ParticleEmitter[]}
|
|
120
|
+
*/
|
|
121
|
+
get emitters(): ParticleEmitter[];
|
|
122
|
+
/**
|
|
123
|
+
* The scene node built for an entity.
|
|
124
|
+
*
|
|
125
|
+
* Handed out for the things an entity reference cannot express — parenting something to the
|
|
126
|
+
* emitter, reading the world matrix the hierarchy pass composed — and for nothing routine: the
|
|
127
|
+
* component is how an effect is changed, and a node written to behind the component's back is
|
|
128
|
+
* overwritten by the next comparison.
|
|
129
|
+
*
|
|
130
|
+
* @param {number} entity
|
|
131
|
+
* @returns {ParticleEmitter|null} `null` for an entity this system has not linked, or one whose
|
|
132
|
+
* component has no compiled effect yet
|
|
133
|
+
*/
|
|
134
|
+
node_of(entity: number): ParticleEmitter | null;
|
|
135
|
+
/**
|
|
136
|
+
* Ask an entity's emitter for `count` particles on top of its rate, on the next frame.
|
|
137
|
+
*
|
|
138
|
+
* The one-shot half of the API, and the only thing here the CPU asks for rather than describes:
|
|
139
|
+
* an impact, a footfall, a muzzle flash. It goes through the same GPU path as continuous
|
|
140
|
+
* emission — the tick pass folds the burst into the emitter's accumulator, and the pool budget
|
|
141
|
+
* and the culling apply — so it is a request rather than a guarantee, and an entity whose
|
|
142
|
+
* emitter is not live by the time the frame starts is silently skipped.
|
|
143
|
+
*
|
|
144
|
+
* @param {number} entity
|
|
145
|
+
* @param {number} count
|
|
146
|
+
*/
|
|
147
|
+
burst(entity: number, count: number): void;
|
|
36
148
|
/**
|
|
37
149
|
* @param {import("../ecs/EntityManager.js").EntityManager} entityManager
|
|
38
150
|
* @returns {Promise<void>}
|
|
@@ -40,9 +152,37 @@ export class GPUParticleEmitterSystem extends System<any> {
|
|
|
40
152
|
startup(entityManager: import("../ecs/EntityManager.js").EntityManager): Promise<void>;
|
|
41
153
|
/** @returns {Promise<void>} */
|
|
42
154
|
shutdown(): Promise<void>;
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
|
|
155
|
+
/**
|
|
156
|
+
* @param {ParticleEffect} effect
|
|
157
|
+
* @param {Transform64} transform
|
|
158
|
+
* @param {number} entity
|
|
159
|
+
*/
|
|
160
|
+
link(effect: ParticleEffect, transform: Transform64, entity: number): void;
|
|
161
|
+
/**
|
|
162
|
+
* @param {ParticleEffect} effect
|
|
163
|
+
* @param {Transform64} transform
|
|
164
|
+
* @param {number} entity
|
|
165
|
+
*/
|
|
166
|
+
unlink(effect: ParticleEffect, transform: Transform64, entity: number): void;
|
|
167
|
+
/**
|
|
168
|
+
* Bring every emitter in line with its entity: build nodes for effects that have arrived, retire
|
|
169
|
+
* nodes for effects that have gone, copy changed fields onto the ones that stay, and follow the
|
|
170
|
+
* texture URLs.
|
|
171
|
+
*
|
|
172
|
+
* @param {number} [time_delta_seconds]
|
|
173
|
+
* @returns {void}
|
|
174
|
+
*/
|
|
175
|
+
update(time_delta_seconds?: number): void;
|
|
176
|
+
/**
|
|
177
|
+
* Publish the atlas at FrameStart — after the scene context has established transform rows, and
|
|
178
|
+
* before the renderer records the particle passes that read the emitter table.
|
|
179
|
+
*
|
|
180
|
+
* {@link update} is called from here as well as by the entity manager, because a frame must not
|
|
181
|
+
* depend on a simulation tick having preceded it: an editor draws on demand, and a paused game
|
|
182
|
+
* still renders. It is idempotent and costs a comparison per emitter when nothing has changed,
|
|
183
|
+
* which is what makes running it twice a frame the cheap way to be right rather than a saving
|
|
184
|
+
* worth chasing.
|
|
185
|
+
*
|
|
46
186
|
* @param {import("../../shade/renderer/extension/FrameContext.js").FrameContext} frame
|
|
47
187
|
* @returns {void}
|
|
48
188
|
*/
|
|
@@ -51,7 +191,7 @@ export class GPUParticleEmitterSystem extends System<any> {
|
|
|
51
191
|
}
|
|
52
192
|
export type ParticleAtlasTexture = {
|
|
53
193
|
/**
|
|
54
|
-
* Number of
|
|
194
|
+
* Number of entities using this URL.
|
|
55
195
|
*/
|
|
56
196
|
references: number;
|
|
57
197
|
/**
|
|
@@ -59,20 +199,33 @@ export type ParticleAtlasTexture = {
|
|
|
59
199
|
*/
|
|
60
200
|
patch: import("../graphics/texture/atlas/AtlasPatch.js").AtlasPatch | null;
|
|
61
201
|
};
|
|
62
|
-
export type
|
|
202
|
+
export type ParticleEmitterEntry = {
|
|
203
|
+
entity: number;
|
|
63
204
|
/**
|
|
64
|
-
*
|
|
205
|
+
* the entity's component — what to emit
|
|
65
206
|
*/
|
|
66
|
-
|
|
207
|
+
effect: ParticleEffect;
|
|
67
208
|
/**
|
|
68
|
-
*
|
|
209
|
+
* the entity's transform — where to emit it
|
|
69
210
|
*/
|
|
70
|
-
|
|
211
|
+
transform: Transform64;
|
|
212
|
+
/**
|
|
213
|
+
* the scene node, once the effect has a program to run
|
|
214
|
+
*/
|
|
215
|
+
node: ParticleEmitter | null;
|
|
216
|
+
on_transform_changed: () => void;
|
|
71
217
|
/**
|
|
72
|
-
*
|
|
218
|
+
* last observed {@link ParticleEffecttexture }
|
|
73
219
|
*/
|
|
74
|
-
|
|
220
|
+
url: string | null;
|
|
221
|
+
/**
|
|
222
|
+
* shared image record, or null for an untextured effect
|
|
223
|
+
*/
|
|
224
|
+
texture: ParticleAtlasTexture | null;
|
|
75
225
|
};
|
|
226
|
+
import { ParticleEmitter } from "../../shade/renderer/particles/runtime/ParticleEmitter.js";
|
|
227
|
+
import { ParticleEffect } from "../graphics/ecs/particles/ParticleEffect.js";
|
|
76
228
|
import { System } from "../ecs/System.js";
|
|
229
|
+
import { Transform64 } from "../ecs/transform/Transform64.js";
|
|
77
230
|
import { TextureAtlas } from "../graphics/texture/atlas/TextureAtlas.js";
|
|
78
231
|
//# sourceMappingURL=GPUParticleEmitterSystem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GPUParticleEmitterSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/GPUParticleEmitterSystem.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GPUParticleEmitterSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/GPUParticleEmitterSystem.js"],"names":[],"mappings":"AAqtBA;;;;;;;;;;;;;;;;GAgBG;AACH,4CAJW,eAAe,UACf,cAAc,GACZ,OAAO,CA4BnB;AAvuBD;;;;GAIG;AAEH;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH;IAoDI;;;;;OAKG;IACH,sBALW,OAAO,qBAAqB,EAAE,cAAc,SAC5C,OAAO,qCAAqC,EAAE,KAAK,gEAgB7D;IArED,6DAA6C;IAE7C;;;OAGG;IACH,OAFU,YAAY,CAEO;IAiE7B;;;;;;OAMG;IACH,iEAEC;IAED;;;;;OAKG;IACH,kCAEC;IAED;;;;;;;;;;;OAWG;IACH,gBAJW,MAAM,GACJ,eAAe,GAAC,IAAI,CAWhC;IAED;;;;;;;;;;;OAWG;IACH,cAHW,MAAM,SACN,MAAM,QA4BhB;IAED;;;OAGG;IACH,uBAHW,OAAO,yBAAyB,EAAE,aAAa,GAC7C,QAAQ,IAAI,CAAC,CAYzB;IAED,+BAA+B;IAC/B,YADc,QAAQ,IAAI,CAAC,CAyB1B;IAED;;;;OAIG;IACH,aAJW,cAAc,aACd,WAAW,UACX,MAAM,QAgChB;IAED;;;;OAIG;IACH,eAJW,cAAc,aACd,WAAW,UACX,MAAM,QAIhB;IAED;;;;;;;OAOG;IACH,4BAHW,MAAM,GACJ,IAAI,CAQhB;IAED;;;;;;;;;;;;OAYG;IACH,eAHW,OAAO,gDAAgD,EAAE,YAAY,GACnE,IAAI,CAqChB;;CA0TJ;;;;;gBAxrBa,MAAM;;;;WACN,OAAO,yCAAyC,EAAE,UAAU,GAAC,IAAI;;;YAKjE,MAAM;;;;YACN,cAAc;;;;eACd,WAAW;;;;UACX,eAAe,GAAC,IAAI;gCACT,IAAI;;;;SACf,MAAM,GAAC,IAAI;;;;aACX,oBAAoB,GAAC,IAAI;;gCAnCP,2DAA2D;+BAQ5D,6CAA6C;uBANrD,kBAAkB;4BAEb,iCAAiC;6BAKhC,2CAA2C"}
|