@woosh/meep-engine 2.168.0 → 2.169.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/README.md +2 -2
- package/build/bundle-worker-image-decoder.js +1 -1
- package/package.json +1 -1
- package/src/REVIEW_2026_08_06/adv-core.md +511 -0
- package/src/REVIEW_2026_08_06/adv-gfx.md +480 -0
- package/src/REVIEW_2026_08_06/adv-view.md +446 -0
- package/src/REVIEW_2026_08_06/api-core.md +296 -0
- package/src/REVIEW_2026_08_06/api-engine.md +195 -0
- package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -0
- package/src/REVIEW_2026_08_06/core-binary.md +348 -0
- package/src/REVIEW_2026_08_06/core-collection.md +376 -0
- package/src/REVIEW_2026_08_06/core-math.md +221 -0
- package/src/REVIEW_2026_08_06/core-process.md +266 -0
- package/src/REVIEW_2026_08_06/core-science.md +223 -0
- package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -0
- package/src/REVIEW_2026_08_06/engine-animation.md +167 -0
- package/src/REVIEW_2026_08_06/engine-asset.md +166 -0
- package/src/REVIEW_2026_08_06/engine-ecs.md +920 -0
- package/src/REVIEW_2026_08_06/engine-input.md +197 -0
- package/src/REVIEW_2026_08_06/engine-misc.md +248 -0
- package/src/REVIEW_2026_08_06/engine-terrain.md +52 -0
- package/src/REVIEW_2026_08_06/generation.md +176 -0
- package/src/REVIEW_2026_08_06/geom-2d.md +434 -0
- package/src/REVIEW_2026_08_06/geom-3d.md +117 -0
- package/src/REVIEW_2026_08_06/gfx-gi.md +143 -0
- package/src/REVIEW_2026_08_06/gfx-render.md +740 -0
- package/src/REVIEW_2026_08_06/gfx-texture.md +690 -0
- package/src/REVIEW_2026_08_06/prior-criticals.md +49 -0
- package/src/REVIEW_2026_08_06/prior-highs.md +138 -0
- package/src/REVIEW_2026_08_06/test-gaps.md +364 -0
- package/src/REVIEW_2026_08_06/view.md +667 -0
- package/src/REVIEW_2026_08_06.md +571 -0
- package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
- package/src/core/binary/BinaryBuffer.js +12 -1
- package/src/core/binary/BitImage2.d.ts +5 -1
- package/src/core/binary/BitImage2.d.ts.map +1 -1
- package/src/core/binary/BitImage2.js +5 -1
- package/src/core/bvh8/build/NodeProxy.d.ts.map +1 -1
- package/src/core/bvh8/build/NodeProxy.js +314 -308
- package/src/core/collection/list/List.d.ts +15 -0
- package/src/core/collection/list/List.d.ts.map +1 -1
- package/src/core/collection/list/List.js +34 -0
- package/src/core/collection/list/SortedListProjection.d.ts.map +1 -1
- package/src/core/collection/list/SortedListProjection.js +4 -1
- package/src/core/collection/map/BiMap.d.ts +25 -2
- package/src/core/collection/map/BiMap.d.ts.map +1 -1
- package/src/core/collection/map/BiMap.js +57 -3
- package/src/core/debug/matchers/IsAnything.d.ts.map +1 -1
- package/src/core/debug/matchers/IsAnything.js +5 -1
- package/src/core/events/signal/Signal.d.ts.map +1 -1
- package/src/core/events/signal/Signal.js +3 -1
- package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -0
- package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts +31 -0
- package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -0
- package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts +24 -2
- package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts.map +1 -1
- package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -34
- package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts +28 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts +40 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -0
- package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts +28 -0
- package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts.map +1 -0
- package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts +6 -3
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts.map +1 -1
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +26 -13
- package/src/core/geom/2d/triangle/tri2_signed_area.d.ts +17 -1
- package/src/core/geom/2d/triangle/tri2_signed_area.d.ts.map +1 -1
- package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -23
- package/src/core/geom/2d/v2_morton_encode.d.ts +20 -0
- package/src/core/geom/2d/v2_morton_encode.d.ts.map +1 -0
- package/src/core/geom/2d/v2_morton_encode.js +23 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts.map +1 -1
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +4 -1
- package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts +27 -0
- package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts.map +1 -0
- package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -0
- package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts +34 -0
- package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts.map +1 -0
- package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -0
- package/src/core/geom/3d/quaternion/quat3_multiply.d.ts +8 -2
- package/src/core/geom/3d/quaternion/quat3_multiply.d.ts.map +1 -1
- package/src/core/geom/3d/quaternion/quat3_multiply.js +8 -2
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.js +32 -2
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts +23 -6
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -124
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts +17 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts +20 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.js +40 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts +19 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.js +34 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts +22 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.js +37 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts +87 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -0
- package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts +32 -0
- package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts.map +1 -1
- package/src/core/geom/3d/triangle/tri3_compute_signed_volume.js +66 -7
- package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts +22 -1
- package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts.map +1 -1
- package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.js +83 -38
- package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -0
- package/src/core/geom/vec3/v3_cotangent.d.ts +6 -2
- package/src/core/geom/vec3/v3_cotangent.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_cotangent.js +6 -2
- package/src/core/geom/vec3/v3_cross.d.ts +6 -2
- package/src/core/geom/vec3/v3_cross.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_cross.js +6 -2
- package/src/core/geom/vec3/v3_multiply.d.ts +6 -2
- package/src/core/geom/vec3/v3_multiply.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_multiply.js +6 -2
- package/src/core/geom/vec3/v3_subtract.d.ts +6 -2
- package/src/core/geom/vec3/v3_subtract.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_subtract.js +6 -2
- package/src/core/localization/Localization.js +1 -1
- package/src/core/math/random/randomSeed.d.ts +13 -0
- package/src/core/math/random/randomSeed.d.ts.map +1 -0
- package/src/core/math/random/randomSeed.js +16 -0
- package/src/core/math/spline/spline3_hermite_apply_transform.d.ts +50 -0
- package/src/core/math/spline/spline3_hermite_apply_transform.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -0
- package/src/core/math/spline/spline3_hermite_reverse.d.ts +34 -0
- package/src/core/math/spline/spline3_hermite_reverse.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_reverse.js +49 -0
- package/src/core/math/statistics/hammersley_sequence.d.ts +17 -4
- package/src/core/math/statistics/hammersley_sequence.d.ts.map +1 -1
- package/src/core/math/statistics/hammersley_sequence.js +25 -16
- package/src/core/process/Future.d.ts.map +1 -1
- package/src/core/process/Future.js +12 -0
- package/src/core/process/PromiseWatcher.d.ts.map +1 -1
- package/src/core/process/PromiseWatcher.js +9 -2
- package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
- package/src/core/process/executor/ConcurrentExecutor.js +12 -2
- package/src/core/process/worker/WorkerProxy.d.ts.map +1 -1
- package/src/core/process/worker/WorkerProxy.js +5 -2
- package/src/core/process/worker/extractTransferables.d.ts.map +1 -1
- package/src/core/process/worker/extractTransferables.js +4 -1
- package/src/engine/Engine.d.ts +12 -12
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +149 -10
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +4 -1
- package/src/engine/asset/loaders/ArrayBufferLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/ArrayBufferLoader.js +7 -0
- package/src/engine/ecs/speaker/lines/sets/LineSetDescription.d.ts.map +1 -1
- package/src/engine/ecs/speaker/lines/sets/LineSetDescription.js +3 -1
- package/src/engine/ecs/terrain/ecs/TerrainSystem.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/TerrainSystem.js +4 -1
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts +29 -0
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +84 -23
- package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -0
- package/src/engine/graphics/GraphicsEngine.d.ts +56 -7
- package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics/GraphicsEngine.js +196 -24
- package/src/engine/graphics/context/WebGLContextFailureReason.d.ts +9 -0
- package/src/engine/graphics/context/WebGLContextFailureReason.d.ts.map +1 -0
- package/src/engine/graphics/context/WebGLContextFailureReason.js +17 -0
- package/src/engine/graphics/context/WebGLContextMonitor.d.ts +106 -0
- package/src/engine/graphics/context/WebGLContextMonitor.d.ts.map +1 -0
- package/src/engine/graphics/context/WebGLContextMonitor.js +341 -0
- package/src/engine/graphics/context/WebGLContextState.d.ts +14 -0
- package/src/engine/graphics/context/WebGLContextState.d.ts.map +1 -0
- package/src/engine/graphics/context/WebGLContextState.js +24 -0
- package/src/engine/graphics/context/testWebGLContextLoss.d.ts +2 -0
- package/src/engine/graphics/context/testWebGLContextLoss.d.ts.map +1 -0
- package/src/engine/graphics/context/testWebGLContextLoss.js +696 -0
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -32
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts +14 -0
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.js +41 -0
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +5 -0
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts +5 -1
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2D.js +15 -0
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +2 -1
- package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +4 -1
- package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3D.js +488 -476
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.js +280 -253
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +3 -2
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +3 -1
- package/src/engine/graphics/geometry/computeMeshSurfaceArea.js +1 -1
- package/src/engine/graphics/load_and_set_cubemap_v0.d.ts +5 -0
- package/src/engine/graphics/load_and_set_cubemap_v0.d.ts.map +1 -1
- package/src/engine/graphics/load_and_set_cubemap_v0.js +26 -21
- package/src/engine/graphics/particles/particular/group/ParticleGroup.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/group/ParticleGroup.js +19 -8
- package/src/engine/graphics/particles/particular/group/optimizeCommandQueue.js +1 -1
- package/src/engine/graphics/texture/atlas/AtlasLookupTexture.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/AtlasLookupTexture.js +10 -3
- package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.js +4 -1
- package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +11 -0
- package/src/engine/graphics/texture/cubemap/load_environment_map.d.ts.map +1 -1
- package/src/engine/graphics/texture/cubemap/load_environment_map.js +5 -2
- package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.js +26 -18
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts +15 -2
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.js +29 -3
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts +11 -1
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +158 -171
- package/src/engine/graphics/texture/sampler/sampler2d_paint.js +1 -1
- package/src/engine/graphics/texture/sampler/util/bitSet2Sampler2D.js +2 -2
- package/src/engine/input/ecs/util/TopDownCameraControllerHelper.d.ts.map +1 -1
- package/src/engine/input/ecs/util/TopDownCameraControllerHelper.js +10 -3
- package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts +14 -0
- package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts.map +1 -0
- package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.js +38 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +433 -425
- package/src/engine/physics/constraint/solve_constraints.d.ts +4 -1
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +38 -13
- package/src/engine/physics/contact/ManifoldStore.d.ts +15 -3
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
- package/src/engine/physics/contact/ManifoldStore.js +15 -3
- package/src/engine/physics/ecs/Joint.d.ts +7 -4
- package/src/engine/physics/ecs/Joint.d.ts.map +1 -1
- package/src/engine/physics/ecs/Joint.js +7 -4
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +14 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +16 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +15 -7
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/convex_convex_manifold.js +33 -10
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts +6 -2
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_concave.js +6 -2
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +6 -2
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_hit.js +6 -2
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +11 -4
- package/src/engine/save/storage/IndexedDBStorage.d.ts.map +1 -1
- package/src/engine/save/storage/IndexedDBStorage.js +21 -3
- package/src/engine/simulation/Ticker.d.ts +12 -0
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +18 -0
- package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
- package/src/engine/sound/simulation/AcousticSimulator.js +9 -1
- package/src/engine/sound/simulation/core/VolumeField.d.ts +6 -2
- package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/VolumeField.js +6 -2
- package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts +6 -2
- package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/AcousticProbeField.js +6 -2
- package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts +6 -2
- package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +6 -2
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts +3 -1
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +3 -1
- package/src/engine/ui/GUIEngine.d.ts.map +1 -1
- package/src/engine/ui/GUIEngine.js +8 -1
- package/src/generation/theme/TerrainTheme.d.ts.map +1 -1
- package/src/generation/theme/TerrainTheme.js +2 -1
- package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
- package/src/generation/theme/ThemeEngine.js +6 -5
- package/src/view/ViewGroup.d.ts.map +1 -1
- package/src/view/ViewGroup.js +9 -7
- package/src/view/graphics/WebGLContextFailureView.d.ts +19 -0
- package/src/view/graphics/WebGLContextFailureView.d.ts.map +1 -0
- package/src/view/graphics/WebGLContextFailureView.js +76 -0
- package/src/view/minimap/Minimap.d.ts +8 -0
- package/src/view/minimap/Minimap.d.ts.map +1 -1
- package/src/view/minimap/Minimap.js +16 -3
- package/src/view/minimap/dom/MinimapMarkerView.d.ts.map +1 -1
- package/src/view/minimap/dom/MinimapMarkerView.js +3 -1
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { assert } from "../../../core/assert.js";
|
|
2
|
+
import Signal from "../../../core/events/signal/Signal.js";
|
|
3
|
+
import { WebGLContextFailureReason } from "./WebGLContextFailureReason.js";
|
|
4
|
+
import { WebGLContextState } from "./WebGLContextState.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Detects WebGL context loss on a canvas and tracks whether the context may be used.
|
|
8
|
+
*
|
|
9
|
+
* The browser is only allowed to restore a lost context if `preventDefault()` was called on the loss
|
|
10
|
+
* event, which is what this class does. Restoration is still the browser's decision - it will refuse
|
|
11
|
+
* when the page caused the loss itself (typically by exceeding the per-page context limit) or when
|
|
12
|
+
* acceleration has been disabled for the page. That is why recovery is bounded: after
|
|
13
|
+
* {@link WebGLContextMonitor#restore_timeout} seconds without a restore, or after more than
|
|
14
|
+
* {@link WebGLContextMonitor#max_loss_count} losses, the monitor gives up and reports
|
|
15
|
+
* {@link WebGLContextMonitor#on}.failed so the application can tell the user instead of presenting a
|
|
16
|
+
* permanently black canvas.
|
|
17
|
+
*
|
|
18
|
+
* The restore deadline only runs while the page is visible. The browser does not restore a context in a
|
|
19
|
+
* hidden tab, so counting hidden time would fail sessions that were merely backgrounded when the loss
|
|
20
|
+
* happened - a common case, since background tabs are where the browser prefers to evict contexts. Each
|
|
21
|
+
* return to visibility restarts the full {@link WebGLContextMonitor#restore_timeout} wait.
|
|
22
|
+
*
|
|
23
|
+
* Detection is entirely event driven. Nothing here runs per frame; consumers read
|
|
24
|
+
* {@link WebGLContextMonitor#is_live} (a single field compare) and subscribe to the signals.
|
|
25
|
+
*/
|
|
26
|
+
export class WebGLContextMonitor {
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @type {HTMLCanvasElement|null}
|
|
30
|
+
*/
|
|
31
|
+
#canvas = null;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @type {WebGLContextState}
|
|
36
|
+
*/
|
|
37
|
+
#state = WebGLContextState.Live;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Incremented every time the context is restored. Async work that spans a loss can compare the
|
|
41
|
+
* generation it started in against the current one to find out whether its GPU-side results are
|
|
42
|
+
* still meaningful.
|
|
43
|
+
* @type {number}
|
|
44
|
+
*/
|
|
45
|
+
#generation = 0;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* How many times the context has been lost since {@link WebGLContextMonitor#attach}
|
|
49
|
+
* @type {number}
|
|
50
|
+
*/
|
|
51
|
+
#loss_count = 0;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Timestamps of recent losses, in milliseconds, oldest first. Entries older than
|
|
55
|
+
* {@link WebGLContextMonitor#loss_window} are dropped, so this measures a burst rather than a
|
|
56
|
+
* lifetime total - a session that hits an unrelated loss every couple of hours should keep
|
|
57
|
+
* recovering, one that dies four times in a minute should not.
|
|
58
|
+
* @type {number[]}
|
|
59
|
+
*/
|
|
60
|
+
#recent_losses = [];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Handle of the pending restore watchdog, `-1` when none is scheduled
|
|
64
|
+
* @type {number}
|
|
65
|
+
*/
|
|
66
|
+
#restore_watchdog = -1;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Timestamp of the most recent loss, in milliseconds
|
|
70
|
+
* @type {number}
|
|
71
|
+
*/
|
|
72
|
+
#time_of_loss = 0;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* How long the most recent recovery took, in seconds. `-1` until the first recovery.
|
|
76
|
+
* @type {number}
|
|
77
|
+
*/
|
|
78
|
+
#restore_duration = -1;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* How long to wait for the browser to restore a lost context before declaring failure, in seconds.
|
|
82
|
+
* Only visible time counts - the browser will not restore while the tab is hidden, so the deadline is
|
|
83
|
+
* suspended for as long as the page is, and restarts in full when the page is revealed.
|
|
84
|
+
* @type {number}
|
|
85
|
+
*/
|
|
86
|
+
restore_timeout = 5;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* How many losses within {@link WebGLContextMonitor#loss_window} to recover from before giving up. A
|
|
90
|
+
* context that keeps dying is usually a symptom of something recovery cannot fix, such as a driver
|
|
91
|
+
* that crashes on our workload.
|
|
92
|
+
* @type {number}
|
|
93
|
+
*/
|
|
94
|
+
max_loss_count = 3;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Window over which {@link WebGLContextMonitor#max_loss_count} is counted, in seconds
|
|
98
|
+
* @type {number}
|
|
99
|
+
*/
|
|
100
|
+
loss_window = 60;
|
|
101
|
+
|
|
102
|
+
on = {
|
|
103
|
+
/**
|
|
104
|
+
* Context has been lost. Rendering must stop until `restored` or `failed`.
|
|
105
|
+
* @type {Signal}
|
|
106
|
+
*/
|
|
107
|
+
lost: new Signal(),
|
|
108
|
+
/**
|
|
109
|
+
* Context has been restored, carries the new generation number. GPU-side state must be
|
|
110
|
+
* considered empty; anything not re-derivable from CPU-side data has to be rebuilt here.
|
|
111
|
+
* @type {Signal<number>}
|
|
112
|
+
*/
|
|
113
|
+
restored: new Signal(),
|
|
114
|
+
/**
|
|
115
|
+
* Recovery was abandoned, carries a {@link WebGLContextFailureReason}. Terminal.
|
|
116
|
+
* @type {Signal<string>}
|
|
117
|
+
*/
|
|
118
|
+
failed: new Signal()
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @returns {WebGLContextState}
|
|
123
|
+
*/
|
|
124
|
+
get state() {
|
|
125
|
+
return this.#state;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @returns {number}
|
|
130
|
+
*/
|
|
131
|
+
get generation() {
|
|
132
|
+
return this.#generation;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Total number of losses observed since {@link WebGLContextMonitor#attach}
|
|
137
|
+
* @returns {number}
|
|
138
|
+
*/
|
|
139
|
+
get loss_count() {
|
|
140
|
+
return this.#loss_count;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Number of losses within the last {@link WebGLContextMonitor#loss_window} seconds, including the
|
|
145
|
+
* current one if the context is presently lost
|
|
146
|
+
* @returns {number}
|
|
147
|
+
*/
|
|
148
|
+
get recent_loss_count() {
|
|
149
|
+
const window_start = performance.now() - this.loss_window * 1000;
|
|
150
|
+
|
|
151
|
+
const recent = this.#recent_losses;
|
|
152
|
+
|
|
153
|
+
let result = 0;
|
|
154
|
+
|
|
155
|
+
for (let i = 0; i < recent.length; i++) {
|
|
156
|
+
if (recent[i] >= window_start) {
|
|
157
|
+
result++;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Duration of the most recent recovery in seconds, `-1` if the context has never been restored
|
|
166
|
+
* @returns {number}
|
|
167
|
+
*/
|
|
168
|
+
get restore_duration() {
|
|
169
|
+
return this.#restore_duration;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Whether the context may be used for rendering. This is the per-frame gate, keep it cheap.
|
|
174
|
+
* @returns {boolean}
|
|
175
|
+
*/
|
|
176
|
+
get is_live() {
|
|
177
|
+
return this.#state === WebGLContextState.Live;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Start watching a canvas, whose context is assumed to be live. Must be called before the context is
|
|
182
|
+
* used, and at most once without an intervening {@link WebGLContextMonitor#detach}.
|
|
183
|
+
*
|
|
184
|
+
* Loss bookkeeping is reset, so attaching to a freshly created canvas after giving up on the previous
|
|
185
|
+
* one starts with a clean slate. The generation counter is not reset - it is monotonic for the
|
|
186
|
+
* lifetime of the monitor, so that stale async results can always be recognised.
|
|
187
|
+
*
|
|
188
|
+
* @param {HTMLCanvasElement} canvas
|
|
189
|
+
*/
|
|
190
|
+
attach(canvas) {
|
|
191
|
+
assert.defined(canvas, 'canvas');
|
|
192
|
+
assert.equal(this.#canvas, null, 'monitor is already attached');
|
|
193
|
+
|
|
194
|
+
this.#canvas = canvas;
|
|
195
|
+
this.#state = WebGLContextState.Live;
|
|
196
|
+
this.#loss_count = 0;
|
|
197
|
+
this.#recent_losses.length = 0;
|
|
198
|
+
|
|
199
|
+
canvas.addEventListener('webglcontextlost', this.#handle_lost, false);
|
|
200
|
+
canvas.addEventListener('webglcontextrestored', this.#handle_restored, false);
|
|
201
|
+
|
|
202
|
+
canvas.ownerDocument.addEventListener('visibilitychange', this.#handle_visibility_change, false);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Stop watching the canvas and cancel any pending watchdog
|
|
207
|
+
*/
|
|
208
|
+
detach() {
|
|
209
|
+
const canvas = this.#canvas;
|
|
210
|
+
|
|
211
|
+
if (canvas === null) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
canvas.removeEventListener('webglcontextlost', this.#handle_lost, false);
|
|
216
|
+
canvas.removeEventListener('webglcontextrestored', this.#handle_restored, false);
|
|
217
|
+
|
|
218
|
+
canvas.ownerDocument.removeEventListener('visibilitychange', this.#handle_visibility_change, false);
|
|
219
|
+
|
|
220
|
+
this.#cancel_watchdog();
|
|
221
|
+
|
|
222
|
+
this.#canvas = null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
#cancel_watchdog() {
|
|
226
|
+
if (this.#restore_watchdog !== -1) {
|
|
227
|
+
clearTimeout(this.#restore_watchdog);
|
|
228
|
+
this.#restore_watchdog = -1;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
#arm_watchdog() {
|
|
233
|
+
this.#restore_watchdog = setTimeout(
|
|
234
|
+
() => {
|
|
235
|
+
this.#restore_watchdog = -1;
|
|
236
|
+
this.#fail(WebGLContextFailureReason.RestoreTimeout);
|
|
237
|
+
},
|
|
238
|
+
this.restore_timeout * 1000
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Whether the page holding the canvas is currently hidden
|
|
244
|
+
* @returns {boolean}
|
|
245
|
+
*/
|
|
246
|
+
#is_page_hidden() {
|
|
247
|
+
return this.#canvas.ownerDocument.visibilityState === 'hidden';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
*
|
|
252
|
+
* @param {WebGLContextFailureReason} reason
|
|
253
|
+
*/
|
|
254
|
+
#fail(reason) {
|
|
255
|
+
this.#cancel_watchdog();
|
|
256
|
+
|
|
257
|
+
this.#state = WebGLContextState.Failed;
|
|
258
|
+
|
|
259
|
+
this.on.failed.send1(reason);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
*
|
|
264
|
+
* @param {WebGLContextEvent} event
|
|
265
|
+
*/
|
|
266
|
+
#handle_lost = (event) => {
|
|
267
|
+
// by default a lost context is never handed back; preventing the default behaviour is what makes
|
|
268
|
+
// the browser consider restoring it
|
|
269
|
+
event.preventDefault();
|
|
270
|
+
|
|
271
|
+
if (this.#state === WebGLContextState.Failed) {
|
|
272
|
+
// already given up, nothing more to do
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
this.#cancel_watchdog();
|
|
277
|
+
|
|
278
|
+
const now = performance.now();
|
|
279
|
+
|
|
280
|
+
this.#loss_count++;
|
|
281
|
+
this.#time_of_loss = now;
|
|
282
|
+
this.#state = WebGLContextState.Lost;
|
|
283
|
+
|
|
284
|
+
const recent = this.#recent_losses;
|
|
285
|
+
|
|
286
|
+
// drop losses that have aged out of the window
|
|
287
|
+
const window_start = now - this.loss_window * 1000;
|
|
288
|
+
|
|
289
|
+
let surviving = 0;
|
|
290
|
+
for (let i = 0; i < recent.length; i++) {
|
|
291
|
+
if (recent[i] >= window_start) {
|
|
292
|
+
recent[surviving++] = recent[i];
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
recent.length = surviving;
|
|
296
|
+
|
|
297
|
+
recent.push(now);
|
|
298
|
+
|
|
299
|
+
this.on.lost.send0();
|
|
300
|
+
|
|
301
|
+
if (recent.length > this.max_loss_count) {
|
|
302
|
+
this.#fail(WebGLContextFailureReason.TooManyLosses);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!this.#is_page_hidden()) {
|
|
307
|
+
// a hidden tab's context cannot be restored, so the deadline would be unmeetable; it is
|
|
308
|
+
// armed by #handle_visibility_change once the page is revealed
|
|
309
|
+
this.#arm_watchdog();
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
#handle_visibility_change = () => {
|
|
314
|
+
if (this.#state !== WebGLContextState.Lost) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (this.#is_page_hidden()) {
|
|
319
|
+
this.#cancel_watchdog();
|
|
320
|
+
} else if (this.#restore_watchdog === -1) {
|
|
321
|
+
this.#arm_watchdog();
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
#handle_restored = () => {
|
|
326
|
+
if (this.#state === WebGLContextState.Failed) {
|
|
327
|
+
// we already told the application that the device is gone and it may have torn down its
|
|
328
|
+
// presentation state; coming back to life here would leave it in an inconsistent state
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
this.#cancel_watchdog();
|
|
333
|
+
|
|
334
|
+
this.#restore_duration = (performance.now() - this.#time_of_loss) / 1000;
|
|
335
|
+
|
|
336
|
+
this.#generation++;
|
|
337
|
+
this.#state = WebGLContextState.Live;
|
|
338
|
+
|
|
339
|
+
this.on.restored.send1(this.#generation);
|
|
340
|
+
};
|
|
341
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle state of the WebGL context tracked by {@link WebGLContextMonitor }.
|
|
3
|
+
*
|
|
4
|
+
* There is deliberately no separate "restoring" state: the monitor always calls `preventDefault()` on
|
|
5
|
+
* the loss event, so `Lost` already means "gone, waiting for the browser to hand it back". Recovery
|
|
6
|
+
* fix-ups run synchronously inside the restore handler, so no state is observable in between.
|
|
7
|
+
*/
|
|
8
|
+
export type WebGLContextState = number;
|
|
9
|
+
export namespace WebGLContextState {
|
|
10
|
+
let Live: number;
|
|
11
|
+
let Lost: number;
|
|
12
|
+
let Failed: number;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=WebGLContextState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebGLContextState.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/context/WebGLContextState.js"],"names":[],"mappings":";;;;;;;gCAOU,MAAM"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle state of the WebGL context tracked by {@link WebGLContextMonitor}.
|
|
3
|
+
*
|
|
4
|
+
* There is deliberately no separate "restoring" state: the monitor always calls `preventDefault()` on
|
|
5
|
+
* the loss event, so `Lost` already means "gone, waiting for the browser to hand it back". Recovery
|
|
6
|
+
* fix-ups run synchronously inside the restore handler, so no state is observable in between.
|
|
7
|
+
*
|
|
8
|
+
* @enum {number}
|
|
9
|
+
*/
|
|
10
|
+
export const WebGLContextState = {
|
|
11
|
+
/**
|
|
12
|
+
* Context is usable, rendering is allowed
|
|
13
|
+
*/
|
|
14
|
+
Live: 0,
|
|
15
|
+
/**
|
|
16
|
+
* Context is gone and we are waiting for the browser to restore it. Rendering is suppressed.
|
|
17
|
+
*/
|
|
18
|
+
Lost: 1,
|
|
19
|
+
/**
|
|
20
|
+
* Recovery was given up on. Terminal - the context will not come back without recreating the
|
|
21
|
+
* renderer or reloading the page.
|
|
22
|
+
*/
|
|
23
|
+
Failed: 2
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testWebGLContextLoss.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/context/testWebGLContextLoss.js"],"names":[],"mappings":""}
|