@woosh/meep-engine 3.45.0 → 3.47.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-terrain.js +1 -1
- package/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
- package/editor/actions/concrete/TransformModifyAction.js +10 -2
- package/editor/ecs/component/FieldDescriptor.js +15 -0
- package/editor/ecs/component/createObjectEditor.js +41 -12
- package/editor/ecs/component/editors/ecs/Transform64Editor.d.ts.map +1 -1
- package/editor/ecs/component/editors/ecs/Transform64Editor.js +77 -70
- package/editor/tools/TransformToolV2.d.ts.map +1 -1
- package/editor/tools/TransformToolV2.js +4 -0
- package/editor/tools/v2/TransformControls.d.ts.map +1 -1
- package/editor/tools/v2/TransformControls.js +7 -0
- package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
- package/editor/view/ecs/EntityEditor.js +4 -2
- package/package.json +1 -1
- package/src/core/assert.d.ts.map +1 -1
- package/src/core/assert.js +5 -1
- package/src/core/binary/hash/XXH128Hash.d.ts +1 -37
- package/src/core/binary/hash/XXH128Hash.d.ts.map +1 -1
- package/src/core/binary/hash/XXH128Hash.js +4 -55
- package/src/core/binary/hash/XXH3_SECRET.d.ts +1 -12
- package/src/core/binary/hash/XXH3_SECRET.d.ts.map +1 -1
- package/src/core/binary/hash/XXH3_SECRET.js +4 -25
- package/src/core/binary/hash/crc32.d.ts +1 -15
- package/src/core/binary/hash/crc32.d.ts.map +1 -1
- package/src/core/binary/hash/crc32.js +4 -96
- package/src/core/binary/hash/xxh3_128.d.ts +1 -9
- package/src/core/binary/hash/xxh3_128.d.ts.map +1 -1
- package/src/core/binary/hash/xxh3_128.js +4 -341
- package/src/core/binary/hash/xxh3_64.d.ts +1 -8
- package/src/core/binary/hash/xxh3_64.d.ts.map +1 -1
- package/src/core/binary/hash/xxh3_64.js +4 -241
- package/src/core/binary/hash/xxh3_common.d.ts +1 -223
- package/src/core/binary/hash/xxh3_common.d.ts.map +1 -1
- package/src/core/binary/hash/xxh3_common.js +90 -476
- package/src/core/collection/array/array_insert_at.d.ts +16 -0
- package/src/core/collection/array/array_insert_at.d.ts.map +1 -0
- package/src/core/collection/array/array_insert_at.js +32 -0
- package/src/core/collection/array/array_remove_at.d.ts +15 -0
- package/src/core/collection/array/array_remove_at.d.ts.map +1 -0
- package/src/core/collection/array/array_remove_at.js +30 -0
- package/src/core/collection/array/combine_hash.d.ts +6 -0
- package/src/core/collection/array/combine_hash.d.ts.map +1 -1
- package/src/core/collection/array/combine_hash.js +6 -0
- package/src/core/function/FunctionCompiler.js +2 -2
- package/src/core/geom/3d/mat4/m4_multiply.d.ts +3 -0
- package/src/core/geom/3d/mat4/m4_multiply.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/m4_multiply.js +3 -0
- package/src/core/geom/3d/mat4/m4_multiply_f64.d.ts +30 -0
- package/src/core/geom/3d/mat4/m4_multiply_f64.d.ts.map +1 -0
- package/src/core/geom/3d/mat4/m4_multiply_f64.js +106 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts +37 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.js +172 -0
- package/src/core/geom/ConicRay.js +2 -2
- package/src/core/geom/Quaternion.d.ts +1 -0
- package/src/core/geom/Quaternion.d.ts.map +1 -1
- package/src/core/geom/Quaternion.js +12 -48
- package/src/core/geom/Vector4.d.ts.map +1 -1
- package/src/core/geom/Vector4.js +8 -5
- package/src/core/math/hash/XXH128Hash.d.ts +38 -0
- package/src/core/math/hash/XXH128Hash.d.ts.map +1 -0
- package/src/core/math/hash/XXH128Hash.js +55 -0
- package/src/core/math/hash/XXH3_SECRET.d.ts +13 -0
- package/src/core/math/hash/XXH3_SECRET.d.ts.map +1 -0
- package/src/core/math/hash/XXH3_SECRET.js +25 -0
- package/src/core/math/hash/crc32.d.ts +16 -0
- package/src/core/math/hash/crc32.d.ts.map +1 -0
- package/src/core/math/hash/crc32.js +96 -0
- package/src/core/math/hash/xxh3_128.d.ts +10 -0
- package/src/core/math/hash/xxh3_128.d.ts.map +1 -0
- package/src/core/math/hash/xxh3_128.js +341 -0
- package/src/core/math/hash/xxh3_64.d.ts +9 -0
- package/src/core/math/hash/xxh3_64.d.ts.map +1 -0
- package/src/core/math/hash/xxh3_64.js +241 -0
- package/src/core/math/hash/xxh3_common.d.ts +224 -0
- package/src/core/math/hash/xxh3_common.d.ts.map +1 -0
- package/src/core/math/hash/xxh3_common.js +476 -0
- package/src/core/math/lookup/ParameterLookupTable.js +2 -2
- package/src/core/model/node-graph/node/NodeInstancePortReference.js +2 -2
- package/src/core/model/reactive/model/ReactiveBinaryExpression.js +2 -2
- package/src/core/model/reactive/model/terminal/ReactiveReference.js +2 -2
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +9 -4
- package/src/engine/asset/AssetDescription.js +2 -2
- package/src/engine/ecs/animation/Animation.js +2 -2
- package/src/engine/ecs/animation/AnimationClip.d.ts.map +1 -1
- package/src/engine/ecs/animation/AnimationClip.js +7 -5
- package/src/engine/ecs/gui/GUIElement.d.ts.map +1 -1
- package/src/engine/ecs/gui/GUIElement.js +7 -5
- package/src/engine/ecs/gui/hud/HeadsUpDisplay.js +2 -2
- package/src/engine/ecs/gui/position/ViewportPosition.d.ts.map +1 -1
- package/src/engine/ecs/gui/position/ViewportPosition.js +11 -7
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +10 -0
- package/src/engine/ecs/transform/Transform64.d.ts +1 -1
- package/src/engine/ecs/transform/Transform64.d.ts.map +1 -1
- package/src/engine/ecs/transform/Transform64.js +5 -4
- package/src/engine/ecs/transform/t64_look_rotation.d.ts +4 -4
- package/src/engine/ecs/transform/t64_look_rotation.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_look_rotation.js +7 -18
- package/src/engine/graphics/ecs/animation/animator/AnimationClip.d.ts.map +1 -1
- package/src/engine/graphics/ecs/animation/animator/AnimationClip.js +8 -5
- package/src/engine/graphics/ecs/animation/animator/AnimationClipDefinition.js +2 -2
- package/src/engine/graphics/ecs/animation/animator/AnimationNotification.js +2 -2
- package/src/engine/graphics/ecs/animation/animator/AnimationNotificationDefinition.js +2 -2
- package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.js +2 -2
- package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationStateDefinition.js +2 -2
- package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationTransitionDefinition.d.ts.map +1 -1
- package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationTransitionDefinition.js +8 -5
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +30 -1
- package/src/engine/graphics/ecs/decal/v2/Decal.d.ts.map +1 -1
- package/src/engine/graphics/ecs/decal/v2/Decal.js +9 -8
- package/src/engine/graphics/render/frame_graph/resource/TextureResourceDescriptor.d.ts.map +1 -1
- package/src/engine/graphics/render/frame_graph/resource/TextureResourceDescriptor.js +9 -6
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +72 -29
- package/src/engine/graphics3/ParticipatingMedia.js +204 -204
- package/src/engine/graphics3/animation/AnimationClips.d.ts +5 -0
- package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -1
- package/src/engine/graphics3/animation/AnimationClips.js +5 -0
- package/src/engine/grid/obstacle/GridObstacle.js +2 -2
- package/src/engine/input/devices/KeyboardDevice.d.ts +1 -0
- package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
- package/src/engine/input/devices/KeyboardDevice.js +7 -6
- package/src/engine/intelligence/behavior/selector/WeightedElement.js +2 -2
- package/src/engine/interpolation/Interpolated.js +2 -2
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.d.ts.map +1 -1
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +15 -2
- package/src/engine/network/CONGESTION_CONTROL.md +9 -9
- package/src/engine/network/MESSAGE_TRANSPORT.md +364 -0
- package/src/engine/network/NetworkSession.d.ts +31 -11
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +453 -286
- package/src/engine/network/README.md +77 -27
- package/src/engine/network/SMOOTHNESS_DESIGN.md +13 -5
- package/src/engine/network/diagnostics/BandwidthMeter.d.ts +1 -1
- package/src/engine/network/diagnostics/BandwidthMeter.js +1 -1
- package/src/engine/network/orchestrator/HostJoin.d.ts +111 -0
- package/src/engine/network/orchestrator/HostJoin.d.ts.map +1 -0
- package/src/engine/network/orchestrator/HostJoin.js +271 -0
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +151 -112
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +450 -499
- package/src/engine/network/orchestrator/PendingSlices.d.ts +30 -0
- package/src/engine/network/orchestrator/PendingSlices.d.ts.map +1 -0
- package/src/engine/network/orchestrator/PendingSlices.js +83 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts +34 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts.map +1 -0
- package/src/engine/network/orchestrator/ReliableFrames.js +96 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +77 -10
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +236 -61
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +20 -6
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +33 -8
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +7 -1
- package/src/engine/network/sim/ActionLog.d.ts +32 -5
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +47 -5
- package/src/engine/network/sim/SimActionExecutor.d.ts +42 -2
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +100 -4
- package/src/engine/network/sim/Snapshotter.d.ts +12 -0
- package/src/engine/network/sim/Snapshotter.d.ts.map +1 -1
- package/src/engine/network/sim/Snapshotter.js +43 -0
- package/src/engine/network/state/Baseline.d.ts +1 -1
- package/src/engine/network/state/Baseline.js +1 -1
- package/src/engine/network/state/FrameBufferRing.d.ts +25 -6
- package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
- package/src/engine/network/state/FrameBufferRing.js +51 -6
- package/src/engine/network/state/InputRing.d.ts +4 -0
- package/src/engine/network/state/InputRing.d.ts.map +1 -1
- package/src/engine/network/state/InputRing.js +7 -0
- package/src/engine/network/transport/DeferredTransport.d.ts.map +1 -1
- package/src/engine/network/transport/DeferredTransport.js +1 -0
- package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -1
- package/src/engine/network/transport/LoopbackTransport.js +4 -2
- package/src/engine/network/transport/Transport.d.ts +7 -0
- package/src/engine/network/transport/Transport.d.ts.map +1 -1
- package/src/engine/network/transport/Transport.js +8 -0
- package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +20 -5
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +8 -0
- package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebTransportTransport.js +6 -0
- package/src/engine/network/transport/connection/Connection.d.ts +191 -0
- package/src/engine/network/transport/connection/Connection.d.ts.map +1 -0
- package/src/engine/network/transport/connection/Connection.js +1262 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts +94 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RangeSet.js +260 -0
- package/src/engine/network/transport/connection/RxStream.d.ts +48 -0
- package/src/engine/network/transport/connection/RxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RxStream.js +211 -0
- package/src/engine/network/transport/connection/TxStream.d.ts +90 -0
- package/src/engine/network/transport/connection/TxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/TxStream.js +243 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts +17 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts.map +1 -0
- package/src/engine/network/transport/connection/bytes_copy.js +34 -0
- package/src/engine/network/transport/connection/varint.d.ts +46 -0
- package/src/engine/network/transport/connection/varint.d.ts.map +1 -0
- package/src/engine/network/transport/connection/varint.js +107 -0
- package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/Cloth.js +7 -5
- package/src/engine/physics/cloth/ecs/ClothCollider.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothCollider.js +7 -5
- package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothDynamics.js +20 -11
- package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidField.js +7 -5
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -1
- package/src/engine/physics/fluid/ecs/FluidComponent.js +19 -11
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +2 -2
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +2 -2
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +11 -7
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +11 -7
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/WakeFluidEffector.js +16 -9
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +38 -7
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitter.js +47 -14
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js +48 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +12 -2
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +173 -9
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts +9 -3
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/LiveEmitterSet.js +28 -8
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts +8 -0
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.js +192 -191
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js +51 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.js +15 -1
- package/src/engine/sound/simulation/core/AcousticMedium.js +2 -2
- package/src/engine/sound/simulation/definition/AcousticDirectivity.js +2 -2
- package/src/engine/sound/simulation/definition/AcousticMaterial.d.ts.map +1 -1
- package/src/engine/sound/simulation/definition/AcousticMaterial.js +11 -7
- package/src/engine/sound/sopra/README.md +768 -644
- package/src/engine/sound/sopra/SopraEngine.d.ts +104 -8
- package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
- package/src/engine/sound/sopra/SopraEngine.js +327 -12
- package/src/engine/sound/sopra/definition/BusDefinition.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/BusDefinition.js +5 -4
- package/src/engine/sound/sopra/definition/DuckingRule.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/DuckingRule.js +7 -5
- package/src/engine/sound/sopra/definition/EventDescription.d.ts +28 -2
- package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescription.js +77 -17
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts +10 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +77 -55
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts +31 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.js +75 -0
- package/src/engine/sound/sopra/definition/MixerSnapshot.js +2 -2
- package/src/engine/sound/sopra/definition/ParameterDefinition.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/ParameterDefinition.js +7 -5
- package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +2 -2
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +4 -3
- package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +2 -2
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +3 -3
- package/src/engine/sound/sopra/definition/clip/SampleAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +16 -9
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +2 -2
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +1 -1
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +2 -2
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts +38 -9
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +34 -5
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts +7 -2
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +137 -120
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts +3 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.js +146 -128
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +1 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +8 -3
- package/src/engine/sound/sopra/legacy/SoundEmitter.d.ts.map +1 -1
- package/src/engine/sound/sopra/legacy/SoundEmitter.js +357 -352
- package/src/engine/sound/sopra/legacy/SoundTrack.d.ts.map +1 -1
- package/src/engine/sound/sopra/legacy/SoundTrack.js +281 -278
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts +44 -2
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/BusGraph.js +83 -43
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts +96 -0
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectChain.js +286 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts +123 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.js +320 -0
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts +55 -5
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/EventInstance.js +201 -26
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts +2 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +6 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts +15 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +32 -0
- package/src/engine/sound/sopra/util/MockAudioContext.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/MockAudioContext.js +3 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts +13 -3
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/fadeOutAndStop.js +25 -13
- package/src/format/image/png/PNGReader.js +644 -644
- package/src/format/image/png/crc32.d.ts +1 -1
- package/src/format/image/png/crc32.js +7 -8
- package/src/shade/RENDERER_CONTRACT.md +6 -3
- package/src/shade/descriptor/binding/BindGroupLayoutDescriptor.js +2 -2
- package/src/shade/descriptor/binding/BindGroupLayoutEntry.d.ts.map +1 -1
- package/src/shade/descriptor/binding/BindGroupLayoutEntry.js +12 -8
- package/src/shade/descriptor/binding/StorageTextureBindingLayout.js +2 -2
- package/src/shade/descriptor/binding/TextureBindingLayout.js +2 -2
- package/src/shade/descriptor/blend/BlendComponent.js +2 -2
- package/src/shade/descriptor/pipeline/PipelineDescriptorBase.js +2 -2
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +2 -2
- package/src/shade/descriptor/pipeline/ProgrammableStage.js +2 -2
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +2 -2
- package/src/shade/descriptor/pipeline/render/ColorTargetState.js +2 -2
- package/src/shade/descriptor/pipeline/render/FragmentState.js +2 -2
- package/src/shade/descriptor/pipeline/render/PrimitiveState.js +2 -2
- package/src/shade/descriptor/pipeline/render/RenderPipelineDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/render/RenderPipelineDescriptor.js +8 -5
- package/src/shade/descriptor/pipeline/render/VertexAttribute.js +2 -2
- package/src/shade/descriptor/texture/SamplerDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/texture/SamplerDescriptor.js +20 -12
- package/src/shade/descriptor/texture/TextureDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/texture/TextureDescriptor.js +11 -7
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts +24 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts.map +1 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.js +34 -0
- package/src/shade/device/ShadeDeviceFailure.d.ts +12 -5
- package/src/shade/device/ShadeDeviceFailure.d.ts.map +1 -1
- package/src/shade/device/ShadeDeviceFailure.js +17 -8
- package/src/shade/device/ShadeDeviceFailureReason.d.ts +1 -1
- package/src/shade/device/ShadeDeviceFailureReason.js +2 -2
- package/src/shade/device/graph/BufferResourceDescriptor.d.ts.map +1 -1
- package/src/shade/device/graph/BufferResourceDescriptor.js +196 -193
- package/src/shade/device/graph/TextureResourceDescriptor.d.ts.map +1 -1
- package/src/shade/device/graph/TextureResourceDescriptor.js +178 -173
- package/src/shade/device/shade_device_floor_unmet.d.ts +13 -0
- package/src/shade/device/shade_device_floor_unmet.d.ts.map +1 -0
- package/src/shade/device/shade_device_floor_unmet.js +32 -0
- package/src/shade/device/timing/profile/sgpt_read_header.js +1 -1
- package/src/shade/device/timing/profile/sgpt_read_records.js +1 -1
- package/src/shade/device/timing/profile/sgpt_write_header.js +1 -1
- package/src/shade/device/timing/profile/sgpt_write_record.js +1 -1
- package/src/shade/renderer/Renderer.d.ts +2 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +29 -55
- package/src/shade/renderer/binding/BufferBinding.js +2 -2
- package/src/shade/renderer/buffer/GPUBufferAllocator.d.ts.map +1 -1
- package/src/shade/renderer/buffer/GPUBufferAllocator.js +9 -0
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts +21 -12
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts.map +1 -1
- package/src/shade/renderer/buffer/buffer_pool_ops.js +18 -19
- package/src/shade/renderer/camera/Camera.js +2 -2
- package/src/shade/renderer/geometry/Attribute.js +2 -2
- package/src/shade/renderer/geometry/Geometry.js +2 -2
- package/src/shade/renderer/geometry/geometry_deduplicate_vertices.js +2 -2
- package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +2 -2
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
- package/src/shade/renderer/gpu_primitive/test/gpu_test.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/test/gpu_test.js +8 -11
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/StandardShadeMaterial.d.ts.map +1 -1
- package/src/shade/renderer/material/StandardShadeMaterial.js +13 -8
- package/src/shade/renderer/pool/TransientResourcePool.d.ts +24 -0
- package/src/shade/renderer/pool/TransientResourcePool.d.ts.map +1 -1
- package/src/shade/renderer/pool/TransientResourcePool.js +41 -10
- package/src/shade/renderer/scene/optimization/geometry/internal/triangle_fingerprint_stream.d.ts.map +1 -1
- package/src/shade/renderer/scene/optimization/geometry/internal/triangle_fingerprint_stream.js +14 -5
- package/src/shade/renderer/scene/optimization/sampler2d_from_image_bitmap.js +1 -1
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +18 -2
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +230 -218
- package/src/shade/renderer/shader/type/WGSLStructField.js +2 -2
- package/src/shade/renderer/shader/type/WebGPUArray.js +2 -2
- package/src/shade/renderer/shader/type/WebGPUStruct.d.ts.map +1 -1
- package/src/shade/renderer/shader/type/WebGPUStruct.js +9 -6
- package/src/shade/renderer/texture/ShadeTexture.d.ts.map +1 -1
- package/src/shade/renderer/texture/ShadeTexture.js +17 -10
- package/src/shade/renderer/texture/mipmaps/WebGPUMipmapGenerator.js +2 -2
- package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts +4 -4
- package/src/shade/renderer/water/surface/chunk_water_surface_sample.js +6 -6
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +46 -55
- package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts +3 -3
- package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.js +14 -4
- package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts +10 -1
- package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/chunk_water_particle.js +82 -40
- package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts +4 -1
- package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.js +8 -4
- package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts +98 -86
- package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/shader_water_particles.js +440 -298
- package/src/view/common/HTMLElementCacheKey.d.ts.map +1 -1
- package/src/view/common/HTMLElementCacheKey.js +4 -3
- package/src/view/graphics/GraphicsContextFailureView.d.ts +1 -2
- package/src/view/graphics/GraphicsContextFailureView.d.ts.map +1 -1
- package/src/view/graphics/GraphicsContextFailureView.js +1 -2
- package/src/view/minimap/MinimapMarker.js +2 -2
- package/src/engine/network/transport/Channel.js +0 -336
- package/src/engine/network/transport/ReliableCommandPipeline.js +0 -335
- package/src/engine/network/transport/fragments/FragmentAssembler.js +0 -350
- package/src/engine/network/transport/fragments/FragmentRetention.js +0 -191
- package/src/engine/network/transport/fragments/fragment_send.js +0 -157
- package/src/engine/network/transport/fragments/packet_size.js +0 -107
|
@@ -833,6 +833,12 @@ export class GPUParticleEmitterSystem extends System {
|
|
|
833
833
|
* to. Layout and program are shared by reference, never copied — two entities of one effect belong
|
|
834
834
|
* on one program id in the heap.
|
|
835
835
|
*
|
|
836
|
+
* Every field is compared by name, and that is load-bearing rather than style. Through a shared
|
|
837
|
+
* `assign(target, field, value)` the one `target[field]` access saw all thirteen names, went
|
|
838
|
+
* megamorphic, and read numbers back boxed, while the call boxed the value it was handed: 228 B and
|
|
839
|
+
* ~120 ns per emitter per call, against nothing and ~9 ns written out like this
|
|
840
|
+
* (`GPUParticleEmitterSystem.allocation.spec.js`). This runs for every live emitter twice a frame.
|
|
841
|
+
*
|
|
836
842
|
* @param {ParticleEmitter} emitter
|
|
837
843
|
* @param {ParticleEffect} effect
|
|
838
844
|
* @returns {boolean} whether the emitter differs from what it held before
|
|
@@ -840,45 +846,82 @@ export class GPUParticleEmitterSystem extends System {
|
|
|
840
846
|
export function apply_particle_effect(emitter, effect) {
|
|
841
847
|
let changed = false;
|
|
842
848
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
changed = assign(emitter, "spawn_rate", effect.effective_spawn_rate) || changed;
|
|
848
|
-
changed = assign(emitter, "prewarm", effect.prewarm) || changed;
|
|
849
|
-
changed = assign(emitter, "flags", effect.flags) || changed;
|
|
850
|
-
changed = assign(emitter, "render_position", effect.render_position) || changed;
|
|
851
|
-
changed = assign(emitter, "render_size", effect.render_size) || changed;
|
|
852
|
-
changed = assign(emitter, "render_color", effect.render_color) || changed;
|
|
853
|
-
changed = assign(emitter, "render_rotation", effect.render_rotation) || changed;
|
|
854
|
-
changed = assign(emitter, "render_frame", effect.render_frame) || changed;
|
|
855
|
-
changed = assign(emitter, "render_velocity", effect.render_velocity) || changed;
|
|
849
|
+
if (emitter.layout !== effect.layout) {
|
|
850
|
+
emitter.layout = effect.layout;
|
|
851
|
+
changed = true;
|
|
852
|
+
}
|
|
856
853
|
|
|
857
|
-
|
|
854
|
+
if (emitter.program !== effect.program) {
|
|
855
|
+
emitter.program = effect.program;
|
|
856
|
+
changed = true;
|
|
857
|
+
}
|
|
858
858
|
|
|
859
|
-
if (
|
|
860
|
-
|
|
859
|
+
if (emitter.texture !== effect.texture) {
|
|
860
|
+
emitter.texture = effect.texture;
|
|
861
|
+
changed = true;
|
|
862
|
+
}
|
|
861
863
|
|
|
864
|
+
if (emitter.seed !== effect.seed) {
|
|
865
|
+
emitter.seed = effect.seed;
|
|
862
866
|
changed = true;
|
|
863
867
|
}
|
|
864
868
|
|
|
865
|
-
|
|
866
|
-
}
|
|
869
|
+
const spawn_rate = effect.effective_spawn_rate;
|
|
867
870
|
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
return false;
|
|
871
|
+
if (emitter.spawn_rate !== spawn_rate) {
|
|
872
|
+
emitter.spawn_rate = spawn_rate;
|
|
873
|
+
changed = true;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
if (emitter.prewarm !== effect.prewarm) {
|
|
877
|
+
emitter.prewarm = effect.prewarm;
|
|
878
|
+
changed = true;
|
|
877
879
|
}
|
|
878
880
|
|
|
879
|
-
|
|
881
|
+
if (emitter.flags !== effect.flags) {
|
|
882
|
+
emitter.flags = effect.flags;
|
|
883
|
+
changed = true;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
if (emitter.render_position !== effect.render_position) {
|
|
887
|
+
emitter.render_position = effect.render_position;
|
|
888
|
+
changed = true;
|
|
889
|
+
}
|
|
880
890
|
|
|
881
|
-
|
|
891
|
+
if (emitter.render_size !== effect.render_size) {
|
|
892
|
+
emitter.render_size = effect.render_size;
|
|
893
|
+
changed = true;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (emitter.render_color !== effect.render_color) {
|
|
897
|
+
emitter.render_color = effect.render_color;
|
|
898
|
+
changed = true;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
if (emitter.render_rotation !== effect.render_rotation) {
|
|
902
|
+
emitter.render_rotation = effect.render_rotation;
|
|
903
|
+
changed = true;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
if (emitter.render_frame !== effect.render_frame) {
|
|
907
|
+
emitter.render_frame = effect.render_frame;
|
|
908
|
+
changed = true;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
if (emitter.render_velocity !== effect.render_velocity) {
|
|
912
|
+
emitter.render_velocity = effect.render_velocity;
|
|
913
|
+
changed = true;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const flipbook = emitter.flipbook;
|
|
917
|
+
|
|
918
|
+
if (flipbook[0] !== effect.flipbook[0] || flipbook[1] !== effect.flipbook[1]) {
|
|
919
|
+
flipbook.set(effect.flipbook);
|
|
920
|
+
|
|
921
|
+
changed = true;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
return changed;
|
|
882
925
|
}
|
|
883
926
|
|
|
884
927
|
class GPUParticleAtlasExtension extends RenderExtension {
|
|
@@ -1,204 +1,204 @@
|
|
|
1
|
-
import { assert } from "../../core/assert.js";
|
|
2
|
-
import {
|
|
3
|
-
import { rgb_to_luminance } from "../../core/color/rgb_to_luminance.js";
|
|
4
|
-
import { computeHashFloat } from "../../core/primitives/numbers/computeHashFloat.js";
|
|
5
|
-
import {
|
|
6
|
-
VOLUMETRIC_PARTICLE_SPEC_FOG,
|
|
7
|
-
VolumetricsParticleSpec
|
|
8
|
-
} from "../../shade/renderer/volumetrics/ParticipatingMediaVolume.js";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Particles per cubic metre of dense fog, which is what a medium is until it is told otherwise.
|
|
12
|
-
* @type {number}
|
|
13
|
-
*/
|
|
14
|
-
const DEFAULT_DENSITY = 3e7;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @type {number}
|
|
18
|
-
*/
|
|
19
|
-
const DEFAULT_FADE_DISTANCE = 0.1;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* A box of fog, smoke, dust or cloud that an entity carries around.
|
|
23
|
-
*
|
|
24
|
-
* **What is in here is the medium; the {@link Transform} beside it is the box.** Shade's
|
|
25
|
-
* {@link ParticipatingMediaVolume} is a unit cube centred on the origin, posed by a transform — so
|
|
26
|
-
* position, size and orientation are already an ECS concept and there is nothing to restate. Which
|
|
27
|
-
* is also why this component does nothing on its own: {@link ParticipatingMediaSystem} links it
|
|
28
|
-
* against a `Transform` and only that pair becomes a volume.
|
|
29
|
-
*
|
|
30
|
-
* **Three numbers, in two different currencies.** {@link particle_spec} is what a single particle
|
|
31
|
-
* does to light — a Mie solution, physical and reusable — and {@link density} is how many of them
|
|
32
|
-
* there are per cubic metre. The pair is what makes smoke and fog different things rather than the
|
|
33
|
-
* same fog at two strengths. Authoring in raw density means knowing the cross-sections, so
|
|
34
|
-
* {@link target_extinction} exists to author the other way round: say how much light the medium
|
|
35
|
-
* should swallow and let the particle decide the count.
|
|
36
|
-
*
|
|
37
|
-
* @see ParticipatingMediaSystem what turns this into something the renderer draws
|
|
38
|
-
* @see ParticipatingMediaVolume the renderer's own object
|
|
39
|
-
*/
|
|
40
|
-
export class ParticipatingMedia {
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Particles per cubic metre.
|
|
44
|
-
*
|
|
45
|
-
* Physically a count, so the numbers are large — the default is dense fog — and the useful range
|
|
46
|
-
* depends entirely on {@link particle_spec}: a cloud droplet blocks far more light than a haze
|
|
47
|
-
* particle, so the same count of them is a very different medium.
|
|
48
|
-
*
|
|
49
|
-
* @type {number}
|
|
50
|
-
*/
|
|
51
|
-
density = DEFAULT_DENSITY;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* What one particle of this medium does to light.
|
|
55
|
-
*
|
|
56
|
-
* Defaults to fog. The generated `MIE_PARTICLES_STANDARD_PRECOMPUTED` library is where the
|
|
57
|
-
* physically meaningful values live — `VolumetricsParticleSpec.fromMeep` converts an entry of it
|
|
58
|
-
* into one of these.
|
|
59
|
-
*
|
|
60
|
-
* @type {VolumetricsParticleSpec}
|
|
61
|
-
*/
|
|
62
|
-
particle_spec = VolumetricsParticleSpec.fromJSON(VOLUMETRIC_PARTICLE_SPEC_FOG);
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* How far in from the box's faces the medium fades out, in metres.
|
|
66
|
-
*
|
|
67
|
-
* **World-space, and deliberately not scaled by the transform**, so a 0.5 here is half a metre
|
|
68
|
-
* of softness whether the volume is a metre across or a hundred. Zero gives the box hard edges,
|
|
69
|
-
* which is visible as a straight line across the screen wherever the box crosses the view.
|
|
70
|
-
*
|
|
71
|
-
* @type {number}
|
|
72
|
-
*/
|
|
73
|
-
fade_distance = DEFAULT_FADE_DISTANCE;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* The medium's extinction per metre, which is {@link density} expressed in what it does rather
|
|
77
|
-
* than in how many particles it took.
|
|
78
|
-
*
|
|
79
|
-
* The point of it is that it is comparable across particles: a smoke volume and a fog volume set
|
|
80
|
-
* to the same target extinction swallow the same amount of light, while the same *density* in
|
|
81
|
-
* both would differ by orders of magnitude.
|
|
82
|
-
*
|
|
83
|
-
* **Derived, not stored** — writing it sets {@link density}, and changing `particle_spec`
|
|
84
|
-
* afterwards therefore changes what reading it back gives. The density is what survives a save.
|
|
85
|
-
*
|
|
86
|
-
* @returns {number}
|
|
87
|
-
*/
|
|
88
|
-
get target_extinction() {
|
|
89
|
-
return this.density * rgb_to_luminance(...this.particle_spec.extinction);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* @param {number} value
|
|
94
|
-
*/
|
|
95
|
-
set target_extinction(value) {
|
|
96
|
-
assert.isNumber(value, 'target_extinction');
|
|
97
|
-
assert.isFinite(value, 'target_extinction');
|
|
98
|
-
|
|
99
|
-
const density = value / rgb_to_luminance(...this.particle_spec.extinction);
|
|
100
|
-
|
|
101
|
-
/*
|
|
102
|
-
Catches the one way this goes wrong: a particle spec that extinguishes nothing. A default-
|
|
103
|
-
constructed `VolumetricsParticleSpec` has zero cross-sections, and asking such a medium to
|
|
104
|
-
reach any extinction at all needs infinitely many of its particles. Rejecting it here names
|
|
105
|
-
the mistake; letting it through puts an `Infinity` in the GPU table, where it becomes a
|
|
106
|
-
screenful of NaN several passes later.
|
|
107
|
-
*/
|
|
108
|
-
assert.isFinite(density, 'the density this target_extinction implies (the particle spec extinguishes nothing)');
|
|
109
|
-
|
|
110
|
-
this.density = density;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @param {*} json
|
|
115
|
-
* @returns {ParticipatingMedia}
|
|
116
|
-
*/
|
|
117
|
-
static fromJSON(json) {
|
|
118
|
-
const r = new ParticipatingMedia();
|
|
119
|
-
|
|
120
|
-
r.fromJSON(json);
|
|
121
|
-
|
|
122
|
-
return r;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
toJSON() {
|
|
126
|
-
const spec = this.particle_spec;
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
density: this.density,
|
|
130
|
-
fade_distance: this.fade_distance,
|
|
131
|
-
particle_spec: {
|
|
132
|
-
scattering: spec.scattering.slice(),
|
|
133
|
-
extinction: spec.extinction.slice(),
|
|
134
|
-
radius: spec.radius,
|
|
135
|
-
g: spec.g
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {Object} options
|
|
142
|
-
* @param {number} [options.density]
|
|
143
|
-
* @param {number} [options.fade_distance]
|
|
144
|
-
* @param {object} [options.particle_spec] omitted resets the medium to fog rather than leaving whatever
|
|
145
|
-
* the component already held — a load has to determine the whole component, or an instance being
|
|
146
|
-
* reused would carry the previous level's particle into the next one
|
|
147
|
-
*/
|
|
148
|
-
fromJSON({
|
|
149
|
-
density = DEFAULT_DENSITY,
|
|
150
|
-
fade_distance = DEFAULT_FADE_DISTANCE,
|
|
151
|
-
particle_spec
|
|
152
|
-
}) {
|
|
153
|
-
assert.isNumber(density, 'density');
|
|
154
|
-
assert.isFinite(density, 'density');
|
|
155
|
-
assert.greaterThanOrEqual(density, 0, 'density must not be negative');
|
|
156
|
-
|
|
157
|
-
assert.isNumber(fade_distance, 'fade_distance');
|
|
158
|
-
assert.isFinite(fade_distance, 'fade_distance');
|
|
159
|
-
assert.greaterThanOrEqual(fade_distance, 0, 'fade_distance must not be negative');
|
|
160
|
-
|
|
161
|
-
this.density = density;
|
|
162
|
-
this.fade_distance = fade_distance;
|
|
163
|
-
|
|
164
|
-
if (particle_spec === undefined) {
|
|
165
|
-
this.particle_spec.copy(VOLUMETRIC_PARTICLE_SPEC_FOG);
|
|
166
|
-
} else {
|
|
167
|
-
this.particle_spec.fromJSON(particle_spec);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* **The cross-sections and the radius are left out of this on purpose.** They run to 1e-16 and
|
|
173
|
-
* 1e-6, and {@link computeHashFloat} collapses anything that small to zero, so mixing them in
|
|
174
|
-
* would cost a multiply and buy no dispersion at all. A hash is allowed to collide;
|
|
175
|
-
* {@link equals} is the exact one.
|
|
176
|
-
*
|
|
177
|
-
* @returns {number}
|
|
178
|
-
*/
|
|
179
|
-
hash() {
|
|
180
|
-
const spec = this.particle_spec;
|
|
181
|
-
|
|
182
|
-
return
|
|
183
|
-
computeHashFloat(this.density),
|
|
184
|
-
computeHashFloat(this.fade_distance),
|
|
185
|
-
computeHashFloat(spec.g)
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* @param {ParticipatingMedia} other
|
|
191
|
-
* @returns {boolean}
|
|
192
|
-
*/
|
|
193
|
-
equals(other) {
|
|
194
|
-
return this.density === other.density
|
|
195
|
-
&& this.fade_distance === other.fade_distance
|
|
196
|
-
&& this.particle_spec.equals(other.particle_spec);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* @readonly
|
|
202
|
-
* @type {string}
|
|
203
|
-
*/
|
|
204
|
-
ParticipatingMedia.typeName = "ParticipatingMedia";
|
|
1
|
+
import { assert } from "../../core/assert.js";
|
|
2
|
+
import { hash_mix3 } from "../../core/math/hash/hash_mix3.js";
|
|
3
|
+
import { rgb_to_luminance } from "../../core/color/rgb_to_luminance.js";
|
|
4
|
+
import { computeHashFloat } from "../../core/primitives/numbers/computeHashFloat.js";
|
|
5
|
+
import {
|
|
6
|
+
VOLUMETRIC_PARTICLE_SPEC_FOG,
|
|
7
|
+
VolumetricsParticleSpec
|
|
8
|
+
} from "../../shade/renderer/volumetrics/ParticipatingMediaVolume.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Particles per cubic metre of dense fog, which is what a medium is until it is told otherwise.
|
|
12
|
+
* @type {number}
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_DENSITY = 3e7;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @type {number}
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_FADE_DISTANCE = 0.1;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A box of fog, smoke, dust or cloud that an entity carries around.
|
|
23
|
+
*
|
|
24
|
+
* **What is in here is the medium; the {@link Transform} beside it is the box.** Shade's
|
|
25
|
+
* {@link ParticipatingMediaVolume} is a unit cube centred on the origin, posed by a transform — so
|
|
26
|
+
* position, size and orientation are already an ECS concept and there is nothing to restate. Which
|
|
27
|
+
* is also why this component does nothing on its own: {@link ParticipatingMediaSystem} links it
|
|
28
|
+
* against a `Transform` and only that pair becomes a volume.
|
|
29
|
+
*
|
|
30
|
+
* **Three numbers, in two different currencies.** {@link particle_spec} is what a single particle
|
|
31
|
+
* does to light — a Mie solution, physical and reusable — and {@link density} is how many of them
|
|
32
|
+
* there are per cubic metre. The pair is what makes smoke and fog different things rather than the
|
|
33
|
+
* same fog at two strengths. Authoring in raw density means knowing the cross-sections, so
|
|
34
|
+
* {@link target_extinction} exists to author the other way round: say how much light the medium
|
|
35
|
+
* should swallow and let the particle decide the count.
|
|
36
|
+
*
|
|
37
|
+
* @see ParticipatingMediaSystem what turns this into something the renderer draws
|
|
38
|
+
* @see ParticipatingMediaVolume the renderer's own object
|
|
39
|
+
*/
|
|
40
|
+
export class ParticipatingMedia {
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Particles per cubic metre.
|
|
44
|
+
*
|
|
45
|
+
* Physically a count, so the numbers are large — the default is dense fog — and the useful range
|
|
46
|
+
* depends entirely on {@link particle_spec}: a cloud droplet blocks far more light than a haze
|
|
47
|
+
* particle, so the same count of them is a very different medium.
|
|
48
|
+
*
|
|
49
|
+
* @type {number}
|
|
50
|
+
*/
|
|
51
|
+
density = DEFAULT_DENSITY;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* What one particle of this medium does to light.
|
|
55
|
+
*
|
|
56
|
+
* Defaults to fog. The generated `MIE_PARTICLES_STANDARD_PRECOMPUTED` library is where the
|
|
57
|
+
* physically meaningful values live — `VolumetricsParticleSpec.fromMeep` converts an entry of it
|
|
58
|
+
* into one of these.
|
|
59
|
+
*
|
|
60
|
+
* @type {VolumetricsParticleSpec}
|
|
61
|
+
*/
|
|
62
|
+
particle_spec = VolumetricsParticleSpec.fromJSON(VOLUMETRIC_PARTICLE_SPEC_FOG);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* How far in from the box's faces the medium fades out, in metres.
|
|
66
|
+
*
|
|
67
|
+
* **World-space, and deliberately not scaled by the transform**, so a 0.5 here is half a metre
|
|
68
|
+
* of softness whether the volume is a metre across or a hundred. Zero gives the box hard edges,
|
|
69
|
+
* which is visible as a straight line across the screen wherever the box crosses the view.
|
|
70
|
+
*
|
|
71
|
+
* @type {number}
|
|
72
|
+
*/
|
|
73
|
+
fade_distance = DEFAULT_FADE_DISTANCE;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The medium's extinction per metre, which is {@link density} expressed in what it does rather
|
|
77
|
+
* than in how many particles it took.
|
|
78
|
+
*
|
|
79
|
+
* The point of it is that it is comparable across particles: a smoke volume and a fog volume set
|
|
80
|
+
* to the same target extinction swallow the same amount of light, while the same *density* in
|
|
81
|
+
* both would differ by orders of magnitude.
|
|
82
|
+
*
|
|
83
|
+
* **Derived, not stored** — writing it sets {@link density}, and changing `particle_spec`
|
|
84
|
+
* afterwards therefore changes what reading it back gives. The density is what survives a save.
|
|
85
|
+
*
|
|
86
|
+
* @returns {number}
|
|
87
|
+
*/
|
|
88
|
+
get target_extinction() {
|
|
89
|
+
return this.density * rgb_to_luminance(...this.particle_spec.extinction);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param {number} value
|
|
94
|
+
*/
|
|
95
|
+
set target_extinction(value) {
|
|
96
|
+
assert.isNumber(value, 'target_extinction');
|
|
97
|
+
assert.isFinite(value, 'target_extinction');
|
|
98
|
+
|
|
99
|
+
const density = value / rgb_to_luminance(...this.particle_spec.extinction);
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
Catches the one way this goes wrong: a particle spec that extinguishes nothing. A default-
|
|
103
|
+
constructed `VolumetricsParticleSpec` has zero cross-sections, and asking such a medium to
|
|
104
|
+
reach any extinction at all needs infinitely many of its particles. Rejecting it here names
|
|
105
|
+
the mistake; letting it through puts an `Infinity` in the GPU table, where it becomes a
|
|
106
|
+
screenful of NaN several passes later.
|
|
107
|
+
*/
|
|
108
|
+
assert.isFinite(density, 'the density this target_extinction implies (the particle spec extinguishes nothing)');
|
|
109
|
+
|
|
110
|
+
this.density = density;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {*} json
|
|
115
|
+
* @returns {ParticipatingMedia}
|
|
116
|
+
*/
|
|
117
|
+
static fromJSON(json) {
|
|
118
|
+
const r = new ParticipatingMedia();
|
|
119
|
+
|
|
120
|
+
r.fromJSON(json);
|
|
121
|
+
|
|
122
|
+
return r;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
toJSON() {
|
|
126
|
+
const spec = this.particle_spec;
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
density: this.density,
|
|
130
|
+
fade_distance: this.fade_distance,
|
|
131
|
+
particle_spec: {
|
|
132
|
+
scattering: spec.scattering.slice(),
|
|
133
|
+
extinction: spec.extinction.slice(),
|
|
134
|
+
radius: spec.radius,
|
|
135
|
+
g: spec.g
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {Object} options
|
|
142
|
+
* @param {number} [options.density]
|
|
143
|
+
* @param {number} [options.fade_distance]
|
|
144
|
+
* @param {object} [options.particle_spec] omitted resets the medium to fog rather than leaving whatever
|
|
145
|
+
* the component already held — a load has to determine the whole component, or an instance being
|
|
146
|
+
* reused would carry the previous level's particle into the next one
|
|
147
|
+
*/
|
|
148
|
+
fromJSON({
|
|
149
|
+
density = DEFAULT_DENSITY,
|
|
150
|
+
fade_distance = DEFAULT_FADE_DISTANCE,
|
|
151
|
+
particle_spec
|
|
152
|
+
}) {
|
|
153
|
+
assert.isNumber(density, 'density');
|
|
154
|
+
assert.isFinite(density, 'density');
|
|
155
|
+
assert.greaterThanOrEqual(density, 0, 'density must not be negative');
|
|
156
|
+
|
|
157
|
+
assert.isNumber(fade_distance, 'fade_distance');
|
|
158
|
+
assert.isFinite(fade_distance, 'fade_distance');
|
|
159
|
+
assert.greaterThanOrEqual(fade_distance, 0, 'fade_distance must not be negative');
|
|
160
|
+
|
|
161
|
+
this.density = density;
|
|
162
|
+
this.fade_distance = fade_distance;
|
|
163
|
+
|
|
164
|
+
if (particle_spec === undefined) {
|
|
165
|
+
this.particle_spec.copy(VOLUMETRIC_PARTICLE_SPEC_FOG);
|
|
166
|
+
} else {
|
|
167
|
+
this.particle_spec.fromJSON(particle_spec);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* **The cross-sections and the radius are left out of this on purpose.** They run to 1e-16 and
|
|
173
|
+
* 1e-6, and {@link computeHashFloat} collapses anything that small to zero, so mixing them in
|
|
174
|
+
* would cost a multiply and buy no dispersion at all. A hash is allowed to collide;
|
|
175
|
+
* {@link equals} is the exact one.
|
|
176
|
+
*
|
|
177
|
+
* @returns {number}
|
|
178
|
+
*/
|
|
179
|
+
hash() {
|
|
180
|
+
const spec = this.particle_spec;
|
|
181
|
+
|
|
182
|
+
return hash_mix3(
|
|
183
|
+
computeHashFloat(this.density),
|
|
184
|
+
computeHashFloat(this.fade_distance),
|
|
185
|
+
computeHashFloat(spec.g)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @param {ParticipatingMedia} other
|
|
191
|
+
* @returns {boolean}
|
|
192
|
+
*/
|
|
193
|
+
equals(other) {
|
|
194
|
+
return this.density === other.density
|
|
195
|
+
&& this.fade_distance === other.fade_distance
|
|
196
|
+
&& this.particle_spec.equals(other.particle_spec);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @readonly
|
|
202
|
+
* @type {string}
|
|
203
|
+
*/
|
|
204
|
+
ParticipatingMedia.typeName = "ParticipatingMedia";
|
|
@@ -23,6 +23,11 @@
|
|
|
23
23
|
* clip, take the component off and put another on, which the drivers see as their entity leaving
|
|
24
24
|
* and coming back.
|
|
25
25
|
*
|
|
26
|
+
* **The entities it keys go no sooner than it does.** While it is on, the drivers hold a row for
|
|
27
|
+
* every entity a channel keys, as a skin holds its joints'. Removing one of them means taking this
|
|
28
|
+
* off before the next frame — `prefab_instance_destroy` removes the entities and then the clips, in
|
|
29
|
+
* one step — or the scene is left holding the row of an entity that is gone.
|
|
30
|
+
*
|
|
26
31
|
* **Not saved**, for the reason `MeshSkin` is not: the channels key entities that whatever builds
|
|
27
32
|
* the rig creates, and the curves are asset data. A load rebuilds them the way it rebuilds the rig.
|
|
28
33
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimationClips.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/animation/AnimationClips.js"],"names":[],"mappings":"AAEA;;GAEG;AAEH
|
|
1
|
+
{"version":3,"file":"AnimationClips.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/animation/AnimationClips.js"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH;IASI;;;OAGG;IACH,mBAHW,kBAAkB,EAAE,GAClB,cAAc,CAc1B;IAxBD;;;;;OAKG;IACH,OAFU,kBAAkB,EAAE,CAEnB;IAqBf;;;OAGG;IACH,2BAFU,OAAO,CAEwB;CANxC;;kBAUS,MAAM;sBAMN,OAAO;;iCA9EJ,OAAO,yDAAyD,EAAE,kBAAkB"}
|
|
@@ -26,6 +26,11 @@ import { assert } from "../../../core/assert.js";
|
|
|
26
26
|
* clip, take the component off and put another on, which the drivers see as their entity leaving
|
|
27
27
|
* and coming back.
|
|
28
28
|
*
|
|
29
|
+
* **The entities it keys go no sooner than it does.** While it is on, the drivers hold a row for
|
|
30
|
+
* every entity a channel keys, as a skin holds its joints'. Removing one of them means taking this
|
|
31
|
+
* off before the next frame — `prefab_instance_destroy` removes the entities and then the clips, in
|
|
32
|
+
* one step — or the scene is left holding the row of an entity that is gone.
|
|
33
|
+
*
|
|
29
34
|
* **Not saved**, for the reason `MeshSkin` is not: the channels key entities that whatever builds
|
|
30
35
|
* the rig creates, and the curves are asset data. A load rebuilds them the way it rebuilds the rig.
|
|
31
36
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../../core/assert.js";
|
|
2
|
-
import {
|
|
2
|
+
import { hash_mix2 } from "../../../core/math/hash/hash_mix2.js";
|
|
3
3
|
import { computeIntegerArrayHash } from "../../../core/collection/array/computeIntegerArrayHash.js";
|
|
4
4
|
import { isArrayEqualStrict } from "../../../core/collection/array/isArrayEqualStrict.js";
|
|
5
5
|
import Vector2 from '../../../core/geom/Vector2.js';
|
|
@@ -235,7 +235,7 @@ class GridObstacle {
|
|
|
235
235
|
* @returns {number}
|
|
236
236
|
*/
|
|
237
237
|
hash() {
|
|
238
|
-
return
|
|
238
|
+
return hash_mix2(
|
|
239
239
|
this.size.hash(),
|
|
240
240
|
computeIntegerArrayHash(this.data, 0, this.data.length)
|
|
241
241
|
);
|
|
@@ -6,6 +6,7 @@ export default KeyboardDevice;
|
|
|
6
6
|
* the key remains pressed and the eventual physical release is picked up at the window level.
|
|
7
7
|
* NOTE: when the window itself loses focus (e.g. switching to another application), key releases can no longer
|
|
8
8
|
* be observed at all, so any "pressed" keys are forcibly released with the appropriate signal.
|
|
9
|
+
* A key still held when focus returns is pressed again by its next automatic repetition.
|
|
9
10
|
*
|
|
10
11
|
* @author Alex Goldring
|
|
11
12
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyboardDevice.d.ts","sourceRoot":"","sources":["../../../../../src/engine/input/devices/KeyboardDevice.js"],"names":[],"mappings":";AAYA
|
|
1
|
+
{"version":3,"file":"KeyboardDevice.d.ts","sourceRoot":"","sources":["../../../../../src/engine/input/devices/KeyboardDevice.js"],"names":[],"mappings":";AAYA;;;;;;;;;;;GAWG;AACH;IA4BI;;;OAGG;IACH,wBAHW,WAAW,GAAC,OAAO,EAgC7B;IA3DD;;OAEG;IACH;QACI;;;WAGG;;QAEH;;;WAGG;;MAEL;IAEF;;;;;;;OAOG;IACH,mBAAU;IAkBN;;;OAGG;IACH,YAFU,WAAW,CAEO;IA2HhC;;;OAGG;IACH,SAFa,IAAI,CAWhB;IAED;;;OAGG;IACH,QAFa,IAAI,CAUhB;;CAEJ"}
|
|
@@ -17,6 +17,7 @@ const codeToKeyNameMap = [];
|
|
|
17
17
|
* the key remains pressed and the eventual physical release is picked up at the window level.
|
|
18
18
|
* NOTE: when the window itself loses focus (e.g. switching to another application), key releases can no longer
|
|
19
19
|
* be observed at all, so any "pressed" keys are forcibly released with the appropriate signal.
|
|
20
|
+
* A key still held when focus returns is pressed again by its next automatic repetition.
|
|
20
21
|
*
|
|
21
22
|
* @author Alex Goldring
|
|
22
23
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -90,14 +91,14 @@ class KeyboardDevice {
|
|
|
90
91
|
* @private
|
|
91
92
|
*/
|
|
92
93
|
#handlerKeyDown = (event) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
// Automatic repetition is not a new press, so the raw signal skips it,
|
|
95
|
+
// see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat
|
|
96
|
+
// It is still proof the key is held: a key released by a window blur, or whose original key-down
|
|
97
|
+
// never reached the element, is pressed again here. Pressing is idempotent, so a key already held is unaffected.
|
|
98
|
+
if (!event.repeat) {
|
|
99
|
+
this.on.down.send1(event);
|
|
97
100
|
}
|
|
98
101
|
|
|
99
|
-
this.on.down.send1(event);
|
|
100
|
-
|
|
101
102
|
let should_prevent_default = false;
|
|
102
103
|
|
|
103
104
|
//hook up dispatch handler for individual keys
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../../../core/assert.js";
|
|
2
|
-
import {
|
|
2
|
+
import { hash_mix2 } from "../../../../core/math/hash/hash_mix2.js";
|
|
3
3
|
import { invokeObjectEquals } from "../../../../core/model/object/invokeObjectEquals.js";
|
|
4
4
|
import { invokeObjectHash } from "../../../../core/model/object/invokeObjectHash.js";
|
|
5
5
|
import { computeHashFloat } from "../../../../core/primitives/numbers/computeHashFloat.js";
|
|
@@ -66,7 +66,7 @@ export class WeightedElement {
|
|
|
66
66
|
* @return {number}
|
|
67
67
|
*/
|
|
68
68
|
hash() {
|
|
69
|
-
return
|
|
69
|
+
return hash_mix2(
|
|
70
70
|
computeHashFloat(this.weight),
|
|
71
71
|
invokeObjectHash(this.data)
|
|
72
72
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hash_mix2 } from "../../core/math/hash/hash_mix2.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Sentinel for {@link Interpolated#key} before assignment. The
|
|
@@ -114,7 +114,7 @@ export class Interpolated {
|
|
|
114
114
|
let h = this.sourceId | 0;
|
|
115
115
|
const ips = this.interpolands;
|
|
116
116
|
for (let i = 0; i < ips.length; i++) {
|
|
117
|
-
h =
|
|
117
|
+
h = hash_mix2(h, ips[i].type_id | 0);
|
|
118
118
|
}
|
|
119
119
|
return h;
|
|
120
120
|
}
|