@woosh/meep-engine 3.1.0 → 3.3.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.
Files changed (1869) hide show
  1. package/LICENSE +188 -188
  2. package/README.md +152 -152
  3. package/editor/Editor.js +598 -598
  4. package/editor/EditorCameraNavigation.js +205 -205
  5. package/editor/EditorKeyMap.js +182 -182
  6. package/editor/SelectionVisualizer.js +127 -127
  7. package/editor/actions/concrete/ActionInvalidateSampler.js +27 -27
  8. package/editor/actions/concrete/PatchTerrainHeightAction.js +85 -85
  9. package/editor/camera/camera_framing.js +104 -104
  10. package/editor/clipboard.js +184 -184
  11. package/editor/ecs/component/editors/ObservedIntegerEditor.js +22 -22
  12. package/editor/ecs/component/editors/ObservedStringEditor.js +34 -34
  13. package/editor/ecs/component/editors/common/two_way_sync.js +50 -50
  14. package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +19 -19
  15. package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +35 -35
  16. package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -17
  17. package/editor/ecs/component/editors/ecs/SGMeshEditor.js +24 -24
  18. package/editor/ecs/component/editors/ecs/ShadedGeometryEditor.js +33 -33
  19. package/editor/ecs/component/editors/ecs/Trail3DEditor.js +45 -45
  20. package/editor/ecs/component/editors/ecs/buildGridObstaclePreview.js +19 -19
  21. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +72 -72
  22. package/editor/ecs/component/editors/shade/MeshletGeometryEditor.js +30 -30
  23. package/editor/ecs/component/editors/shade/ShadeImageEditor.js +70 -70
  24. package/editor/ecs/component/editors/shade/ShadeMaterialEditor.js +34 -34
  25. package/editor/ecs/component/editors/shade/ShadeTextureEditor.js +46 -46
  26. package/editor/ecs/component/editors/shade/StandardShadeMaterialEditor.js +24 -24
  27. package/editor/ecs/component/prototypeObjectEditor.js +265 -265
  28. package/editor/ecs/component/registerBasicTypeEditors.js +100 -100
  29. package/editor/ecs/component/registerEngineComponentEditors.js +95 -95
  30. package/editor/entity_world_bounds.js +27 -27
  31. package/editor/particles/lut_ops.js +148 -148
  32. package/editor/particles/particleEditEvents.js +12 -12
  33. package/editor/particles/rebuildParticleEmitter.js +31 -31
  34. package/editor/persistence/EditorLayoutStore.js +71 -71
  35. package/editor/persistence/SceneMetadata.js +52 -52
  36. package/editor/persistence/SceneSlotManager.js +144 -144
  37. package/editor/persistence/buildNewSceneDataset.js +67 -67
  38. package/editor/persistence/files.js +68 -68
  39. package/editor/persistence/scene_import.js +143 -143
  40. package/editor/persistence/scene_serialization.js +79 -79
  41. package/editor/persistence/string_buffer_codec.js +41 -41
  42. package/editor/process/GridDisplayProcess.js +125 -125
  43. package/editor/process/SymbolicDisplayProcess.js +106 -108
  44. package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
  45. package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
  46. package/editor/process/symbolic/PathSymbolicDisplay.js +118 -118
  47. package/editor/process/symbolic/PositionedMarkerSymbolicDisplay.js +79 -79
  48. package/editor/process/symbolic/SoundEmitterSymbolicDisplay.js +57 -57
  49. package/editor/process/symbolic/SymbolicDisplay.js +62 -62
  50. package/editor/process/symbolic/gizmo_draw_wire_box_oriented.js +85 -85
  51. package/editor/process/symbolic/gizmo_draw_wire_circle.js +53 -53
  52. package/editor/prototypeEditorShell.js +156 -156
  53. package/editor/selection/editor_pick.js +130 -130
  54. package/editor/selection/screen_rect_frustum.js +119 -119
  55. package/editor/style/controls.scss +168 -168
  56. package/editor/style/inspector.scss +223 -223
  57. package/editor/templates/entity_templates.js +167 -167
  58. package/editor/tools/GridPaintTool.js +273 -273
  59. package/editor/tools/SelectionTool.js +307 -307
  60. package/editor/tools/TransformToolV2.js +378 -378
  61. package/editor/tools/engine/ToolEngine.js +188 -188
  62. package/editor/tools/paint/TerrainTexturePaintTool.js +250 -250
  63. package/editor/tools/v2/BlenderCameraOrientationGizmo.js +501 -501
  64. package/editor/tools/v2/TransformControls.js +971 -971
  65. package/editor/tools/v2/handle/gizmo_drag_plane.js +141 -141
  66. package/editor/tools/v2/handle/gizmo_draw.js +399 -399
  67. package/editor/tools/v2/handle/gizmo_handles.js +364 -364
  68. package/editor/tools/v2/handle/gizmo_ray_shapes.js +239 -239
  69. package/editor/view/ecs/HierarchicalEntityListView.js +339 -339
  70. package/editor/view/ecs/components/DatGuiController.js +2 -2
  71. package/editor/view/ecs/components/common/AutoCanvasView.js +100 -100
  72. package/editor/view/ecs/components/common/TextController.js +59 -59
  73. package/editor/view/library/MeshLibraryView.js +175 -175
  74. package/editor/view/library/mesh_library_drag.js +63 -63
  75. package/editor/view/library/model_thumbnail_source.js +86 -86
  76. package/editor/view/makeEntityDecorators.js +125 -125
  77. package/editor/view/node-graph/NodeGraphSelection.js +89 -89
  78. package/editor/view/node-graph/NodeView.js +211 -211
  79. package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -36
  80. package/editor/view/node-graph/actions/NodesMoveAction.js +41 -41
  81. package/editor/view/node-graph/connection_wire_geometry.js +107 -107
  82. package/editor/view/particles/ColorLutGradientView.js +291 -291
  83. package/editor/view/particles/ScalarLutCurveView.js +279 -279
  84. package/editor/view/prepareMeshLibrary.js +188 -188
  85. package/editor/view/shell/SceneTreePanelView.js +119 -119
  86. package/editor/view/v2/SplitView.js +2 -2
  87. package/package.json +94 -94
  88. package/samples/generation/generators/interactive/mir_generator_place_buff_objects.js +362 -362
  89. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +738 -738
  90. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +79 -79
  91. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +93 -93
  92. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +80 -80
  93. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +164 -164
  94. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +69 -69
  95. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +102 -102
  96. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +129 -129
  97. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +72 -72
  98. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +74 -74
  99. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +169 -169
  100. package/src/DUPLICATION_AUDIT_2026_08_07.md +254 -254
  101. package/src/DUPLICATION_AUDIT_REMEDIATION.md +250 -250
  102. package/src/REVIEW_2026_08_06/adv-core.md +511 -511
  103. package/src/REVIEW_2026_08_06/adv-gfx.md +480 -480
  104. package/src/REVIEW_2026_08_06/adv-view.md +446 -446
  105. package/src/REVIEW_2026_08_06/api-core.md +296 -296
  106. package/src/REVIEW_2026_08_06/api-engine.md +195 -195
  107. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -507
  108. package/src/REVIEW_2026_08_06/core-binary.md +348 -348
  109. package/src/REVIEW_2026_08_06/core-collection.md +376 -376
  110. package/src/REVIEW_2026_08_06/core-math.md +221 -221
  111. package/src/REVIEW_2026_08_06/core-process.md +266 -266
  112. package/src/REVIEW_2026_08_06/core-science.md +223 -223
  113. package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -279
  114. package/src/REVIEW_2026_08_06/engine-animation.md +167 -167
  115. package/src/REVIEW_2026_08_06/engine-asset.md +166 -166
  116. package/src/REVIEW_2026_08_06/engine-ecs.md +920 -920
  117. package/src/REVIEW_2026_08_06/engine-input.md +197 -197
  118. package/src/REVIEW_2026_08_06/engine-misc.md +248 -248
  119. package/src/REVIEW_2026_08_06/engine-terrain.md +52 -52
  120. package/src/REVIEW_2026_08_06/generation.md +176 -176
  121. package/src/REVIEW_2026_08_06/geom-2d.md +434 -434
  122. package/src/REVIEW_2026_08_06/geom-3d.md +117 -117
  123. package/src/REVIEW_2026_08_06/gfx-gi.md +143 -143
  124. package/src/REVIEW_2026_08_06/gfx-render.md +740 -740
  125. package/src/REVIEW_2026_08_06/gfx-texture.md +690 -690
  126. package/src/REVIEW_2026_08_06/prior-criticals.md +49 -49
  127. package/src/REVIEW_2026_08_06/prior-highs.md +138 -138
  128. package/src/REVIEW_2026_08_06/test-gaps.md +364 -364
  129. package/src/REVIEW_2026_08_06/view.md +667 -667
  130. package/src/REVIEW_2026_08_06.md +610 -610
  131. package/src/avif/codec/dec/avif_dec.cpp +233 -233
  132. package/src/avif/codec/dec/avif_dec.js +16 -16
  133. package/src/avif/encoder_worker.js +5 -18
  134. package/src/core/binary/BitImage2.js +246 -246
  135. package/src/core/binary/align_32.js +21 -21
  136. package/src/core/binary/data_view/DataType2DataViewReaders.js +23 -23
  137. package/src/core/binary/data_view/DataType2DataViewWriters.js +25 -25
  138. package/src/core/binary/hash/XXH128Hash.js +55 -55
  139. package/src/core/binary/hash/XXH3_SECRET.js +25 -25
  140. package/src/core/binary/hash/xxh3_128.js +341 -341
  141. package/src/core/binary/hash/xxh3_64.js +241 -241
  142. package/src/core/binary/hash/xxh3_common.js +476 -476
  143. package/src/core/binary/lz4/LZ4_MAX_INPUT_SIZE.js +9 -9
  144. package/src/core/binary/lz4/lz4_compress_block.js +385 -385
  145. package/src/core/binary/lz4/lz4_compress_bound.js +25 -25
  146. package/src/core/binary/lz4/lz4_decompress_block.js +139 -139
  147. package/src/core/binary/lz4/lz4_decompress_bound.js +30 -30
  148. package/src/core/binary/meshopt/MESHOPT_GROUP_SIZE.js +18 -18
  149. package/src/core/binary/meshopt/MeshoptCompressionFilter.js +30 -30
  150. package/src/core/binary/meshopt/MeshoptCompressionMode.js +21 -21
  151. package/src/core/binary/meshopt/__meshopt_test_streams.js +237 -237
  152. package/src/core/binary/meshopt/meshopt_decode.js +73 -73
  153. package/src/core/binary/meshopt/meshopt_decode_byte_group.js +67 -67
  154. package/src/core/binary/meshopt/meshopt_decode_data_block.js +59 -59
  155. package/src/core/binary/meshopt/meshopt_decode_filter_color.js +69 -69
  156. package/src/core/binary/meshopt/meshopt_decode_filter_exponential.js +43 -43
  157. package/src/core/binary/meshopt/meshopt_decode_filter_octahedral.js +60 -60
  158. package/src/core/binary/meshopt/meshopt_decode_filter_quaternion.js +71 -71
  159. package/src/core/binary/meshopt/meshopt_decode_index_buffer.js +294 -294
  160. package/src/core/binary/meshopt/meshopt_decode_index_sequence.js +115 -115
  161. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +381 -381
  162. package/src/core/binary/meshopt/meshopt_read_uint_var.js +59 -59
  163. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -13
  164. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -14
  165. package/src/core/binary/type/DataType2TypedArrayConstructorMapping.js +35 -35
  166. package/src/core/bvh2/bvh3/ebvh_geometry_query_any_triangle_ray.js +149 -149
  167. package/src/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +96 -96
  168. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -101
  169. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +77 -77
  170. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +90 -90
  171. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray_segment.js +94 -94
  172. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +86 -86
  173. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +101 -101
  174. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +92 -92
  175. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray.js +96 -96
  176. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray_segment.js +100 -100
  177. package/src/core/bvh2/visual/BVHGeometry.js +131 -131
  178. package/src/core/bvh8/BVH8.js +436 -436
  179. package/src/core/bvh8/aabb3_round_to_float32.js +22 -22
  180. package/src/core/bvh8/build/BVH8Converter.js +588 -588
  181. package/src/core/bvh8/build/TriangleCluster.js +122 -122
  182. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +28 -28
  183. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +17 -17
  184. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -303
  185. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -256
  186. package/src/core/bvh8/build/byte.js +9 -9
  187. package/src/core/bvh8/build/encode_bounds_e.js +11 -11
  188. package/src/core/bvh8/bvh8_convert_to_dot.js +132 -132
  189. package/src/core/bvh8/bvh8_count_primitives.js +98 -98
  190. package/src/core/bvh8/bvh8_geometry_validate.js +138 -138
  191. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +166 -166
  192. package/src/core/bvh8/bvh8_get_node_bounds.js +34 -34
  193. package/src/core/bvh8/bvh8_get_node_child_bounds.js +52 -52
  194. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -18
  195. package/src/core/bvh8/bvh8_node_count_triangles.js +27 -27
  196. package/src/core/bvh8/bvh8_quality.js +72 -72
  197. package/src/core/bvh8/bvh8_validate_structure.js +87 -87
  198. package/src/core/clipboard/obtainClipBoard.js +29 -29
  199. package/src/core/clipboard/safeClipboardReadText.js +55 -55
  200. package/src/core/clipboard/safeClipboardWriteText.js +23 -23
  201. package/src/core/collection/array/typed/typed_array_value_denormalize.js +52 -52
  202. package/src/core/collection/array/typed/typed_array_value_normalize.js +51 -51
  203. package/src/core/collection/union-find/union_find.js +79 -79
  204. package/src/core/color/PQ/PQ_constants.d.ts +43 -0
  205. package/src/core/color/PQ/PQ_constants.d.ts.map +1 -0
  206. package/src/core/color/PQ/PQ_constants.js +50 -0
  207. package/src/core/color/PQ/PQ_to_linear.d.ts +24 -0
  208. package/src/core/color/PQ/PQ_to_linear.d.ts.map +1 -0
  209. package/src/core/color/PQ/PQ_to_linear.js +35 -0
  210. package/src/core/color/PQ/linear_to_PQ.d.ts +27 -0
  211. package/src/core/color/PQ/linear_to_PQ.d.ts.map +1 -0
  212. package/src/core/color/PQ/linear_to_PQ.js +32 -0
  213. package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -20
  214. package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -17
  215. package/src/core/color/colormap/MAGMA_LUT.js +26 -26
  216. package/src/core/color/illuminant/D65_TRISTIMULUS_XYZ.js +19 -19
  217. package/src/core/color/lab/lab_apply_hunt_adjustment.js +27 -27
  218. package/src/core/color/lab/lab_distance_hyab.js +23 -23
  219. package/src/core/color/lab/xyz_to_lab.js +62 -62
  220. package/src/core/color/operations/color_darken.js +24 -24
  221. package/src/core/color/operations/color_desaturate.js +24 -24
  222. package/src/core/color/operations/color_lighten.js +24 -24
  223. package/src/core/color/operations/color_saturate.js +24 -24
  224. package/src/core/color/operations/color_scale_okhsv_channel.js +45 -45
  225. package/src/core/color/tonemap/tonemap_aces.js +41 -41
  226. package/src/core/color/ycxcz/xyz_to_ycxcz.js +28 -28
  227. package/src/core/color/ycxcz/ycxcz_to_xyz.js +19 -19
  228. package/src/core/dom/isImageBitmap.js +12 -12
  229. package/src/core/function/frameThrottle.js +23 -23
  230. package/src/core/geom/2d/aabb/aabb2_array_combine.js +7 -7
  231. package/src/core/geom/2d/aabb/aabb2_compute_area.js +7 -7
  232. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +7 -7
  233. package/src/core/geom/2d/aabb/aabb2_compute_overlap.js +7 -7
  234. package/src/core/geom/2d/aabb/aabb2_from_v2_array.js +7 -7
  235. package/src/core/geom/2d/aabb/aabb2_intersects_point.js +7 -7
  236. package/src/core/geom/2d/aabb/aabb2_overlap_exists.js +7 -7
  237. package/src/core/geom/2d/circle/circle_compute_circle_intersection.js +7 -7
  238. package/src/core/geom/2d/circle/circle_compute_circle_penetration.js +7 -7
  239. package/src/core/geom/2d/circle/circle_intersects_point.js +7 -7
  240. package/src/core/geom/2d/compute_polygon_area_2d.js +7 -7
  241. package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +7 -7
  242. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +7 -7
  243. package/src/core/geom/2d/convex-hull/orientation3_array.js +7 -7
  244. package/src/core/geom/2d/intersect_ray_2d.js +7 -7
  245. package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +7 -7
  246. package/src/core/geom/2d/line/line2_segment_intersection_fraction_2d.js +44 -44
  247. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +7 -7
  248. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +7 -7
  249. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +7 -7
  250. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +7 -7
  251. package/src/core/geom/2d/line/line_segment_intersection_fraction_2d.js +7 -7
  252. package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +7 -7
  253. package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -25
  254. package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -46
  255. package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -52
  256. package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -69
  257. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -433
  258. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.js +51 -51
  259. package/src/core/geom/2d/polygon/polygon2_clip_halfplane.js +50 -50
  260. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -84
  261. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -52
  262. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -86
  263. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -1280
  264. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -77
  265. package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -39
  266. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -101
  267. package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -7
  268. package/src/core/geom/2d/rectangle_to_aabb.js +7 -7
  269. package/src/core/geom/2d/spline_bezier2_2d.js +7 -7
  270. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +99 -99
  271. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -35
  272. package/src/core/geom/2d/triangle2d_compute_area.js +7 -7
  273. package/src/core/geom/2d/triangle2d_contains_point.js +7 -7
  274. package/src/core/geom/2d/triangle2d_get_barycentric.js +7 -7
  275. package/src/core/geom/2d/v2_morton_encode.js +23 -23
  276. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_degree.js +7 -7
  277. package/src/core/geom/3d/aabb/aabb3_box_surface_area_2.js +7 -7
  278. package/src/core/geom/3d/aabb/aabb3_build_frustum.js +5 -5
  279. package/src/core/geom/3d/aabb/aabb3_closest_point_on_surface.js +57 -57
  280. package/src/core/geom/3d/aabb/aabb3_combined_surface_area.js +7 -7
  281. package/src/core/geom/3d/aabb/aabb3_compute_half_surface_area.js +7 -7
  282. package/src/core/geom/3d/aabb/aabb3_compute_projected_area.js +7 -7
  283. package/src/core/geom/3d/aabb/aabb3_compute_surface_area.js +7 -7
  284. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +7 -7
  285. package/src/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +7 -7
  286. package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +7 -7
  287. package/src/core/geom/3d/aabb/aabb3_from_triangle_group.js +46 -46
  288. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_degree.js +7 -7
  289. package/src/core/geom/3d/aabb/aabb3_intersects_line_segment.js +7 -7
  290. package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +7 -7
  291. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +7 -7
  292. package/src/core/geom/3d/aabb/aabb3_ray_segment_entry_distance.js +95 -95
  293. package/src/core/geom/3d/aabb/aabb3_raycast.js +7 -7
  294. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -93
  295. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.js +82 -82
  296. package/src/core/geom/3d/aabb/compute_aabb_from_points.js +7 -7
  297. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +7 -7
  298. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -486
  299. package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -174
  300. package/src/core/geom/3d/atlas/Chart.js +77 -77
  301. package/src/core/geom/3d/atlas/REVIEW_02.md +392 -392
  302. package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -315
  303. package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -16
  304. package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -188
  305. package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -107
  306. package/src/core/geom/3d/atlas/atlas_generate.js +50 -50
  307. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -266
  308. package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -36
  309. package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -62
  310. package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -33
  311. package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -50
  312. package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -39
  313. package/src/core/geom/3d/atlas/io/bt_loop_uv.js +35 -35
  314. package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -46
  315. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +269 -269
  316. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +209 -209
  317. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -38
  318. package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -86
  319. package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -183
  320. package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -66
  321. package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -40
  322. package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -136
  323. package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -30
  324. package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -77
  325. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +116 -116
  326. package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +271 -271
  327. package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +191 -191
  328. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -35
  329. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_closed.js +67 -67
  330. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_iterative.js +137 -137
  331. package/src/core/geom/3d/compute_circle_bounding_box.js +7 -7
  332. package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -7
  333. package/src/core/geom/3d/cone/computeConePlaneSide.js +7 -7
  334. package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +7 -7
  335. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts +38 -0
  336. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts.map +1 -0
  337. package/src/core/geom/3d/cylinder/cylinder3_raycast.js +105 -0
  338. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -18
  339. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -24
  340. package/src/core/geom/3d/frustum/clipping_volume_matrix4_project.js +7 -7
  341. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +7 -7
  342. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +117 -117
  343. package/src/core/geom/3d/frustum/frustum_matrix4_project.js +7 -7
  344. package/src/core/geom/3d/frustum/hexahedron_from_aabb.js +7 -7
  345. package/src/core/geom/3d/frustum/read_frustum_corner.js +17 -17
  346. package/src/core/geom/3d/frustum/read_three_planes_to_array.js +7 -7
  347. package/src/core/geom/3d/frustum/slice_frustum_linear_to_points.js +7 -7
  348. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +146 -146
  349. package/src/core/geom/3d/gjk/gjk.js +430 -430
  350. package/src/core/geom/3d/gjk/gjk_epa_penetration.js +520 -520
  351. package/src/core/geom/3d/gjk/minkowski_support.js +71 -71
  352. package/src/core/geom/3d/gjk/mpr.js +368 -368
  353. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +7 -7
  354. package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.js +7 -7
  355. package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -64
  356. package/src/core/geom/3d/line/line3_compute_segment_closest_point_to_aabb3_t.js +153 -153
  357. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_aabb3_t.js +7 -7
  358. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_point_t.js +7 -7
  359. package/src/core/geom/3d/line/line3_compute_segment_segment_closest_points.js +88 -88
  360. package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -71
  361. package/src/core/geom/3d/line/segment3_point_distance_to_segments.js +25 -25
  362. package/src/core/geom/3d/mat4/allocate_m4.js +7 -7
  363. package/src/core/geom/3d/mat4/apply_mat4_transform_to_direction_v3_array.js +7 -7
  364. package/src/core/geom/3d/mat4/apply_mat4_transform_to_v3_array.js +7 -7
  365. package/src/core/geom/3d/mat4/compose_matrix4_array.js +7 -7
  366. package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +7 -7
  367. package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +7 -7
  368. package/src/core/geom/3d/mat4/m4_compose.js +22 -22
  369. package/src/core/geom/3d/mat4/m4_compute_normal_matrix3.js +7 -7
  370. package/src/core/geom/3d/mat4/m4_decompose.js +64 -64
  371. package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -157
  372. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +32 -32
  373. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -67
  374. package/src/core/geom/3d/mat4/m4_linear_matrix3.js +29 -29
  375. package/src/core/geom/3d/mat4/m4_look_at.js +96 -96
  376. package/src/core/geom/3d/mat4/m4_make_rotation_x.js +47 -47
  377. package/src/core/geom/3d/mat4/m4_make_rotation_y.js +47 -47
  378. package/src/core/geom/3d/mat4/m4_make_rotation_z.js +47 -47
  379. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +39 -39
  380. package/src/core/geom/3d/mat4/m4_perspective.js +66 -66
  381. package/src/core/geom/3d/mat4/m4_transpose.js +48 -48
  382. package/src/core/geom/3d/morton/mortonEncode_LUT.js +7 -7
  383. package/src/core/geom/3d/morton/mortonEncode_magicbits.js +7 -7
  384. package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -5
  385. package/src/core/geom/3d/normal/hemioct/encode_unit_to_hemioct.js +28 -28
  386. package/src/core/geom/3d/normal/lambert_azimuth/decode_azimuth_to_unit.js +30 -30
  387. package/src/core/geom/3d/normal/lambert_azimuth/encode_unit_to_azimuth.js +19 -19
  388. package/src/core/geom/3d/normal/spherical/decode_spheremap_to_unit.js +38 -38
  389. package/src/core/geom/3d/normal/spherical/encode_unit_to_spheremap.js +30 -30
  390. package/src/core/geom/3d/plane/is_point_within_planes.js +7 -7
  391. package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -47
  392. package/src/core/geom/3d/plane/plane3_compute_convex_3_plane_intersection.js +7 -7
  393. package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +7 -7
  394. package/src/core/geom/3d/plane/plane3_intersect_plane.js +7 -7
  395. package/src/core/geom/3d/plane/plane3_three_compute_convex_3_plane_intersection.js +7 -7
  396. package/src/core/geom/3d/point/point3_raycast.d.ts +33 -0
  397. package/src/core/geom/3d/point/point3_raycast.d.ts.map +1 -0
  398. package/src/core/geom/3d/point/point3_raycast.js +47 -0
  399. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -60
  400. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -94
  401. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts +40 -0
  402. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts.map +1 -0
  403. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.js +94 -0
  404. package/src/core/geom/3d/quadric/QUADRIC3_SIZE.js +14 -14
  405. package/src/core/geom/3d/quadric/Quadric3.js +282 -282
  406. package/src/core/geom/3d/quadric/quadric3_add.js +33 -33
  407. package/src/core/geom/3d/quadric/quadric3_clear.js +25 -25
  408. package/src/core/geom/3d/quadric/quadric3_copy.js +27 -27
  409. package/src/core/geom/3d/quadric/quadric3_distance.js +36 -36
  410. package/src/core/geom/3d/quadric/quadric3_evaluate.js +25 -25
  411. package/src/core/geom/3d/quadric/quadric3_optimize.js +45 -45
  412. package/src/core/geom/3d/quadric/quadric3_scale.js +32 -32
  413. package/src/core/geom/3d/quadric/quadric3_set_from_plane_through_point.js +30 -30
  414. package/src/core/geom/3d/quadric/quadric3_set_from_vector4.js +35 -35
  415. package/src/core/geom/3d/quadric/quadric3_sub.js +36 -36
  416. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3.js +28 -28
  417. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3_inverse.js +56 -56
  418. package/src/core/geom/3d/quadric/quadric3_to_vector3.js +19 -19
  419. package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +7 -7
  420. package/src/core/geom/3d/quaternion/quat3_integrate.js +62 -62
  421. package/src/core/geom/3d/quaternion/quat3_multiply.js +31 -31
  422. package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -72
  423. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -69
  424. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +7 -7
  425. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +7 -7
  426. package/src/core/geom/3d/ray/ray3_array_compose.js +7 -7
  427. package/src/core/geom/3d/ray/ray3_compute_nearest_point_to_point.js +7 -7
  428. package/src/core/geom/3d/ray/ray3_distance_to_point.js +7 -7
  429. package/src/core/geom/3d/ray/ray3_shift_origin_along_direction.js +7 -7
  430. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +17 -0
  431. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  432. package/src/core/geom/3d/shape/ConvexHullShape3D.js +43 -0
  433. package/src/core/geom/3d/shape/CylinderShape3D.d.ts +1 -0
  434. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  435. package/src/core/geom/3d/shape/CylinderShape3D.js +21 -0
  436. package/src/core/geom/3d/shape/PointShape3D.d.ts +7 -0
  437. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
  438. package/src/core/geom/3d/shape/PointShape3D.js +88 -63
  439. package/src/core/geom/3d/shape/PosedShape3D.d.ts +6 -0
  440. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  441. package/src/core/geom/3d/shape/PosedShape3D.js +27 -0
  442. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
  443. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  444. package/src/core/geom/3d/shape/TransformedShape3D.js +13 -0
  445. package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -0
  446. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
  447. package/src/core/geom/3d/shape/Triangle3D.js +26 -0
  448. package/src/core/geom/3d/shape/UnionShape3D.d.ts +6 -0
  449. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  450. package/src/core/geom/3d/shape/UnionShape3D.js +7 -0
  451. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -45
  452. package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -44
  453. package/src/core/geom/3d/shape/shape3_mesh_from_geometry.js +64 -64
  454. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +7 -7
  455. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -51
  456. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +7 -7
  457. package/src/core/geom/3d/sphere/compute_bounding_sphere_of_2_spheres.js +7 -7
  458. package/src/core/geom/3d/sphere/harmonics/sh3_convolve_with_zh.js +53 -53
  459. package/src/core/geom/3d/sphere/harmonics/sh3_ggx_zh.js +30 -30
  460. package/src/core/geom/3d/sphere/harmonics/sh3_rotate_bl.js +7 -7
  461. package/src/core/geom/3d/sphere/harmonics/sh_compute_K.js +7 -7
  462. package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +7 -7
  463. package/src/core/geom/3d/sphere/sphere_array_intersects_ray.js +7 -7
  464. package/src/core/geom/3d/sphere/sphere_intersects_point.js +7 -7
  465. package/src/core/geom/3d/sphere/sphere_matrix4_transform.js +5 -5
  466. package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +7 -7
  467. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +7 -7
  468. package/src/core/geom/3d/sphere/spherical_from_cartesian.js +7 -7
  469. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +174 -174
  470. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +7 -7
  471. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_volume.js +7 -7
  472. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +7 -7
  473. package/src/core/geom/3d/tetrahedra/graphics/build_tetrahedral_mesh_geometry.js +39 -39
  474. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -48
  475. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +173 -173
  476. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_compute_tet_quality.js +22 -22
  477. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -146
  478. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -232
  479. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -255
  480. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -387
  481. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -140
  482. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +7 -7
  483. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -97
  484. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -66
  485. package/src/core/geom/3d/tetrahedra/triangle/triangle_decode_depth.js +59 -59
  486. package/src/core/geom/3d/tetrahedra/triangle/triangle_rasterized_depth_sample_index.js +54 -54
  487. package/src/core/geom/3d/tetrahedra/validate_neighbour.js +70 -70
  488. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +314 -314
  489. package/src/core/geom/3d/topology/struct/binary/BinaryDataLayer.js +364 -364
  490. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +567 -567
  491. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1085 -1085
  492. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -73
  493. package/src/core/geom/3d/topology/struct/binary/io/bt_loop_kill.js +35 -35
  494. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_append.js +119 -119
  495. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +84 -84
  496. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +172 -172
  497. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +56 -56
  498. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadratics.js +7 -7
  499. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +227 -227
  500. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +161 -161
  501. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +490 -490
  502. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +120 -120
  503. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +120 -120
  504. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_collapse.js +52 -52
  505. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +115 -115
  506. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_flip.js +142 -142
  507. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -21
  508. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +92 -92
  509. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_split.js +179 -179
  510. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_swap_vertex_slots.js +28 -28
  511. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_kill_only_edge.js +8 -8
  512. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_fuse_duplicate_edges.js +83 -83
  513. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +89 -89
  514. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_kill.js +25 -25
  515. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +127 -127
  516. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -268
  517. package/src/core/geom/3d/topology/struct/binary/io/face/bt_kill_only_face.js +8 -8
  518. package/src/core/geom/3d/topology/struct/binary/io/face/bt_mesh_kill_degenerate_faces.js +72 -72
  519. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_kill_only_vert.js +7 -7
  520. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_merge_verts_by_distance.js +7 -7
  521. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_relative_merge_distance.js +48 -48
  522. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_split_pinched_vertices.js +256 -256
  523. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_vertex_merge_distance.js +77 -77
  524. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_fuse_duplicate_edges.js +7 -7
  525. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_kill.js +7 -7
  526. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +148 -148
  527. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_kill_only.js +7 -7
  528. package/src/core/geom/3d/topology/struct/binary/query/bt_collect_boundary_segments.js +29 -29
  529. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_breaks_link_condition.js +107 -107
  530. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_is_legal.js +41 -41
  531. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_would_fold.js +120 -120
  532. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -42
  533. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_is_boundary.js +20 -20
  534. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.d.ts +32 -0
  535. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.d.ts.map +1 -0
  536. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.js +59 -0
  537. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_read_diamond.js +96 -96
  538. package/src/core/geom/3d/topology/struct/binary/query/bt_face_compute_newell_normal.js +72 -72
  539. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_attached_faces.js +7 -7
  540. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces.js +39 -39
  541. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces_weighted.js +93 -93
  542. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_neighbour_faces.js +7 -7
  543. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_shared_loop.js +48 -48
  544. package/src/core/geom/3d/topology/struct/binary/query/bt_face_island_flood_fill.js +45 -45
  545. package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -66
  546. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.d.ts +26 -0
  547. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.d.ts.map +1 -0
  548. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.js +55 -0
  549. package/src/core/geom/3d/topology/struct/binary/query/bt_faces_shared_loop.js +7 -7
  550. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -44
  551. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_euclidean_distance_field.js +32 -32
  552. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_compute_face_islands.js +53 -53
  553. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -703
  554. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +181 -181
  555. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +133 -133
  556. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -82
  557. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -599
  558. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -108
  559. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +7 -7
  560. package/src/core/geom/3d/triangle/computeTriangleClosestPointToPointBarycentric.js +7 -7
  561. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +7 -7
  562. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +7 -7
  563. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +7 -7
  564. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricGeometry.js +7 -7
  565. package/src/core/geom/3d/triangle/compute_triangle_area_3d.js +7 -7
  566. package/src/core/geom/3d/triangle/compute_triangle_normal.js +7 -7
  567. package/src/core/geom/3d/triangle/rayTriangleIntersection.js +7 -7
  568. package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -65
  569. package/src/core/geom/3d/triangle/tri3_closest_point_barycentric.js +171 -171
  570. package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -79
  571. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +160 -160
  572. package/src/core/geom/3d/triangle/tri3_ray_intersection_barycentric.js +96 -96
  573. package/src/core/geom/3d/triangle/tri3_raycast.d.ts +42 -0
  574. package/src/core/geom/3d/triangle/tri3_raycast.d.ts.map +1 -0
  575. package/src/core/geom/3d/triangle/tri3_raycast.js +94 -0
  576. package/src/core/geom/3d/triangle/triangle3_incenter.js +7 -7
  577. package/src/core/geom/3d/triangle/triangle_compute_plane_side.js +7 -7
  578. package/src/core/geom/3d/triangle/triangle_compute_signed_volume.js +7 -7
  579. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +7 -7
  580. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +7 -7
  581. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +7 -7
  582. package/src/core/geom/3d/util/make_justified_point_grid.js +7 -7
  583. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +381 -381
  584. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +684 -684
  585. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -554
  586. package/src/core/geom/mat3/m3_cm_from_translation.js +7 -7
  587. package/src/core/geom/mat3/m3_cm_invert.js +7 -7
  588. package/src/core/geom/mat3/m3_make_rotation.js +5 -5
  589. package/src/core/geom/mat3/m3_make_rotation_TBN.js +31 -31
  590. package/src/core/geom/mat3/m3_multiply_vec3.js +7 -7
  591. package/src/core/geom/packing/computeBoundingSphereOfSpheres.js +7 -7
  592. package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +7 -7
  593. package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +7 -7
  594. package/src/core/geom/packing/max-rect/cutArea.js +7 -7
  595. package/src/core/geom/packing/max-rect/findBestContainer.js +7 -7
  596. package/src/core/geom/packing/max-rect/packMaxRectangles.js +7 -7
  597. package/src/core/geom/packing/max-rect/packOneBox.js +7 -7
  598. package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +7 -7
  599. package/src/core/geom/packing/max-rect/removeRedundantBoxesArray.js +7 -7
  600. package/src/core/geom/random/randomPointInBox.js +7 -7
  601. package/src/core/geom/random/randomPointInCircle.js +7 -7
  602. package/src/core/geom/random/randomPointInPoint.js +7 -7
  603. package/src/core/geom/random/randomPointInSphere.js +7 -7
  604. package/src/core/geom/random/randomPointOnBox.js +7 -7
  605. package/src/core/geom/random/randomPointOnSphere.js +7 -7
  606. package/src/core/geom/random/random_orthonormal_basis.js +31 -31
  607. package/src/core/geom/vec/vector_axpy.js +15 -15
  608. package/src/core/geom/vec/vector_axpy_offset.js +20 -20
  609. package/src/core/geom/vec/vector_copy.js +7 -7
  610. package/src/core/geom/vec/vector_dot_offset.js +25 -25
  611. package/src/core/geom/vec/vector_scale_array.js +7 -7
  612. package/src/core/geom/vec2/v2_rotate.js +21 -21
  613. package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -21
  614. package/src/core/geom/vec3/v3_angle_atan2_between.js +7 -7
  615. package/src/core/geom/vec3/v3_angle_between.js +7 -7
  616. package/src/core/geom/vec3/v3_angle_cos_between.js +7 -7
  617. package/src/core/geom/vec3/v3_array_add_in_place.js +7 -7
  618. package/src/core/geom/vec3/v3_array_centroid.js +7 -7
  619. package/src/core/geom/vec3/v3_array_copy.js +7 -7
  620. package/src/core/geom/vec3/v3_array_displace_in_direction.js +7 -7
  621. package/src/core/geom/vec3/v3_array_equals.js +7 -7
  622. package/src/core/geom/vec3/v3_array_immediate_add.js +7 -7
  623. package/src/core/geom/vec3/v3_array_matrix4_rotate.js +7 -7
  624. package/src/core/geom/vec3/v3_array_normalize.js +7 -7
  625. package/src/core/geom/vec3/v3_array_scale.js +7 -7
  626. package/src/core/geom/vec3/v3_compute_interior_angle.js +7 -7
  627. package/src/core/geom/vec3/v3_cotangent.js +33 -33
  628. package/src/core/geom/vec3/v3_dot_array_array.js +7 -7
  629. package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -30
  630. package/src/core/geom/vec3/v3_matrix3_rotate.js +49 -49
  631. package/src/core/geom/vec3/v3_matrix4_rotate.js +7 -7
  632. package/src/core/geom/vec3/v3_multiply.js +23 -23
  633. package/src/core/geom/vec3/v3_multiply_scalar.js +7 -7
  634. package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.js +49 -49
  635. package/src/core/geom/vec3/v3_quat3_apply.js +7 -7
  636. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +7 -7
  637. package/src/core/geom/vec3/v3_quaternion_apply.js +39 -39
  638. package/src/core/geom/vec3/v3_quaternion_apply_inverse.js +41 -41
  639. package/src/core/geom/vec3/v3_reflect.js +24 -24
  640. package/src/core/geom/vec3/v3_scale_array.js +18 -18
  641. package/src/core/geom/vec3/v3_triple_cross.js +45 -45
  642. package/src/core/geom/vec3/v3_triple_cross_product.js +7 -7
  643. package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -21
  644. package/src/core/geom/vec4/v4_multiply_mat4.js +7 -7
  645. package/src/core/graph/csr/csr_graph_build_distance_field.js +112 -112
  646. package/src/core/graph/csr/csr_graph_find_edge.js +25 -25
  647. package/src/core/graph/csr/csr_graph_find_shortest_path.js +105 -105
  648. package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -94
  649. package/src/core/graph/graph_k_means_cluster.js +250 -250
  650. package/src/core/graph/layout/CircleLayout.js +1 -1
  651. package/src/core/graph/layout/box/BoxLayouter.js +1 -1
  652. package/src/core/graph/layout/graph_peel_topological_layer.js +45 -45
  653. package/src/core/graph/metis/BinaryTopologyFaceGraph.js +49 -49
  654. package/src/core/graph/metis/bt_mesh_build_face_graph.js +111 -111
  655. package/src/core/graph/metis/cluster_mesh_metis.js +137 -137
  656. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -100
  657. package/src/core/graph/metis/native/bisection/compute_2way_params.js +86 -86
  658. package/src/core/graph/metis/native/bisection/fm_2way.js +297 -297
  659. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -137
  660. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -119
  661. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -94
  662. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -158
  663. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -175
  664. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -122
  665. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -170
  666. package/src/core/graph/metis/native/metis_partition_kway.js +126 -126
  667. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -53
  668. package/src/core/graph/metis/native/refine/fm_kway.js +487 -487
  669. package/src/core/graph/metis/native/refine/project_kway.js +43 -43
  670. package/src/core/graph/metis/native/refine/refine_kway.js +43 -43
  671. package/src/core/lang/reactive/pegjs/parser.js +3458 -3458
  672. package/src/core/math/complex/complex_horner_eval.js +31 -31
  673. package/src/core/math/computeWholeDivisorLow.js +33 -33
  674. package/src/core/math/f32_next_down.js +24 -24
  675. package/src/core/math/f32_next_up.js +27 -27
  676. package/src/core/math/hash/hash_mix2.js +22 -22
  677. package/src/core/math/hash/hash_mix3.js +19 -19
  678. package/src/core/math/linalg/cg/cg_solve.js +106 -106
  679. package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -59
  680. package/src/core/math/linalg/cubic_residual_times_derivative_accumulate.js +43 -43
  681. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +122 -122
  682. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +190 -190
  683. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -117
  684. package/src/core/math/linalg/givens/givens_apply_rows.js +28 -28
  685. package/src/core/math/linalg/givens/givens_apply_rows_offset.js +30 -30
  686. package/src/core/math/linalg/givens/givens_rotation_coefficients.js +39 -39
  687. package/src/core/math/linalg/lu_factor_linear_system.js +108 -108
  688. package/src/core/math/linalg/lu_solve_linear_system.js +53 -53
  689. package/src/core/math/linalg/polynomial_add_into.js +29 -29
  690. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +159 -159
  691. package/src/core/math/linalg/polynomial_cubic_derivative_eval.js +16 -16
  692. package/src/core/math/linalg/polynomial_cubic_horner_eval.js +19 -19
  693. package/src/core/math/linalg/polynomial_cubic_second_derivative_eval.js +14 -14
  694. package/src/core/math/linalg/polynomial_multiply.js +41 -41
  695. package/src/core/math/linalg/polynomial_real_roots_in_interval.js +211 -211
  696. package/src/core/math/linalg/polynomial_root_bound_cauchy.js +30 -30
  697. package/src/core/math/linalg/polynomial_scale_into.js +17 -17
  698. package/src/core/math/linalg/polynomial_sub_into.js +29 -29
  699. package/src/core/math/linalg/solve_linear_system_GEPP_2x2.js +96 -96
  700. package/src/core/math/linalg/sor_optimal_omega.js +42 -42
  701. package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -88
  702. package/src/core/math/linalg/sparse/spm_matvec.js +22 -22
  703. package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -29
  704. package/src/core/math/lookup/LUT_HEATMAP.js +30 -30
  705. package/src/core/math/lookup/ParameterLookupTable.js +495 -495
  706. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -6
  707. package/src/core/math/noise/curl_noise_3d.js +18 -18
  708. package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -28
  709. package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -48
  710. package/src/core/math/physics/kinematics/computeInterceptPoint.js +79 -79
  711. package/src/core/math/random/randomSeed.js +16 -16
  712. package/src/core/math/random/random_pick_weighted_index.js +26 -26
  713. package/src/core/math/round_half_away_from_zero.js +13 -13
  714. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -107
  715. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +125 -125
  716. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +50 -50
  717. package/src/core/math/spline/spline3_hermite_reverse.js +49 -49
  718. package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -37
  719. package/src/core/math/statistics/hammersley_sequence.js +53 -53
  720. package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
  721. package/src/core/path/convertPathToURL.js +107 -107
  722. package/src/core/process/delay.js +16 -16
  723. package/src/core/science/units/MEASUREMENT_UNITS_SCIENTIFIC.js +87 -87
  724. package/src/core/science/units/MEASUREMENT_UNITS_SI.js +17 -17
  725. package/src/core/science/units/NamedUnit.js +48 -48
  726. package/src/core/science/units/UNIT_DIMENSION_MAPPING.js +29 -29
  727. package/src/core/science/units/UnitDimension.js +28 -28
  728. package/src/core/science/units/format_quantity.js +74 -74
  729. package/src/core/science/units/magnitude_prefix.js +127 -127
  730. package/src/core/science/units/si/AMPERE.js +13 -13
  731. package/src/core/science/units/si/CANDELA.js +13 -13
  732. package/src/core/science/units/si/DIMENSIONLESS.js +14 -14
  733. package/src/core/science/units/si/KELVIN.js +13 -13
  734. package/src/core/science/units/si/KILOGRAM.js +13 -13
  735. package/src/core/science/units/si/METER.js +13 -13
  736. package/src/core/science/units/si/MOLE.js +13 -13
  737. package/src/core/science/units/si/SECOND.js +13 -13
  738. package/src/core/science/units/si/derived/BECQUEREL.js +16 -16
  739. package/src/core/science/units/si/derived/COULOMB.js +13 -13
  740. package/src/core/science/units/si/derived/FARAD.js +13 -13
  741. package/src/core/science/units/si/derived/GRAY.js +16 -16
  742. package/src/core/science/units/si/derived/HENRY.js +13 -13
  743. package/src/core/science/units/si/derived/HERTZ.js +16 -16
  744. package/src/core/science/units/si/derived/JOULE.js +13 -13
  745. package/src/core/science/units/si/derived/KATAL.js +13 -13
  746. package/src/core/science/units/si/derived/LUMEN.js +14 -14
  747. package/src/core/science/units/si/derived/LUX.js +13 -13
  748. package/src/core/science/units/si/derived/NEWTON.js +13 -13
  749. package/src/core/science/units/si/derived/OHM.js +13 -13
  750. package/src/core/science/units/si/derived/PASCAL.js +13 -13
  751. package/src/core/science/units/si/derived/SIEMENS.js +13 -13
  752. package/src/core/science/units/si/derived/SIEVERT.js +16 -16
  753. package/src/core/science/units/si/derived/TESLA.js +13 -13
  754. package/src/core/science/units/si/derived/VOLT.js +13 -13
  755. package/src/core/science/units/si/derived/WATT.js +13 -13
  756. package/src/core/science/units/si/derived/WEBER.js +13 -13
  757. package/src/core/science/units/unit_matrix_to_string.js +403 -403
  758. package/src/engine/Engine.js +726 -726
  759. package/src/engine/EngineHarness.js +590 -590
  760. package/src/engine/REVIEW_2026_07_03.md +211 -211
  761. package/src/engine/animation/AnimatedActions.js +81 -81
  762. package/src/engine/animation/AnimationUtils.js +252 -252
  763. package/src/engine/animation/async/TimeSeries.js +300 -300
  764. package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -60
  765. package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -22
  766. package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -38
  767. package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -22
  768. package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -22
  769. package/src/engine/asset/GameAssetType.d.ts +0 -1
  770. package/src/engine/asset/GameAssetType.js +0 -1
  771. package/src/engine/asset/load_model_scene_bundle.js +27 -27
  772. package/src/engine/asset/loaders/font/FontAsset.js +21 -21
  773. package/src/engine/asset/loaders/font/FontAssetLoader.js +20 -20
  774. package/src/engine/asset/loaders/gltf_test_fixtures.js +358 -358
  775. package/src/engine/asset/loaders/image/ImageBitmapAssetLoader.js +52 -52
  776. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +94 -94
  777. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.js +59 -59
  778. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +55 -55
  779. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.js +74 -74
  780. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +34 -34
  781. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +46 -46
  782. package/src/engine/control/first-person/DESIGN.md +640 -640
  783. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -563
  784. package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -134
  785. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2045 -2045
  786. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -30
  787. package/src/engine/control/first-person/math/Spring.js +71 -71
  788. package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -23
  789. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -41
  790. package/src/engine/control/first-person/math/computeMassRatios.js +44 -44
  791. package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -34
  792. package/src/engine/control/first-person/math/dampedSpringStep.js +72 -72
  793. package/src/engine/control/first-person/math/jumpDynamics.js +108 -108
  794. package/src/engine/control/first-person/math/stepTowards.js +20 -20
  795. package/src/engine/control/first-person/pose/FirstPersonPose.js +137 -137
  796. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -27
  797. package/src/engine/control/first-person/test/buildTestPlayer.js +36 -36
  798. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +531 -531
  799. package/src/engine/ecs/EntityManager.d.ts +7 -3
  800. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  801. package/src/engine/ecs/EntityManager.js +10 -5
  802. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  803. package/src/engine/ecs/async/SystemWorkerHost.js +329 -329
  804. package/src/engine/ecs/async/SystemWorkerLoopback.js +143 -143
  805. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +246 -246
  806. package/src/engine/ecs/async/WorkerSystem.js +702 -702
  807. package/src/engine/ecs/async/WorkerSystemProtocol.js +150 -150
  808. package/src/engine/ecs/fow/FogOfWar.js +707 -707
  809. package/src/engine/ecs/fow/FogOfWarEdgeMode.js +40 -40
  810. package/src/engine/ecs/fow/fog_of_war_mask_world_bounds.js +24 -24
  811. package/src/engine/ecs/fow/fog_of_war_uv_transform.js +30 -30
  812. package/src/engine/ecs/gui/hud/testHudEdgeStick.js +132 -134
  813. package/src/engine/ecs/hierarchy/EntityChildIndex.js +140 -140
  814. package/src/engine/ecs/ik/IKProblem.js +42 -42
  815. package/src/engine/ecs/ik/InverseKinematicsSystem.js +193 -193
  816. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +134 -134
  817. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +97 -97
  818. package/src/engine/ecs/ik/ik_bone_chain.js +85 -85
  819. package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -119
  820. package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
  821. package/src/engine/ecs/parent/EntityNode.js +2 -2
  822. package/src/engine/ecs/parent/ParentEntitySystem.js +255 -255
  823. package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
  824. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  825. package/src/engine/ecs/speaker/VoiceSystem.js +13 -7
  826. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +269 -269
  827. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -315
  828. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -331
  829. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -199
  830. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -57
  831. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -56
  832. package/src/engine/ecs/storage/binary/object-v2/README.md +110 -110
  833. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -48
  834. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -44
  835. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  836. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +5 -1
  837. package/src/engine/ecs/terrain/TerrainClouds.js +97 -97
  838. package/src/engine/ecs/terrain/ecs/StubTerrainBuildWorker.js +65 -65
  839. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +4 -0
  840. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  841. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  842. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +209 -209
  843. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +316 -316
  844. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +416 -416
  845. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +525 -525
  846. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +302 -302
  847. package/src/engine/ecs/terrain/tiles/TerrainTile.js +561 -561
  848. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +896 -896
  849. package/src/engine/ecs/terrain/tiles/tile_geometry_to_meshlets.js +36 -36
  850. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  851. package/src/engine/ecs/transform/Transform64.js +814 -814
  852. package/src/engine/ecs/transform/t64_copy_from_transform.js +35 -35
  853. package/src/engine/ecs/transform/t64_equals_transform.js +55 -55
  854. package/src/engine/ecs/transform/t64_look_rotation.js +36 -36
  855. package/src/engine/ecs/transform/t64_transform_direction.js +25 -25
  856. package/src/engine/ecs/transform/transform_copy_from_t64.js +28 -28
  857. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +345 -345
  858. package/src/engine/ecs/transform-attachment/transform_attachment_find_descendant_by_name.js +65 -65
  859. package/src/engine/ecs/transform-attachment/transform_attachment_parent_of.js +24 -24
  860. package/src/engine/ecs/util/hideEntityGracefully.js +208 -208
  861. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -446
  862. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -14
  863. package/src/engine/graphics/FrameThrottle.js +2 -2
  864. package/src/engine/graphics/ecs/animation/animator/graph/AnimationState.js +207 -207
  865. package/src/engine/graphics/ecs/animation/animator/graph/AnimationTransition.js +151 -151
  866. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -22
  867. package/src/engine/graphics/ecs/camera/Camera.js +165 -165
  868. package/src/engine/graphics/ecs/camera/camera_active_frustum.js +25 -25
  869. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  870. package/src/engine/graphics/ecs/camera/camera_traverse_active.js +18 -18
  871. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +170 -170
  872. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -68
  873. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +296 -296
  874. package/src/engine/graphics/ecs/decal/v2/Decal.js +220 -220
  875. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +56 -56
  876. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js +38 -38
  877. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -62
  878. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +77 -77
  879. package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -33
  880. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -88
  881. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  882. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +303 -303
  883. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.d.ts +1 -1
  884. package/src/engine/graphics/ecs/mesh-v2/aggregate/serialization/SGMeshSerializationAdapter.js +39 -39
  885. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +36 -36
  886. package/src/engine/graphics/ecs/path/tube/build/GeometryStream.js +94 -94
  887. package/src/engine/graphics/ecs/path/tube/build/build_stream_catmullrom.js +310 -310
  888. package/src/engine/graphics/ecs/path/tube/build/build_stream_linear.js +73 -73
  889. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +199 -199
  890. package/src/engine/graphics/ecs/path/tube/build/makeTubeStream.js +217 -217
  891. package/src/engine/graphics/ecs/path/tube/build/make_cap.js +340 -340
  892. package/src/engine/graphics/ecs/path/tube/build/make_ring_faces.js +40 -40
  893. package/src/engine/graphics/ecs/path/tube/build/make_ring_vertices.js +153 -153
  894. package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -64
  895. package/src/engine/graphics/ecs/trail3d/Trail3D.js +483 -483
  896. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +26 -26
  897. package/src/engine/graphics/ecs/trail3d/advance_trail.js +42 -42
  898. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +58 -58
  899. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +90 -90
  900. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +75 -75
  901. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +19 -19
  902. package/src/engine/graphics/ecs/water/Water.js +104 -104
  903. package/src/engine/graphics/geometry/AttributeData.js +84 -84
  904. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +49 -49
  905. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +288 -288
  906. package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -87
  907. package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -102
  908. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_buffered_geometry.js +52 -52
  909. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +20 -20
  910. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +19 -19
  911. package/src/engine/graphics/geometry/optimization/geometry_optimize_uv_tension.js +135 -135
  912. package/src/engine/graphics/impostors/voxel/README.md +149 -149
  913. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -141
  914. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -20
  915. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +2 -0
  916. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +1 -1
  917. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +2 -0
  918. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +1 -1
  919. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +2 -0
  920. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +1 -1
  921. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +1 -2
  922. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +1 -1
  923. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +2 -0
  924. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +1 -1
  925. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +2 -0
  926. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +1 -1
  927. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +2 -0
  928. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +1 -1
  929. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +2 -0
  930. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +1 -1
  931. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +2 -0
  932. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +1 -1
  933. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +2 -0
  934. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +1 -1
  935. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +2 -0
  936. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +1 -1
  937. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +2 -0
  938. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +1 -1
  939. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +2 -0
  940. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +1 -1
  941. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +2 -0
  942. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +1 -1
  943. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +2 -0
  944. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +1 -1
  945. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +2 -0
  946. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +1 -1
  947. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -45
  948. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +229 -229
  949. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -10
  950. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  951. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1149 -1149
  952. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +472 -472
  953. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
  954. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -2
  955. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.d.ts.map +1 -1
  956. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.js +3 -5
  957. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +135 -135
  958. package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -168
  959. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +18 -18
  960. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -2
  961. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +219 -219
  962. package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
  963. package/src/engine/graphics/render/frame_graph/FrameGraphScope.js +72 -72
  964. package/src/engine/graphics/render/frame_graph/FrameGraphState.js +39 -39
  965. package/src/engine/graphics/render/frame_graph/ResourceEntry.js +96 -96
  966. package/src/engine/graphics/render/gizmo/GizmoShapeBuffer.js +105 -105
  967. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +162 -162
  968. package/src/engine/graphics/render/layers/RenderLayer.js +95 -95
  969. package/src/engine/graphics/sh3/build_injected_shader.js +56 -56
  970. package/src/engine/graphics/sh3/grid_dilate_average.js +175 -175
  971. package/src/engine/graphics/sh3/path_tracer/BufferedGeometryBVH.js +506 -506
  972. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +161 -161
  973. package/src/engine/graphics/sh3/path_tracer/PathTracedRenderer.js +205 -205
  974. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +698 -698
  975. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +490 -490
  976. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -2
  977. package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -45
  978. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +73 -73
  979. package/src/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +32 -32
  980. package/src/engine/graphics/sh3/path_tracer/texture/apply_texture_clamping_to_coordinate.js +28 -28
  981. package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +142 -142
  982. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -70
  983. package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -388
  984. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -277
  985. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -57
  986. package/src/engine/graphics/shadows/vsm.glsl.js +43 -43
  987. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -81
  988. package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -15
  989. package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -26
  990. package/src/engine/graphics/texture/isImageBitmap.js +2 -2
  991. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -189
  992. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -51
  993. package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
  994. package/src/engine/graphics/texture/sampler/Sampler2DArray.js +172 -172
  995. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +466 -466
  996. package/src/engine/graphics/texture/sampler/compare/flip/FlipParameters.js +18 -18
  997. package/src/engine/graphics/texture/sampler/compare/flip/FlipPooling.js +33 -33
  998. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_feature_kernel.js +147 -147
  999. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_spatial_kernel.js +177 -177
  1000. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_color_difference.js +104 -104
  1001. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_feature_difference.js +76 -76
  1002. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_pixels_per_degree.js +34 -34
  1003. package/src/engine/graphics/texture/sampler/compare/flip/flip_constants.js +77 -77
  1004. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_feature.js +48 -48
  1005. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_spatial.js +86 -86
  1006. package/src/engine/graphics/texture/sampler/compare/flip/flip_pool.js +71 -71
  1007. package/src/engine/graphics/texture/sampler/compare/flip/flip_srgb_to_ycxcz.js +55 -55
  1008. package/src/engine/graphics/texture/sampler/compare/flip/sampler2d_flip_ldr.js +80 -80
  1009. package/src/engine/graphics/texture/sampler/filter/SeparableKernel.js +82 -82
  1010. package/src/engine/graphics/texture/sampler/filter/sampler2d_convolve_separable.js +122 -122
  1011. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +148 -148
  1012. package/src/engine/graphics/texture/sampler/sampler2d_channel_apply_lut.js +82 -82
  1013. package/src/engine/graphics/texture/sampler/sampler2d_combine.js +67 -67
  1014. package/src/engine/graphics/texture/sampler/sampler2d_linear_f16_to_srgb_u8.js +54 -54
  1015. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -63
  1016. package/src/engine/graphics/texture/sampler/sampler2d_srgb_to_linear.js +33 -33
  1017. package/src/engine/graphics/texture/sampler/sampler2d_srgb_u8_to_linear_f16.js +68 -68
  1018. package/src/engine/graphics/texture/shade_image_preview.js +103 -103
  1019. package/src/engine/graphics/trail/TrailSpawnMode.js +20 -20
  1020. package/src/engine/graphics/trail/tube/TubeX.js +573 -573
  1021. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +58 -58
  1022. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +34 -34
  1023. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +69 -69
  1024. package/src/engine/graphics/trail/tube/tube_frame.js +83 -83
  1025. package/src/engine/graphics3/AnimationGraphSystem3.js +329 -329
  1026. package/src/engine/graphics3/AnimationSystem3.js +352 -352
  1027. package/src/engine/graphics3/CameraSystem3.js +170 -170
  1028. package/src/engine/graphics3/DecalSystem3.js +441 -441
  1029. package/src/engine/graphics3/FogOfWarSystem3.js +265 -265
  1030. package/src/engine/graphics3/GraphicsEngine3.js +776 -776
  1031. package/src/engine/graphics3/HighlightSystem3.js +241 -241
  1032. package/src/engine/graphics3/LightSystem3.js +211 -211
  1033. package/src/engine/graphics3/MeshSystem3.js +646 -646
  1034. package/src/engine/graphics3/ParticleEmitterSystem3.js +289 -289
  1035. package/src/engine/graphics3/PathDisplaySystem3.js +309 -309
  1036. package/src/engine/graphics3/PickingQuery.js +48 -48
  1037. package/src/engine/graphics3/PickingResult.js +47 -47
  1038. package/src/engine/graphics3/PickingSystem3.js +273 -273
  1039. package/src/engine/graphics3/ShadeCameraAdapter.js +55 -55
  1040. package/src/engine/graphics3/ShadedGeometrySystem3.js +169 -169
  1041. package/src/engine/graphics3/TerrainSystem3.js +566 -566
  1042. package/src/engine/graphics3/TooltipComponentSystem3.js +328 -328
  1043. package/src/engine/graphics3/Trail3DSystem3.js +221 -221
  1044. package/src/engine/graphics3/VolumetricLightMap.d.ts +90 -0
  1045. package/src/engine/graphics3/VolumetricLightMap.d.ts.map +1 -0
  1046. package/src/engine/graphics3/VolumetricLightMap.js +160 -0
  1047. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.d.ts +32 -0
  1048. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.d.ts.map +1 -0
  1049. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.js +67 -0
  1050. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts +98 -0
  1051. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts.map +1 -0
  1052. package/src/engine/graphics3/VolumetricLightMapSystem3.js +261 -0
  1053. package/src/engine/graphics3/WaterSystem3.js +293 -293
  1054. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  1055. package/src/engine/graphics3/animation/wrap_clip_time.js +23 -23
  1056. package/src/engine/graphics3/animation/write_graph_playback.js +48 -48
  1057. package/src/engine/graphics3/camera_sync_from_transform.js +29 -29
  1058. package/src/engine/graphics3/debug/gizmo_view_from_camera.js +48 -48
  1059. package/src/engine/graphics3/decal/DECAL_CLUSTER.js +61 -61
  1060. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +117 -117
  1061. package/src/engine/graphics3/decal/DecalAtlas.js +194 -194
  1062. package/src/engine/graphics3/decal/DecalAtlasFill.js +32 -32
  1063. package/src/engine/graphics3/decal/GPUDecalRenderer.js +360 -360
  1064. package/src/engine/graphics3/decal/chunk_decal_intersects_frustum.js +59 -59
  1065. package/src/engine/graphics3/decal/chunk_decal_sampling_info.js +57 -57
  1066. package/src/engine/graphics3/decal/chunk_decal_surface_frame.js +54 -54
  1067. package/src/engine/graphics3/decal/decal_atlas_border.js +69 -69
  1068. package/src/engine/graphics3/decal/decal_gpu_records.js +120 -120
  1069. package/src/engine/graphics3/decal/decal_material_samplers.js +109 -109
  1070. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +212 -212
  1071. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +207 -207
  1072. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +108 -108
  1073. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +151 -151
  1074. package/src/engine/graphics3/highlight/HIGHLIGHT_OUTLINE.js +23 -23
  1075. package/src/engine/graphics3/highlight/chunk_highlight_lookup.js +53 -53
  1076. package/src/engine/graphics3/highlight/pack_highlight_color.js +44 -44
  1077. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  1078. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  1079. package/src/engine/graphics3/load_cube_environment.js +68 -68
  1080. package/src/engine/graphics3/make_default_environment.js +107 -107
  1081. package/src/engine/graphics3/particles/particle_gpu_records.js +221 -221
  1082. package/src/engine/graphics3/path/build_tube_path_streams.js +98 -98
  1083. package/src/engine/graphics3/path/tube_stream_write_geometry.js +90 -90
  1084. package/src/engine/graphics3/preview/ModelPreviewFraming.js +35 -35
  1085. package/src/engine/graphics3/preview/make_model_preview_scene.js +154 -154
  1086. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  1087. package/src/engine/graphics3/preview/model_preview_framing.js +70 -70
  1088. package/src/engine/graphics3/shade_bundle_bounds.js +55 -55
  1089. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  1090. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  1091. package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.js +481 -481
  1092. package/src/engine/graphics3/terrain/chunk_terrain_grid_overlay.js +61 -61
  1093. package/src/engine/graphics3/terrain/chunk_terrain_splat_mix.js +66 -66
  1094. package/src/engine/graphics3/terrain/pack_terrain_row_table.js +53 -53
  1095. package/src/engine/graphics3/terrain/shader_terrain_splat.js +215 -215
  1096. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +158 -158
  1097. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
  1098. package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
  1099. package/src/engine/input/devices/GamepadDevice.js +466 -466
  1100. package/src/engine/input/devices/ManualInputDevice.js +152 -152
  1101. package/src/engine/input/devices/PointerCoordinates.js +26 -26
  1102. package/src/engine/input/devices/events/GamepadEvents.js +10 -10
  1103. package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
  1104. package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
  1105. package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
  1106. package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
  1107. package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
  1108. package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
  1109. package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
  1110. package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
  1111. package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
  1112. package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
  1113. package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
  1114. package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
  1115. package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
  1116. package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
  1117. package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
  1118. package/src/engine/input/ecs/components/Input.js +118 -118
  1119. package/src/engine/input/ecs/components/InputController.js +78 -78
  1120. package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
  1121. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
  1122. package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
  1123. package/src/engine/input/ecs/ism/InputBinding.js +71 -71
  1124. package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
  1125. package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
  1126. package/src/engine/input/ecs/ism/InputDirection.js +33 -33
  1127. package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
  1128. package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
  1129. package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
  1130. package/src/engine/input/ecs/ism/InputSource.js +67 -67
  1131. package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
  1132. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
  1133. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
  1134. package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
  1135. package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
  1136. package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
  1137. package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
  1138. package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
  1139. package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
  1140. package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
  1141. package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
  1142. package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
  1143. package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
  1144. package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
  1145. package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
  1146. package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
  1147. package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
  1148. package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
  1149. package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
  1150. package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
  1151. package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
  1152. package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
  1153. package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
  1154. package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
  1155. package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
  1156. package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
  1157. package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
  1158. package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
  1159. package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
  1160. package/src/engine/input/ecs/systems/InputSystem.js +162 -162
  1161. package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
  1162. package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
  1163. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
  1164. package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
  1165. package/src/engine/interpolation/Interpoland.js +49 -49
  1166. package/src/engine/interpolation/Interpolated.js +149 -149
  1167. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
  1168. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
  1169. package/src/engine/interpolation/pose_interpoland.js +27 -27
  1170. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  1171. package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
  1172. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
  1173. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
  1174. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
  1175. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
  1176. package/src/engine/network/CONGESTION_CONTROL.md +87 -87
  1177. package/src/engine/network/README.md +52 -52
  1178. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
  1179. package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
  1180. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
  1181. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
  1182. package/src/engine/network/convertPathToURL.js +2 -2
  1183. package/src/engine/network/core/MalformedPacketError.js +26 -26
  1184. package/src/engine/network/core/quantize/quantize_float.js +73 -73
  1185. package/src/engine/network/core/quantize/quantize_position.js +65 -65
  1186. package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
  1187. package/src/engine/network/core/sequence/seq16.js +69 -69
  1188. package/src/engine/network/core/sequence/seq32.js +73 -73
  1189. package/src/engine/network/ecs/NetworkSystem.js +84 -84
  1190. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
  1191. package/src/engine/network/ecs/owner_authorization.js +55 -55
  1192. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
  1193. package/src/engine/network/replication/ScopeFilter.js +71 -71
  1194. package/src/engine/network/sim/ActionLog.js +152 -152
  1195. package/src/engine/network/sim/SimAction.js +273 -273
  1196. package/src/engine/network/sim/Snapshotter.js +222 -222
  1197. package/src/engine/network/state/FrameBufferRing.js +168 -168
  1198. package/src/engine/network/state/InputRing.js +134 -134
  1199. package/src/engine/network/state/PriorityAccumulator.js +180 -180
  1200. package/src/engine/network/time/TimeDilation.js +62 -62
  1201. package/src/engine/network/transport/Channel.js +336 -336
  1202. package/src/engine/network/transport/Transport.js +203 -203
  1203. package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
  1204. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
  1205. package/src/engine/network/transport/fragments/fragment_send.js +147 -147
  1206. package/src/engine/network/transport/fragments/packet_size.js +101 -101
  1207. package/src/engine/network/xhr.js +23 -23
  1208. package/src/engine/physics/BULLET_REVIEW.md +945 -945
  1209. package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
  1210. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
  1211. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
  1212. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
  1213. package/src/engine/physics/JOLT_REVIEW.md +913 -913
  1214. package/src/engine/physics/PLAN.md +1120 -1094
  1215. package/src/engine/physics/RAPIER_REVIEW.md +934 -934
  1216. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
  1217. package/src/engine/physics/REVIEW_002.md +151 -151
  1218. package/src/engine/physics/REVIEW_003.md +166 -166
  1219. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
  1220. package/src/engine/physics/constraint/DofMode.js +35 -35
  1221. package/src/engine/physics/constraint/solve_constraints.js +1 -1
  1222. package/src/engine/physics/contact/combine_material.js +35 -35
  1223. package/src/engine/physics/ecs/BodyKind.js +29 -29
  1224. package/src/engine/physics/ecs/Collider.js +177 -177
  1225. package/src/engine/physics/ecs/ColliderFlags.js +15 -15
  1226. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
  1227. package/src/engine/physics/ecs/Joint.js +475 -475
  1228. package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
  1229. package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
  1230. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  1231. package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
  1232. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
  1233. package/src/engine/physics/ecs/SleepState.js +12 -12
  1234. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
  1235. package/src/engine/physics/fluid/FluidField.js +867 -867
  1236. package/src/engine/physics/fluid/FluidSimulator.js +832 -832
  1237. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
  1238. package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
  1239. package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
  1240. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
  1241. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
  1242. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  1243. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
  1244. package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
  1245. package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
  1246. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
  1247. package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
  1248. package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
  1249. package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
  1250. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
  1251. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
  1252. package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
  1253. package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
  1254. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
  1255. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
  1256. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
  1257. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
  1258. package/src/engine/physics/fluid/prototype.js +126 -126
  1259. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
  1260. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
  1261. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
  1262. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
  1263. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
  1264. package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
  1265. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
  1266. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
  1267. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
  1268. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
  1269. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
  1270. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
  1271. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
  1272. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
  1273. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
  1274. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
  1275. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
  1276. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
  1277. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
  1278. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
  1279. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
  1280. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
  1281. package/src/engine/physics/integration/integrate_position.js +97 -97
  1282. package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
  1283. package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
  1284. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
  1285. package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
  1286. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
  1287. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
  1288. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  1289. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
  1290. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
  1291. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
  1292. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  1293. package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
  1294. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
  1295. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
  1296. package/src/engine/physics/persistence/solver_caches.js +309 -309
  1297. package/src/engine/physics/queries/overlap_shape.js +187 -187
  1298. package/src/engine/physics/queries/raycast.d.ts +7 -4
  1299. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  1300. package/src/engine/physics/queries/raycast.js +11 -5
  1301. package/src/engine/physics/queries/shape_cast.js +417 -417
  1302. package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
  1303. package/src/engine/physics/solver/friction_cone.js +37 -37
  1304. package/src/engine/physics/solver/solve_contacts.js +1 -1
  1305. package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
  1306. package/src/engine/platform/WebEnginePlatform.js +1 -2
  1307. package/src/engine/scene/SerializedScene.d.ts +2 -2
  1308. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  1309. package/src/engine/scene/transitionToScene.js +121 -121
  1310. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  1311. package/src/engine/simulation/Ticker.js +33 -0
  1312. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
  1313. package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
  1314. package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
  1315. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
  1316. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
  1317. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
  1318. package/src/engine/sound/simulation/README.md +277 -277
  1319. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
  1320. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
  1321. package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
  1322. package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
  1323. package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
  1324. package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
  1325. package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
  1326. package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
  1327. package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
  1328. package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
  1329. package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
  1330. package/src/engine/sound/simulation/core/RayHit.js +50 -50
  1331. package/src/engine/sound/simulation/core/VolumeField.js +149 -149
  1332. package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
  1333. package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
  1334. package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
  1335. package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
  1336. package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
  1337. package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
  1338. package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
  1339. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
  1340. package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
  1341. package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
  1342. package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
  1343. package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
  1344. package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
  1345. package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
  1346. package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
  1347. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
  1348. package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
  1349. package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
  1350. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
  1351. package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
  1352. package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
  1353. package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
  1354. package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
  1355. package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
  1356. package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
  1357. package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
  1358. package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
  1359. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
  1360. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
  1361. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
  1362. package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
  1363. package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
  1364. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
  1365. package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
  1366. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
  1367. package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
  1368. package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
  1369. package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
  1370. package/src/engine/sound/sopra/README.md +643 -643
  1371. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  1372. package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
  1373. package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
  1374. package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
  1375. package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
  1376. package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
  1377. package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
  1378. package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
  1379. package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
  1380. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
  1381. package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
  1382. package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
  1383. package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
  1384. package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
  1385. package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
  1386. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
  1387. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
  1388. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
  1389. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
  1390. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
  1391. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
  1392. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
  1393. package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
  1394. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
  1395. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
  1396. package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
  1397. package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
  1398. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
  1399. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  1400. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
  1401. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
  1402. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
  1403. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
  1404. package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
  1405. package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
  1406. package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
  1407. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
  1408. package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
  1409. package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
  1410. package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
  1411. package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
  1412. package/src/engine/sound/sopra/runtime/Voice.js +145 -145
  1413. package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
  1414. package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
  1415. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
  1416. package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
  1417. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
  1418. package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
  1419. package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
  1420. package/src/engine/ui/DraggableAspect.js +115 -115
  1421. package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
  1422. package/src/generation/COORDINATES.md +54 -54
  1423. package/src/generation/GridGenerationResource.js +24 -24
  1424. package/src/generation/GridTaskGroup.js +214 -214
  1425. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
  1426. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
  1427. package/src/generation/automata/CellularAutomata.js +22 -22
  1428. package/src/generation/compute_writes_union.js +25 -25
  1429. package/src/generation/filtering/CellFilter.js +117 -117
  1430. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
  1431. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
  1432. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
  1433. package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
  1434. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
  1435. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
  1436. package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
  1437. package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
  1438. package/src/generation/grid/GridData.js +233 -233
  1439. package/src/generation/grid/coords/grid_to_texel.js +10 -10
  1440. package/src/generation/grid/coords/texel_to_grid.js +10 -10
  1441. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
  1442. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
  1443. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
  1444. package/src/generation/grid/generation/GridTaskSequence.js +58 -58
  1445. package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
  1446. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
  1447. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
  1448. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
  1449. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
  1450. package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
  1451. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
  1452. package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
  1453. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
  1454. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
  1455. package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
  1456. package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
  1457. package/src/generation/placement/action/GridCellAction.js +45 -45
  1458. package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
  1459. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
  1460. package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
  1461. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
  1462. package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
  1463. package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
  1464. package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
  1465. package/src/generation/theme/ThemeEngine.js +666 -666
  1466. package/src/shade/RENDERER_CONTRACT.md +568 -568
  1467. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
  1468. package/src/shade/device/ShadeDeviceFailure.js +104 -104
  1469. package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
  1470. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
  1471. package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
  1472. package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
  1473. package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
  1474. package/src/shade/device/mock/SoftwareGPUError.js +63 -63
  1475. package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
  1476. package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
  1477. package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
  1478. package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
  1479. package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
  1480. package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
  1481. package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
  1482. package/src/shade/device/mock/texture_copy.js +287 -287
  1483. package/src/shade/device/timing/GPUTimer.js +285 -285
  1484. package/src/shade/device/timing/GPUTimerArray.js +205 -205
  1485. package/src/shade/playground/add_random_lights.js +49 -49
  1486. package/src/shade/playground/add_random_meshes.js +83 -83
  1487. package/src/shade/playground/animation_prototype.js +508 -508
  1488. package/src/shade/playground/animation_prototype_skinning.js +647 -647
  1489. package/src/shade/playground/animation_prototype_stress.js +765 -765
  1490. package/src/shade/playground/enable_picker.js +59 -59
  1491. package/src/shade/playground/gltf_skinned_prototype.js +560 -560
  1492. package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
  1493. package/src/shade/playground/gltf_viewer.js +282 -282
  1494. package/src/shade/playground/load_default_environment.js +19 -19
  1495. package/src/shade/playground/main.js +2727 -2727
  1496. package/src/shade/playground/make_animated_instances.js +117 -117
  1497. package/src/shade/playground/prototype_virtual_texture.js +274 -274
  1498. package/src/shade/playground/prototype_volumetrics_01.js +206 -206
  1499. package/src/shade/playground/sample.js +234 -234
  1500. package/src/shade/playground/sample_load_gltf.js +102 -102
  1501. package/src/shade/playground/spread_node3d_grid.js +19 -19
  1502. package/src/shade/renderer/Renderer.js +2436 -2436
  1503. package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
  1504. package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
  1505. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
  1506. package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
  1507. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
  1508. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
  1509. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
  1510. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
  1511. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
  1512. package/src/shade/renderer/binding/BindGroupManager.js +282 -282
  1513. package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
  1514. package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
  1515. package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
  1516. package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
  1517. package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
  1518. package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
  1519. package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
  1520. package/src/shade/renderer/camera/Camera.js +281 -281
  1521. package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
  1522. package/src/shade/renderer/camera/orbital/README.md +84 -84
  1523. package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
  1524. package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
  1525. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
  1526. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  1527. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
  1528. package/src/shade/renderer/extension/FrameContext.js +263 -263
  1529. package/src/shade/renderer/extension/FramePhase.js +104 -104
  1530. package/src/shade/renderer/extension/FrameRecord.js +126 -126
  1531. package/src/shade/renderer/extension/GBufferTextures.js +83 -83
  1532. package/src/shade/renderer/extension/PresentTarget.js +34 -34
  1533. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  1534. package/src/shade/renderer/extension/RenderExtension.js +69 -69
  1535. package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
  1536. package/src/shade/renderer/extension/SceneColor.js +40 -40
  1537. package/src/shade/renderer/extension/ViewTextures.js +78 -78
  1538. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
  1539. package/src/shade/renderer/geometry/Geometry.js +608 -608
  1540. package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
  1541. package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
  1542. package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
  1543. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
  1544. package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
  1545. package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
  1546. package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
  1547. package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
  1548. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
  1549. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
  1550. package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
  1551. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
  1552. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
  1553. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
  1554. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
  1555. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
  1556. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
  1557. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
  1558. package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
  1559. package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
  1560. package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
  1561. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
  1562. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
  1563. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
  1564. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
  1565. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
  1566. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
  1567. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
  1568. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
  1569. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
  1570. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
  1571. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
  1572. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
  1573. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
  1574. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
  1575. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
  1576. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
  1577. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
  1578. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
  1579. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
  1580. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
  1581. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
  1582. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
  1583. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
  1584. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
  1585. package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
  1586. package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
  1587. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
  1588. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
  1589. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
  1590. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
  1591. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
  1592. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
  1593. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
  1594. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
  1595. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
  1596. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
  1597. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
  1598. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
  1599. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
  1600. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
  1601. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
  1602. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
  1603. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
  1604. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
  1605. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
  1606. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
  1607. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
  1608. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
  1609. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
  1610. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
  1611. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
  1612. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
  1613. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
  1614. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
  1615. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
  1616. package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
  1617. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
  1618. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
  1619. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
  1620. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
  1621. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
  1622. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
  1623. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
  1624. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
  1625. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
  1626. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
  1627. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
  1628. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
  1629. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
  1630. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
  1631. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
  1632. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
  1633. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
  1634. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
  1635. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
  1636. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
  1637. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
  1638. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
  1639. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
  1640. package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
  1641. package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
  1642. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
  1643. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
  1644. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
  1645. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
  1646. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
  1647. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
  1648. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
  1649. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
  1650. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
  1651. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
  1652. package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
  1653. package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
  1654. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
  1655. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
  1656. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
  1657. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
  1658. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
  1659. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
  1660. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.d.ts +23 -0
  1661. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.d.ts.map +1 -0
  1662. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.js +34 -0
  1663. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
  1664. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
  1665. package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
  1666. package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
  1667. package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
  1668. package/src/shade/renderer/light/make_sunlight.js +35 -35
  1669. package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
  1670. package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
  1671. package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
  1672. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
  1673. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
  1674. package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
  1675. package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
  1676. package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
  1677. package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
  1678. package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
  1679. package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
  1680. package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
  1681. package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
  1682. package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
  1683. package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
  1684. package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
  1685. package/src/shade/renderer/loader/usd/UsdError.js +33 -33
  1686. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
  1687. package/src/shade/renderer/loader/usd/load_usd.js +226 -226
  1688. package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
  1689. package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
  1690. package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
  1691. package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
  1692. package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
  1693. package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
  1694. package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
  1695. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
  1696. package/src/shade/renderer/material/ShadeMaterial.js +2 -2
  1697. package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
  1698. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  1699. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
  1700. package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
  1701. package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
  1702. package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
  1703. package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
  1704. package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
  1705. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
  1706. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
  1707. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
  1708. package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
  1709. package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
  1710. package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
  1711. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
  1712. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
  1713. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
  1714. package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
  1715. package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
  1716. package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
  1717. package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
  1718. package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
  1719. package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
  1720. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
  1721. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
  1722. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
  1723. package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
  1724. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
  1725. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
  1726. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
  1727. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
  1728. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
  1729. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
  1730. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
  1731. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
  1732. package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
  1733. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
  1734. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
  1735. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
  1736. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
  1737. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
  1738. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
  1739. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
  1740. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
  1741. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
  1742. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
  1743. package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
  1744. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
  1745. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
  1746. package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
  1747. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
  1748. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
  1749. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
  1750. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
  1751. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
  1752. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  1753. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
  1754. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
  1755. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
  1756. package/src/shade/renderer/scene/DynamicMesh.js +70 -70
  1757. package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
  1758. package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
  1759. package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
  1760. package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
  1761. package/src/shade/renderer/scene/TransformAuthority.js +33 -33
  1762. package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
  1763. package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
  1764. package/src/shade/renderer/scene/optimization/geometry/internal/anchor_grow_topological.d.ts.map +1 -1
  1765. package/src/shade/renderer/scene/optimization/geometry/internal/anchor_grow_topological.js +12 -3
  1766. package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
  1767. package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
  1768. package/src/shade/renderer/scene/optimization/geometry/internal/match_validate_topology.js +3 -3
  1769. package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_window.js +3 -3
  1770. package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
  1771. package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
  1772. package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
  1773. package/src/shade/renderer/scene/serialization/deserialize_scene.d.ts.map +1 -1
  1774. package/src/shade/renderer/scene/serialization/deserialize_scene.js +0 -2
  1775. package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
  1776. package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
  1777. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
  1778. package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
  1779. package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
  1780. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
  1781. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
  1782. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
  1783. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
  1784. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
  1785. package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
  1786. package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
  1787. package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
  1788. package/src/shade/renderer/texture/virtual/README.md +276 -276
  1789. package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
  1790. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
  1791. package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
  1792. package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
  1793. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
  1794. package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
  1795. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
  1796. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
  1797. package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
  1798. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
  1799. package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
  1800. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
  1801. package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
  1802. package/src/shade/renderer/water/shader_water.js +246 -246
  1803. package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
  1804. package/src/shade/vitest.setup.mjs +89 -89
  1805. package/src/shade/wgsl/validate_wgsl_source.js +316 -316
  1806. package/src/view/controller/controls/NumericIntervalControl.js +90 -90
  1807. package/src/view/controller/controls/Vector2Control.js +83 -83
  1808. package/src/view/controller/controls/Vector3Control.js +90 -90
  1809. package/src/view/elements/Group.js +56 -56
  1810. package/src/view/elements/drawCheckers.js +33 -33
  1811. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  1812. package/src/view/graphics/WebGLContextFailureView.js +76 -76
  1813. package/src/view/layout/DockPanel.js +51 -51
  1814. package/src/view/layout/SplitView.js +365 -365
  1815. package/src/view/layout/show_popup_menu.js +81 -81
  1816. package/src/view/minimap/MinimapCanvasView.js +411 -411
  1817. package/src/view/minimap/MinimapImageCache.js +88 -88
  1818. package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
  1819. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  1820. package/src/view/minimap/MinimapMarkerCollection.js +180 -180
  1821. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  1822. package/src/view/minimap/minimap_focus_area.js +97 -97
  1823. package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
  1824. package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
  1825. package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
  1826. package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
  1827. package/src/engine/ecs/attachment/Attachment.js +0 -57
  1828. package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
  1829. package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
  1830. package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
  1831. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
  1832. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
  1833. package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
  1834. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
  1835. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
  1836. package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
  1837. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
  1838. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
  1839. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
  1840. package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
  1841. package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
  1842. package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
  1843. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
  1844. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
  1845. package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
  1846. package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
  1847. package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
  1848. package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
  1849. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
  1850. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
  1851. package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
  1852. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
  1853. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
  1854. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
  1855. package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
  1856. package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
  1857. package/src/shade/renderer/animation/_dump_resolve.mjs +0 -5
  1858. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.d.ts +0 -32
  1859. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.d.ts.map +0 -1
  1860. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.js +0 -77
  1861. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.d.ts +0 -12
  1862. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.d.ts.map +0 -1
  1863. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.js +0 -35
  1864. package/src/shade/renderer/scene/serialization/linear_to_pq.d.ts +0 -2
  1865. package/src/shade/renderer/scene/serialization/linear_to_pq.d.ts.map +0 -1
  1866. package/src/shade/renderer/scene/serialization/linear_to_pq.js +0 -14
  1867. package/src/shade/renderer/scene/serialization/pq_to_linear.d.ts +0 -9
  1868. package/src/shade/renderer/scene/serialization/pq_to_linear.d.ts.map +0 -1
  1869. package/src/shade/renderer/scene/serialization/pq_to_linear.js +0 -30
@@ -1,667 +1,667 @@
1
- # Correctness review — `meep/src/view/`
2
-
3
- Scope: all 111 non-spec source files under `H:/git/moh/app/src/mir-engine/meep/src/view/`.
4
- Excluded: `editor/`, `prototype*.js`, `*.spec.js`, `.d.ts`.
5
-
6
- Notes on evidence used while reviewing:
7
- - `View.unlink()` **clears the `Linked` flag before dispatching `on.unlinked`** (`View.js:325` then `:347`). Several
8
- findings below depend on that ordering.
9
- - `Signal` keeps handlers in a `Map` keyed by the handler function; iteration is insertion-ordered, and a handler
10
- removed mid-dispatch by an earlier handler is **not** invoked (`core/events/signal/Signal.js:378-425`).
11
- - `Vector1`/`ObservedInteger` extend `Number` and implement `valueOf()`, so arithmetic directly on them is valid.
12
- - `segment2_segment_compute_intersection_array_2d` leaves `result` **untouched** and returns `false` on a miss.
13
-
14
- ---
15
-
16
- ### VIEW-1 `DomTooltipObserver.unlink()` never actually detaches, because the view is already unlinked
17
- - **Severity**: CRITICAL
18
- - **File**: `src/view/tooltip/DomTooltipObserver.js:156-165`, driven from `src/view/tooltip/DomTooltipManager.js:109-117,178-194`
19
- - **Defect**: `unlink()` only runs `__handleViewUnlinked()` `if (view.isLinked)`. On the `manage()` path the call
20
- arrives from inside the `view.on.unlinked` dispatch, at which point `View.unlink()` has already cleared the
21
- `Linked` flag — so the guard is always false and the teardown is skipped entirely. The observer's own
22
- `on.unlinked` handler cannot compensate: `manage()`'s handler was subscribed first, and it calls
23
- `observer.unlink()`, which does `view.on.unlinked.remove(this.__handleViewUnlinked, this)` mid-dispatch, deleting
24
- the not-yet-visited Map entry so it never fires.
25
- - **Failure scenario**: `gui.viewTooltips.manage(button, factory)` (used in ~20 places, e.g.
26
- `interaction/createInterfaceCommandButton.js:106`, `view/game/scene/strategy/shop/ItemShopView.js:185`). Link the
27
- panel, then unlink it. `mouseenter`/`mouseleave` listeners stay on `button.el`, and the 4 `SignalBinding`s on
28
- `view.position.onChanged`, `view.size.onChanged` and the `DomSizeObserver` stay linked forever. Re-open the panel
29
- and `manage()`'s linked handler calls `add()` again, creating a *second* observer with a second pair of DOM
30
- listeners on the same element. Ten open/close cycles leave ten live observers per button. Worse: hover a button,
31
- and inside the 128 ms `requestShow` delay close the panel — `remove()` calls `hide()` (no-op, tip not added yet),
32
- the observer teardown is skipped so nothing calls `cancelShowRequest()`, the timeout fires, `tipManager.add(tip)`
33
- builds a tooltip for a detached view, and because the element no longer receives mouse events nothing will ever
34
- fire `on.exited` → the tooltip is stuck on screen for the rest of the session.
35
- - **Fix**: drop the `view.isLinked` guard in `unlink()` and make `__handleViewUnlinked()` idempotent (track an
36
- internal `#attached` boolean set in `__handleViewLinked`), and remove the `view.on.*` handlers *before* calling
37
- `__handleViewUnlinked()`. Additionally call `this.cancelShowRequest()` in `DomTooltipManager.remove()`.
38
- - **Confidence**: Confirmed
39
-
40
- ### VIEW-2 `SvgImageView` cannot be imported and crashes on every `link()`
41
- - **Severity**: CRITICAL
42
- - **File**: `src/view/elements/image/SvgImageView.js:1,64-73`
43
- - **Defect**: Two independent hard errors. (a) `import AABB2 from "../../../core/geom/AABB2.js"` — that file does not
44
- exist; the real path is `core/geom/2d/aabb/AABB2.js`, so the module fails to resolve. (b) `update()` is a class
45
- method but its body references `resize` and `self`, which are `const`/`let` bindings local to the *constructor*.
46
- `link()` calls `this.update()` unconditionally.
47
- - **Failure scenario**: any module that does `import SvgImageView from '.../SvgImageView.js'` fails at bundle/resolve
48
- time. If the import path is fixed, `new SvgImageView(url, {assetManager}); parent.addChild(v)` on a linked parent →
49
- `link()` → `update()` → `ReferenceError: resize is not defined` (caught by Signal only if it were dispatched from a
50
- signal; here it propagates out of `addChild`).
51
- - **Fix**: correct the import path; promote `resize` and the icon element to instance state (`#resize()` reading
52
- `this.#elIcon`, `this.size`) so `update()` can reach them.
53
- - **Confidence**: Confirmed
54
-
55
- ### VIEW-3 `MinimapMarkerView` throws on construction — `this` used before `super()`
56
- - **Severity**: CRITICAL
57
- - **File**: `src/view/minimap/dom/MinimapMarkerView.js:17,51-64`
58
- - **Defect**: `super(entity, this.marker, this.transform, this.worldScale)` dereferences `this` before the base
59
- constructor has run, which is a `ReferenceError` in every ES2015+ engine. Even past that, the three handler methods
60
- reference `setPosition` and `size`, which are constructor-local bindings, and they are bound via `bindSignal(...)`
61
- **without a context argument**, so `this` inside them would be `undefined`.
62
- - **Failure scenario**: `new MinimapMarkerView(entity, marker, transform, worldScale)` →
63
- `ReferenceError: Must call super constructor in derived class before accessing 'this'`. The class is unusable.
64
- - **Fix**: `super()` with no arguments; move `setPosition` to a method and pass `this` as the context to every
65
- `bindSignal` call; read `this.size` instead of the free `size`.
66
- - **Confidence**: Confirmed
67
-
68
- ### VIEW-4 `MinimapTerrainView.__setTerrain` references an undefined identifier and has no context
69
- - **Severity**: CRITICAL
70
- - **File**: `src/view/minimap/dom/MinimapTerrainView.js:126,133-143`
71
- - **Defect**: `this.terrain.onChanged.add(this.__setTerrain)` subscribes a *method* with no context, and the method
72
- body calls `updatePreview()` — a function declared inside the constructor and therefore not in scope. It also
73
- dereferences `terrain.preview` with no null check even though `ObservedValue(null)` is the initial state and
74
- `set(null)` is a legal transition.
75
- - **Failure scenario**: `minimapTerrainView.terrain.set(someTerrain)` → `__setTerrain` runs →
76
- `ReferenceError: updatePreview is not defined` (swallowed by Signal's try/catch and logged) → the terrain preview
77
- image is never set, the view renders an empty `<img>`. `terrain.set(null)` →
78
- `TypeError: Cannot read properties of null (reading 'preview')`.
79
- - **Fix**: make `updatePreview`/`setPreview` instance methods, subscribe with `add(this.__setTerrain, this)`, and
80
- guard the `terrain === null` case.
81
- - **Confidence**: Confirmed
82
-
83
- ### VIEW-5 `ViewGroup.remove()` calls a non-existent `Set.remove`; `disconnect()` adds instead of removes
84
- - **Severity**: CRITICAL
85
- - **File**: `src/view/ViewGroup.js:34,74-89`
86
- - **Defect**: `this.elements` is a `Set`; `Set` has `delete`, not `remove`. Separately, `disconnect()` iterates every
87
- member and calls `this.container.addChild(view)` where the whole point of the method is to detach them.
88
- - **Failure scenario**: `group.remove(view)` → `TypeError: this.elements.remove is not a function`.
89
- `group.connect(a); group.connect(b)` → `connect` calls `disconnect()`, which re-adds every view to container `a`
90
- (pushing a duplicate entry into `a.children` and re-appending the DOM node), sets `this.container = null`, then
91
- `connect` adds them all to `b`. Container `a` is left with duplicate `children` entries pointing at views whose
92
- DOM nodes now live under `b`; a later `a.removeAllChildren()` calls `a.el.removeChild(child.el)` on a node that is
93
- no longer its child → `NotFoundError` DOMException.
94
- - **Fix**: `this.elements.delete(view)`; `disconnect()` must call `this.container.removeChild(view)`.
95
- - **Confidence**: Confirmed
96
-
97
- ### VIEW-6 `MinimapView.clear()` adds children instead of removing them
98
- - **Severity**: CRITICAL
99
- - **File**: `src/view/minimap/Minimap.js:183-188` (called from `unlink()` at `:236`)
100
- - **Defect**: The method is documented "remove all existing markers" / "clear out all camera views" but its body is
101
- `this.__worldView.addChild(v)` for each camera view — the views are already children, so each `unlink()` pushes a
102
- duplicate entry into `__worldView.children`.
103
- - **Failure scenario**: Open the minimap, close it, open it again (each cycle = one link/unlink pair). After N
104
- cycles `__worldView.children` holds each `MinimapCameraView` N+1 times. Now the camera entity is destroyed:
105
- `cameraRemoved` → `__worldView.removeChild(cameraView)` splices out *one* entry and detaches the DOM node, leaving
106
- stale duplicates. On the next `unlink()`, `clear()` runs `addChild` on that stale duplicate, which does
107
- `this.el.appendChild(child.el)` — re-inserting the frustum polygon of a camera that no longer exists back into the
108
- minimap, and re-linking it on the next `link()` so it keeps updating against a dead `Transform`.
109
- - **Fix**: `this.__worldView.removeChild(v)` and iterate a copy (or iterate backwards) since `removeChild` mutates.
110
- - **Confidence**: Confirmed
111
-
112
- ### VIEW-7 `TaskProgressView` displays progress where remaining time belongs
113
- - **Severity**: MAJOR
114
- - **File**: `src/view/task/TaskProgressView.js:127-131`
115
- - **Defect**: `const estimate = Number.isNaN(computedEstimate) ? 0 : computedProgressValue;` — the non-NaN branch uses
116
- `computedProgressValue` (the 0..1 progress fraction) instead of `computedEstimate` (the estimator's output). The
117
- computed estimate is discarded.
118
- - **Failure scenario**: A 60-second load at 20% progress. `remainingTimeEstimator.estimate()` returns ~48, but the
119
- `.remaining-time` label is fed `0.2` and formatted with `toFixed(0)` → it reads `0`. The loading screen shows
120
- "0 seconds remaining" for the entire load, then jumps to "1" at completion.
121
- - **Fix**: `const estimate = Number.isNaN(computedEstimate) ? 0 : computedEstimate;`
122
- - **Confidence**: Confirmed
123
-
124
- ### VIEW-8 `ColorPickerView` unsubscribes from the new colour instead of the old one
125
- - **Severity**: MAJOR
126
- - **File**: `src/view/elements/ColorPickerView.js:282-294`
127
- - **Defect**:
128
- ```js
129
- this.model.onChanged.add(function (v, _v) {
130
- if (v !== null) { modelValueChanged(...); v.onChanged.add(modelValueChanged); }
131
- if (_v !== null) { v.onChanged.remove(modelValueChanged); } // <-- v, should be _v
132
- });
133
- ```
134
- The removal targets the *new* value. The old value keeps the listener forever, and the new value gets `add`
135
- immediately followed by `remove`.
136
- - **Failure scenario**: `picker.model.set(colorA)` then `picker.model.set(colorB)`. Afterwards, changing `colorB`
137
- externally does not move the H/S/L/A gauges (its listener was removed), while changing `colorA` — which the picker
138
- no longer edits — does move them. Additionally `picker.model.set(null)` after having a colour executes
139
- `null.onChanged.remove(...)` → `TypeError: Cannot read properties of null (reading 'onChanged')`.
140
- - **Fix**: `if (_v !== null) { _v.onChanged.remove(modelValueChanged); }`, and perform the removal before the add.
141
- - **Confidence**: Confirmed
142
-
143
- ### VIEW-9 `ColorPickerView` value-channel write lock uses a key that does not exist
144
- - **Severity**: MAJOR
145
- - **File**: `src/view/elements/ColorPickerView.js:156-161,214,224,229,257,266`
146
- - **Defect**: `writeLocks` is declared with keys `h, s, l, a`. The `colorV` handler checks and sets `writeLocks.v`
147
- (undefined key), while `modelValueChanged` checks `writeLocks.l`. The lock protecting the value/lightness channel
148
- therefore never engages in either direction.
149
- - **Failure scenario**: Pick a saturated red (h≈0, s=1, v=1), then drag the **L** gauge to 0. `colorV.onChanged` runs
150
- unguarded (`writeLocks.v` is `undefined`), writes rgb `(0,0,0)` into the model, which dispatches
151
- `modelValueChanged`; that handler's guard reads `writeLocks.l` — also never set by the V handler — so it proceeds
152
- and pushes `rgb2hsv(0,0,0)` back into the gauges, snapping H and S to 0. The user's hue and saturation are
153
- destroyed by moving the lightness slider, and cannot be recovered by dragging L back up.
154
- - **Fix**: use one consistent key (`v`) in the declaration, the `colorV` handler, and `modelValueChanged`.
155
- - **Confidence**: Confirmed
156
-
157
- ### VIEW-10 `Vector1Control` binds the write-back handler to the model's change signal
158
- - **Severity**: MAJOR
159
- - **File**: `src/view/controller/controls/Vector1Control.js:61-81`
160
- - **Defect**: `subscribe(v1)` does `v1.onChanged.add(writeBack)`. `writeBack` is the *controller → model* direction
161
- (`vector1.set(v)`); the *model → controller* direction is `syncForward`, which is only ever called once, inside
162
- `subscribe`. `unsubscribe` symmetrically removes `writeBack`, so the mismatch is consistent and silent.
163
- - **Failure scenario**: Bind a `Vector1Control` to a `Vector1` that some other system writes (e.g. an animated
164
- property). The number field shows the value present at subscribe time and never updates again: each external change
165
- invokes `writeBack(newValue)` which writes `newValue` straight back into the same vector (a no-op) instead of
166
- refreshing `cNumber.value`.
167
- - **Fix**: `v1.onChanged.add(syncForward)` in `subscribe` and `v1.onChanged.remove(syncForward)` in `unsubscribe`;
168
- keep `lockForward` to break the echo.
169
- - **Confidence**: Confirmed
170
-
171
- ### VIEW-11 `ListController` removes the wrong view, so deleted rows stay on screen
172
- - **Severity**: MAJOR
173
- - **File**: `src/view/controller/controls/ListController.js:48-74`
174
- - **Defect**: `handleItemAdded` wraps `guiControl` in a `vElementContainer` and adds *that* to `vContainer`.
175
- `handleItemRemoved` then calls `vContainer.removeChild(guiControl)` — `guiControl` is a child of
176
- `vElementContainer`, not of `vContainer`, so `children.indexOf()` returns `-1` and `removeChild` returns `false`
177
- without doing anything.
178
- - **Failure scenario**: Click the `.close` button next to a list item. The item leaves the model
179
- (`list.removeOneOf(item)`), `elementControllers` drops the entry, `guiControl.model.set(null)` blanks the control —
180
- but the row (control + close button) remains in the DOM permanently. Clicking its close button again calls
181
- `list.removeOneOf(item)` on an item that is no longer present. Rebinding the controller to a different list via
182
- `detachList` leaves every old row visible on top of the new ones.
183
- - **Fix**: keep a `Map<item, vElementContainer>` (or store the wrapper on the control) and remove the wrapper.
184
- - **Confidence**: Confirmed
185
-
186
- ### VIEW-12 `HTMLElementCacheKey.initializeFromElement` wipes the styles it just read (shadowed loop variable)
187
- - **Severity**: MAJOR
188
- - **File**: `src/view/common/HTMLElementCacheKey.js:189-217`
189
- - **Defect**:
190
- ```js
191
- let i = 0;
192
- ...
193
- for (let i = 0; i < styleCount; i++) { ... this.style[i] = pair; } // inner `i` shadows outer
194
- this.style.splice(i, this.style.length - i); // outer i is still 0
195
- ```
196
- The truncation call meant to drop leftover entries instead removes the entire array. (The attribute loop below uses
197
- `for (i = 0; ...)` without `let`, so it truncates correctly — proving the intent.) The key therefore always reports
198
- "no inline styles", while `hash()`/`equals()` treat that as a real property of the element.
199
- - **Failure scenario**: `imageViewA.css({ filter: 'grayscale(1)' })` on an `<img src="x.png" class="icon">`, then
200
- `imageViewA.destroy()` → `key.initializeFromElement(el)` records the tag and attributes but **not** the filter →
201
- the element is pooled under a key that claims no styles. Later `new ImageView('x.png', {classList:['icon']})`
202
- builds a style-less key, `view_pool.get(key)` matches, and the recycled element is returned still carrying
203
- `filter: grayscale(1)` → the new image renders greyed out.
204
- - **Fix**: rename the inner loop variable (or hoist it) so the splice truncates from `styleCount`.
205
- - **Confidence**: Confirmed
206
-
207
- ### VIEW-13 `TabbedView` never attaches its toggle and panel containers — it renders nothing
208
- - **Severity**: MAJOR
209
- - **File**: `src/view/common/TabbedView.js:49-57`
210
- - **Defect**: The constructor creates `this.el`, then `this.__panelContainer` and `this.__toggleContainer`, but never
211
- calls `this.addChild(...)` on either, and neither does `link()`. Every toggle and panel is added to a container
212
- that is not in the view tree.
213
- - **Failure scenario**: `const t = new TabbedView({tabs}); parent.addChild(t);` → a bare empty `<div>`. Tab toggles
214
- and the active panel exist as detached DOM and are never linked (so their signal bindings never activate either).
215
- - **Fix**: `this.addChild(this.__toggleContainer); this.addChild(this.__panelContainer);` in the constructor.
216
- - **Confidence**: Confirmed
217
-
218
- ### VIEW-14 `MinimapFogOfWar.enforceAspectRatio` computes the wrong growth in the "too wide" branch
219
- - **Severity**: MAJOR
220
- - **File**: `src/view/minimap/gl/MinimapFogOfWar.js:16-38`
221
- - **Defect**: When `aspectRatioDelta <= 0` the code grows the width by `-aabbWidth * aspectRatioDelta`. Solving,
222
- the resulting ratio is `aabbHeight / (aabbWidth * (1 + aAR - vAR))`, which only equals `vAR` by coincidence. The
223
- height branch is correct (`aabbWidth * delta` yields exactly `aabbWidth * vAR`); the width branch is not the
224
- mirror of it.
225
- - **Failure scenario**: minimap viewport 200×100 (`vAR = 0.5`), revealed fog region a 100×100 square (`aAR = 1`).
226
- `delta = -0.5`, `d = 50`, new bounds 150×100 → ratio 0.667, not 0.5. `focusArea` is set to that region and drives
227
- the orthographic camera in `MinimapWorldGL.updateCameraFocus`, so the minimap world is squashed horizontally by
228
- ~33%: terrain, entity markers and the camera frustum polygon (which are positioned from `worldScale`) no longer
229
- line up with the fog-of-war overlay.
230
- - **Fix**: `const d = aabbHeight / viewportAspectRatio - aabbWidth;` (equivalently grow to `aabbHeight / vAR`).
231
- - **Confidence**: Confirmed
232
-
233
- ### VIEW-15 `ListView.insertOne` dereferences an undefined sibling view when a filter is in play
234
- - **Severity**: MAJOR
235
- - **File**: `src/view/common/ListView.js:182-197`
236
- - **Defect**: For a non-terminal insert it looks up `this.model.get(index + 1)` and calls `nextChild.el` without
237
- checking that a view exists for it. `getChildByElement` returns `undefined` whenever the next element was skipped
238
- by `this.filter` (or when the list contains duplicate elements — `viewMapping` is keyed by element identity, so a
239
- duplicate overwrites the previous entry).
240
- - **Failure scenario**: `new ListView(model, {elementFactory, filter: e => e.visible})`. Model is `[A(visible),
241
- C(hidden)]`; insert `B(visible)` at index 1. `insertOne` creates B's view, sees `model.length (3) !== index+1 (2)`,
242
- fetches `C`, `getChildByElement(C)` → `undefined` → `TypeError: Cannot read properties of undefined (reading 'el')`
243
- inside the `model.on.added` dispatch. Signal logs it and swallows it, so the symptom is a silently mis-ordered list
244
- (B stays appended at the end) plus a console error on every filtered insert.
245
- - **Fix**: scan forward from `index + 1` for the first element that has a view; if none, leave the child appended.
246
- - **Confidence**: Confirmed
247
-
248
- ### VIEW-16 `DomSizeObserver.attach()` unobserves the new element and never observes it
249
- - **Severity**: MAJOR
250
- - **File**: `src/view/util/DomSizeObserver.js:147-153`
251
- - **Defect**:
252
- ```js
253
- attach(element) {
254
- this.element = element; // old reference already lost
255
- if (this.running) { this.__dom_resize_observer.unobserve(this.element); } // unobserves the NEW element
256
- }
257
- ```
258
- The old element is never unobserved (it stays in the `ResizeObserver`), and the new element is never observed
259
- because `attach` only ever calls `unobserve`.
260
- - **Failure scenario**: `o.attach(elA); o.start();` then `o.attach(elB)` while running. `unobserve(elB)` is a no-op
261
- (B was never observed), A remains observed. Resizing B produces no callback at all — `o.dimensions` goes stale.
262
- Resizing A *does* fire the callback, which then measures **B** via `resizeAABB2ToFitBoundingClientRect(this.element…)`
263
- for the position but takes `rect.width/height` from **A's** `contentRect` → `dimensions` is a mix of two elements.
264
- - **Fix**: capture the previous element, `unobserve(previous)` if running, assign, then `observe(element)` if running.
265
- - **Confidence**: Confirmed
266
-
267
- ### VIEW-17 `SimpleWindowView` resize handler accumulates the full drag delta on every pointer move
268
- - **Severity**: MAJOR
269
- - **File**: `src/view/elements/SimpleWindow.js:47-73`
270
- - **Defect**: `anchor` is captured once on pointer-down and never advanced, yet the move handler does
271
- `view.size.add(position - anchor)` — an *incremental* mutation fed an *absolute* delta. Compare
272
- `BottomLeftResizeHandleView` (`elements/BottomLeftResizeHandleView.js:31-40`), which correctly does
273
- `lastPosition.copy(position)` each move.
274
- - **Failure scenario**: `new SimpleWindowView(content, {resizable: true})`. Grab the bottom-right 10 px corner and
275
- drag 10 px right over 5 pointer-move events (deltas 2, 4, 6, 8, 10 relative to the fixed anchor) → the width grows
276
- by 30 px instead of 10. A slow 200 px drag over 100 events grows the window by ~10 000 px; the window runs away
277
- from the cursor and cannot be resized back down.
278
- - **Fix**: either update `anchor` to `position` at the end of each move, or capture `originalSize` on pointer-down and
279
- use `view.size.copy(originalSize).add(delta)`.
280
- - **Confidence**: Confirmed
281
-
282
- ### VIEW-18 `ToastLogView` registers every notification twice in `children`
283
- - **Severity**: MAJOR
284
- - **File**: `src/view/elements/notify/ToastLogView.js:47,72-88`
285
- - **Defect**: The constructor reassigns `this.children = []` (shadowing the base `View.children` array), and `addOne`
286
- then does **both** `self.addChild(childView)` — which pushes onto `this.children` — **and**
287
- `self.children.push(childView)`. Every toast appears twice in the array. `removeChildView` splices out one
288
- occurrence and bypasses `View.removeChild`, so the second entry survives with its DOM node already detached.
289
- - **Failure scenario**: Two notifications A then B. `children` = `[A, A, B, B]`, so `updatePositions` computes
290
- `maxIndex = 3`: A ends at `-(3-1)*24 = -48 px` and B at `0`, instead of `-24` and `0` → a 24 px gap opens between
291
- the two toasts and the stack floats one row too high. After A's fade-out, `children` = `[A, B, B]` and A's stale
292
- entry keeps skewing every subsequent layout. If the view is ever destroyed, `View.destroy`/`removeAllChildren`
293
- walks the duplicates and calls `this.el.removeChild(A.el)` on an already-detached node → `NotFoundError`.
294
- - **Fix**: delete the `this.children = []` reassignment and the manual `push`; use `View.removeChild` in
295
- `removeChildView`. Also cancel the pending `setTimeout` handles on unlink and unsubscribe
296
- `model.elements.on.added` (currently a permanent subscription, `:90`).
297
- - **Confidence**: Confirmed
298
-
299
- ### VIEW-19 `RadialProgressView` subscribes to its external model permanently
300
- - **Severity**: MAJOR
301
- - **File**: `src/view/elements/radial/RadialProgressView.js:55-68`
302
- - **Defect**: `model.on.changed.add(update)` / `model[0].onChanged.add(redraw)` / `model[1].onChanged.add(redraw)` are
303
- raw subscriptions on caller-owned objects, made in the constructor and never removed — the class has no `unlink()`
304
- or `destroy()` override, and does not use `bindSignal`.
305
- - **Failure scenario**: `view/units/UnitRadialPreview.js:23` builds
306
- `new RadialProgressView([unit.healthCurrent, unit.stats.healthMax], …)`. The unit outlives the preview widget
307
- (health is model state). Every time a unit preview is created and discarded, the unit's `healthCurrent` signal
308
- retains `redraw`, which closes over the view, its SVG element and its `thickness` observable — the whole widget is
309
- unreclaimable, and every health tick redraws N dead widgets. Cycling a roster panel a few hundred times leaks
310
- hundreds of SVG subtrees.
311
- - **Fix**: route all three through `this.bindSignal(...)` so they follow the view's link lifecycle.
312
- - **Confidence**: Confirmed
313
-
314
- ### VIEW-20 `createInterfaceCommandButton` subscribes to the command's feature signals twice, one of them forever
315
- - **Severity**: MAJOR
316
- - **File**: `src/view/interaction/createInterfaceCommandButton.js:91-99`
317
- - **Defect**:
318
- ```js
319
- if (interaction.features !== undefined) {
320
- interaction.features.on.added.add(addCommandFeature); // permanent
321
- interaction.features.on.removed.add(removeCommandFeature); // permanent
322
- }
323
- button.bindSignal(interaction.features.on.added, addCommandFeature); // link-scoped (correct)
324
- button.bindSignal(interaction.features.on.removed, removeCommandFeature); // link-scoped (correct)
325
- ```
326
- `InteractionCommand` always constructs `this.features = new List(features)` (`interaction/InteractionCommand.js:40`),
327
- so the `if` is always taken and the first pair is always added. Nothing ever removes them.
328
- - **Failure scenario**: `InteractionCommand` instances are long-lived and shared — `InteractionCommandSet` keys them
329
- by id. A command bar that is rebuilt on every selection change produces a new `ButtonView` per command each time;
330
- each one permanently registers two closures on the shared command's feature list. After 100 selection changes,
331
- `interaction.setFeature('highlighted', true)` invokes `addCommandFeature` on 100 discarded buttons, and all 100
332
- button subtrees are unreclaimable.
333
- - **Fix**: delete the raw `on.added`/`on.removed` subscriptions; the `bindSignal` pair already covers the live case
334
- and `button.on.linked` already replays the current features.
335
- - **Confidence**: Confirmed
336
-
337
- ### VIEW-21 `MeshPreview` multiplies its pointer handlers on every link, and dereferences a null camera
338
- - **Severity**: MAJOR
339
- - **File**: `src/view/elements/MeshPreview.js:204-234`
340
- - **Defect**: (a) `link()` attaches a fresh `self.pContents.then(...)` continuation each time. Because `pContents` is
341
- already settled after the first load, every subsequent link immediately runs `__addInteraction`, which creates a
342
- **new** `PointerDevice`, calls `start()` on it, and adds another `dragStart`/`drag` pair that mutates
343
- `contents.group.rotation` — none of which is ever stopped in `unlink()`. (b) `__update_renderer_size` guards on
344
- `this.renderer !== null` but then touches `this.camera.aspect`; `camera` is only assigned in the asset callback.
345
- - **Failure scenario (a)**: Open a unit-detail panel containing a `MeshPreview`, close it, open it again. Two
346
- `PointerDevice`s are now live on the pooled canvas; one drag rotates the model twice as fast. After ten cycles the
347
- model spins ~10× per pixel of drag. (b): `preview.size.set(256, 256)` after linking but before the glTF resolves —
348
- the bound `size.onChanged` fires with `renderer` set and `camera` still `null` →
349
- `TypeError: Cannot set properties of null (setting 'aspect')`.
350
- - **Fix**: attach the `pContents` continuation once in the constructor and have it store `contents.group`; create the
351
- `PointerDevice` once and `start()`/`stop()` it from `link`/`unlink`. Guard `__update_renderer_size` on
352
- `this.camera !== null` as well (it is genuinely null until the async load lands).
353
- - **Confidence**: Confirmed
354
-
355
- ### VIEW-22 `renderModel` caches the caller's live `size`/`focus` objects, so resizes return the stale image
356
- - **Severity**: MAJOR
357
- - **File**: `src/view/renderModel.js:15-29,85-92`
358
- - **Defect**: The cache entry stores `size: size` and `focus: focus` by reference, and `findInCache` compares with
359
- `piece.size.equals(size)` / component-wise on `focus`. When the caller passes a mutable vector, the cached entry's
360
- key mutates in lockstep with the query, so the comparison always succeeds.
361
- - **Failure scenario**: `MeshView.render()` (`common/MeshView.js:61`) passes `this.size` and `this.focus` straight
362
- through. Render a mesh preview at 50×50 — cached with `piece.size === view.size`. Resize the view to 200×200:
363
- `update()` sees the change and calls `render()`, `findInCache(url, this.size, this.focus)` compares `this.size`
364
- against itself → hit → the 50×50 `dataURL` is returned and stretched to 200×200 (blurry), and no re-render is ever
365
- scheduled. The cache also has no eviction (`cache.push` only), so it grows without bound.
366
- - **Fix**: store `size.clone()` and a copied `AABB2` in the cache entry; add an eviction policy (the codebase already
367
- has `core/cache/Cache`).
368
- - **Confidence**: Confirmed
369
-
370
- ### VIEW-23 `MeshView` never reacts to its own model
371
- - **Severity**: MAJOR
372
- - **File**: `src/view/common/MeshView.js:72-92`
373
- - **Defect**: The view observes `this.size` only. `update()`'s change test compares `size` and `focus` against
374
- `renderedParams` and ignores the model entirely, so even an explicit `update()` after a model change does nothing.
375
- `this.model.onChanged` is never bound.
376
- - **Failure scenario**: `meshView.model.set('models/sword.gltf')` on a linked `MeshView` currently showing
377
- `models/axe.gltf` → nothing happens; a manual `meshView.update()` also short-circuits on "no change". The view keeps
378
- displaying the axe until the element is resized.
379
- - **Fix**: `this.bindSignal(this.model.onChanged, this.render, this)`, and include the rendered URL in
380
- `renderedParams` so `update()` detects it.
381
- - **Confidence**: Confirmed
382
-
383
- ### VIEW-24 `RectangularPieProgressView` assumes a square element; on any other aspect the path becomes invalid
384
- - **Severity**: MAJOR
385
- - **File**: `src/view/elements/progress/RectangularPieProgressView.js:77-107`
386
- - **Defect**: The fraction thresholds `.125 / .375 / .625 / .875` place the corner transitions at 45°, which is only
387
- where the corners are for a square. For a non-square element the sweep ray exits through a different edge than the
388
- branch tests, `segment2_segment_compute_intersection_array_2d` returns `false` and leaves `p` empty, and the path
389
- string is built from `p[0]`/`p[1]` === `undefined`.
390
- - **Failure scenario**: `v.size.set(100, 50); v.model.set(13); v.max.set(100)` (fraction 0.13 → branch 2, which tests
391
- the **right** edge). `angle ≈ 43°` from the centre `(50,25)`: reaching `x = 100` needs `Δy = -47`, i.e. `y = -22`,
392
- outside the edge segment — the ray actually exits through the **top** edge at `x ≈ 76.6`. No intersection is
393
- written, so `d` becomes `"M 50 0 L 50 25 L undefined undefined L 100 50 L 0 50 L 0 0 Z"`. Browsers reject the whole
394
- `d` attribute → the cooldown overlay disappears entirely for that fraction range.
395
- (In-repo the only caller, `view/units/ability/CombatAbilityView.js:30`, sizes it 64×64, so the game path is safe —
396
- but this is a public class with a `size` the caller controls.)
397
- - **Fix**: compute the corner fractions from the actual aspect (`atan2(size_y, size_x)` etc.) instead of hard-coded
398
- eighths, or pick the edge by testing all four and taking whichever intersects.
399
- - **Confidence**: Confirmed
400
-
401
- ### VIEW-25 `EmptyView.absolute` nests the caller's CSS instead of spreading it
402
- - **Severity**: MAJOR
403
- - **File**: `src/view/elements/EmptyView.js:54-72`
404
- - **Defect**:
405
- ```js
406
- css: {
407
- css, // shorthand -> a property literally named "css"
408
- ...CSS_ABSOLUTE_POSITIONING
409
- }
410
- ```
411
- The intent is clearly `...css`. `View.css(hash)` then executes `this.el.style['css'] = {…}`, which the CSSOM
412
- ignores.
413
- - **Failure scenario**: `EmptyView.absolute({ css: { width: '100px', backgroundColor: 'red' } })` produces an element
414
- with only `position/top/left` applied; width and background are silently dropped, so the element collapses to zero
415
- size. No error is raised anywhere.
416
- - **Fix**: `css: { ...css, ...CSS_ABSOLUTE_POSITIONING }`.
417
- - **Confidence**: Confirmed
418
-
419
- ### VIEW-26 `TileGridView` subscribes to the model and the DnD context outside the view lifecycle
420
- - **Severity**: MAJOR
421
- - **File**: `src/view/elements/tiles2d/TileGrid.js:135-136,301-338,411-419`
422
- - **Defect**: `model.tiles.on.added.add(this.addTile, this)` and `.on.removed.add(this.removeTile, this)` are raw
423
- subscriptions (not `bindSignal`) with no counterpart anywhere. Likewise every slot registers a `DropTarget` into
424
- `this.__dragAndDropContext` via `addTarget` (which immediately `link()`s DOM listeners) and every tile registers a
425
- `Draggable` via `addElement`; neither `removeTarget` nor `removeElement` is ever called, and the context is a
426
- constructor parameter, i.e. typically shared across grids.
427
- - **Failure scenario**: An inventory panel builds a 10×6 `TileGridView` against a shared `DragAndDropContext` each
428
- time it opens. Every open/close cycle permanently adds 60 `DropTarget`s (each with 4 DOM listeners) and one
429
- `Draggable` per item to `context.targets`/`context.elements`, and leaves the grid subscribed to `model.tiles`. After
430
- 20 cycles, `DragAndDropContext.finalizeDrag` iterates 1200+ targets on every drop, `getElementById` scans hundreds
431
- of dead draggables, and adding an item to the inventory while all panels are closed calls `addTile` on 20 detached
432
- grids. Removing an item calls `removeTile` on grids where `findTileView` returns `undefined`, so
433
- `this.__hookTileRemoved(undefined, tile)` fires with an undefined view.
434
- - **Fix**: route the two model subscriptions through `bindSignal`; add an `unlink()` that calls
435
- `context.removeTarget(slotView)` for each slot and `context.removeElement(draggable)` for each tile, and rebuild on
436
- `link()`.
437
- - **Confidence**: Confirmed
438
-
439
- ### VIEW-27 `LocalizedLabelView.update()` dereferences a null localization outside the try
440
- - **Severity**: MAJOR
441
- - **File**: `src/view/common/LocalizedLabelView.js:122-154`
442
- - **Defect**: `localization = null` is the constructor default and the class explicitly tests for it at `:60`, so it
443
- is an anticipated state. `update()` wraps only `localization.getString(...)` in `try/catch`; line 143
444
- (`this.__localeKey = localization.locale.getValue()`) and the `$el.text(value)` fallback that follows are outside
445
- it. The throw at 143 skips the fallback text.
446
- - **Failure scenario**: `new TaskProgressView({ task })` — `localization` defaults to `null`
447
- (`task/TaskProgressView.js:20,29-33`) — then link. The `on.linked` handler calls `update()`, `getString` throws,
448
- the catch sets `value = "failed to localize @…"`, then line 143 throws `TypeError: Cannot read properties of null
449
- (reading 'locale')` before the text is written. Signal's dispatch try/catch swallows it, so the loading screen's
450
- task-name label renders completely blank with two console errors per link.
451
- - **Fix**: return early (writing the raw `@id` fallback) when `localization === null`, and move the `__localeKey`
452
- assignment after a successful `getString`.
453
- - **Confidence**: Confirmed
454
-
455
- ### VIEW-28 `MarkerGL` leaks atlas patch references acquired across shutdown / rapid icon changes
456
- - **Severity**: MAJOR
457
- - **File**: `src/view/minimap/gl/MarkerGL.js:57-87,109-118`
458
- - **Defect**: `updateIcon` releases the *current* `this.patch`, then awaits `atlasManager.acquire(newURL)`. The
459
- continuation assigns `this.patch = patch` and then bails on `!this.active` — but the freshly acquired reference is
460
- never released on that path. Similarly, two `updateIcon` calls in flight both release `Reference.NULL` up front and
461
- the first resolved patch is overwritten (and leaked) by the second.
462
- - **Failure scenario**: A unit with a minimap marker is killed while its icon texture is still being fetched
463
- (`MinimapMarkersGL.removeElement` → `markerGL.shutdown()` → `active = false`, releases `Reference.NULL`). The
464
- `acquire` promise then resolves, stores the patch on the dead marker and returns without releasing it → the
465
- `ManagedAtlas` never frees that icon's slot. Repeated over a battle with many short-lived markers, the atlas fills
466
- up and later markers fail to get a patch.
467
- - **Fix**: in the continuation, if `!this.active`, call `patch.release()` before returning; also release the previous
468
- `this.patch` when overwriting it rather than at call time.
469
- - **Confidence**: Confirmed
470
-
471
- ### VIEW-29 `DropTarget` drag-enter tracking has no dedup and splices with `-1`
472
- - **Severity**: MAJOR
473
- - **File**: `src/view/common/dnd/DropTarget.js:72-92,212-236`
474
- - **Defect**: `handleDragEnter` pushes into `isInState_ENTER` unconditionally, and
475
- `attachDropValidityIndicators.handleDragEnter` unconditionally appends a `{draggable, bindings}` record with a fresh
476
- `SignalBinding` on `draggable.on.dragFinalized`. `removeDraggable` removes exactly one record per call.
477
- `handleDragLeave` additionally does `isInState_ENTER.splice(indexOf(e), 1)` without checking for `-1`, and
478
- `splice(-1, 1)` removes the *last* element.
479
- - **Failure scenario**: `Draggable.link()` explicitly routes `dragenter` to the parent drop target
480
- (`common/dnd/Draggable.js:103-106`) *and* the event bubbles to the drop target's own listener — so dragging an item
481
- over another item inside the same slot fires `handleDragEnter` twice for one enter. `current` gains two records and
482
- two live bindings. On drop, `dragFinalized` fires once, `removeDraggable` clears one record, and `update()` still
483
- sees a non-empty `current` → the slot keeps its `drop-target-hover-valid` class permanently after the drag ends,
484
- and each further hover leaks another `SignalBinding` on the draggable.
485
- - **Fix**: dedup on enter (skip if the draggable is already tracked), loop `removeDraggable` until it returns false on
486
- finalize, and guard the `indexOf === -1` case before splicing.
487
- - **Confidence**: Likely
488
-
489
- ### VIEW-30 A throwing tooltip factory disables tooltips globally for the rest of the session
490
- - **Severity**: MAJOR
491
- - **File**: `src/view/tooltip/TooltipManager.js:129-138`
492
- - **Defect**:
493
- ```js
494
- gml.pushState();
495
- gml.setTooltipsEnabled(false);
496
- const factoryProduct = tip.factory.call(tip.factoryContext); // may throw
497
- gml.popState();
498
- ```
499
- There is no `try/finally`. `GMLEngine.compile`/`compileAsText` both use `try { … } finally { this.popState(); }`
500
- (`tooltip/gml/GMLEngine.js:481-493,512-525`), so the omission here is clearly unintended.
501
- - **Failure scenario**: A single tooltip factory throws (e.g. an item tooltip for an item whose data row is missing).
502
- `popState()` is skipped, so `__tooltipsEnabled` stays `false` and one orphan frame stays on `__contextStack`. Every
503
- reference compiler that consults `gml.getTooltipsEnabled()` from then on sees `false` → nested tooltips stop being
504
- attached anywhere in the UI until reload.
505
- - **Fix**: wrap the factory call in `try { … } finally { gml.popState(); }`.
506
- - **Confidence**: Confirmed
507
-
508
- ### VIEW-31 `RadialMenu.init()` leaves the previous element views attached, and shared icon views get stolen
509
- - **Severity**: MAJOR
510
- - **File**: `src/view/elements/radial/RadialMenu.js:194-223`, `src/view/elements/radial/RadialMenuElement.js:70`
511
- - **Defect**: `init()` resets `this.elements = []` but never removes the previously created `RadialMenuElement`
512
- children from `this.vElementContainer`. Separately, `RadialMenuElement`'s constructor does
513
- `this.addChild(description.iconView)` — the icon `View` lives on the caller-owned
514
- `RadialMenuElementDefinition`, and `View.addChild` re-parents it (`child.parent = this; this.el.appendChild(child.el)`).
515
- - **Failure scenario**: (a) `menu.init(newItems)` on an existing menu — the old wedges, labels and icons stay in the
516
- DOM underneath the new ones, and `selectByAngle`/`render` only touch the new set, so the stale wedges are frozen in
517
- place and never highlight. (b) Building two `RadialMenu`s from the same `items` array (definitions are plain data
518
- objects that are easy to reuse) — the second menu's `addChild` moves every `iconView`'s DOM node out of the first
519
- menu, leaving the first menu iconless while both `children` arrays still list it.
520
- - **Fix**: `this.vElementContainer.removeAllChildren()` at the top of `init()`; and either clone the icon view per
521
- element or document/enforce one definition per menu.
522
- - **Confidence**: Confirmed
523
-
524
- ### VIEW-32 `ConfirmationDialogView` builds a class name that can contain a space
525
- - **Severity**: MAJOR
526
- - **File**: `src/view/elements/ConfirmationDialogView.js:38`
527
- - **Defect**: `"button-" + option.name.replace(' ', '-')` — `String.replace` with a string pattern replaces only the
528
- **first** occurrence. The result is handed to `ButtonView`'s `classList`, which reaches `DOMTokenList.add()`.
529
- - **Failure scenario**: `new ConfirmationDialogView(content, [{name: 'cancel all now', displayName: 'Cancel', …}])`
530
- → class token `"button-cancel-all now"` → `classList.add` throws
531
- `InvalidCharacterError: The string contains invalid characters`, aborting the whole dialog construction so no
532
- confirmation dialog is shown at all.
533
- - **Fix**: `option.name.replace(/\s+/g, '-')`, or reuse `string_tag_to_css_class_name`.
534
- - **Confidence**: Confirmed
535
-
536
- ### VIEW-33 `VirtualListView` disables the scrollbar one row too early, and `AlignmentOption.Center` does nothing
537
- - **Severity**: MINOR
538
- - **File**: `src/view/common/VirtualListView.js:181-196`
539
- - **Defect**: The "everything fits" test is
540
- `row_height * (last_visible_line - first_visible_line) < this.size.y`, i.e. it measures `n-1` rows instead of `n`.
541
- Separately, `AlignmentOption.Center` is exported and accepted as `verticalAlignment` but the offset block only
542
- handles `End`, so `Center` silently behaves like `Start`.
543
- - **Failure scenario**: `lineSize = 20, lineSpacing = 0`, 5 elements, `size.y = 90` (content 100 px). `l0 = 0`,
544
- `l1 = 4 = numTotalElements - 1`, and `20 * (4 - 0) = 80 < 90` → `__setScrollBar(false)` and `rowWidth` is not
545
- reduced. The list declares itself fully visible while the 5th row is clipped by 10 px and cannot be scrolled to.
546
- - **Fix**: compare `row_height * (last - first + 1) <= this.size.y`; implement the `Center` branch
547
- (`line_offset_y = (this.size.y - total_lines_height) / 2`).
548
- - **Confidence**: Confirmed
549
-
550
- ### VIEW-34 `DropDownSelectionView.setSelectedValue` uses the model index against always-appended options
551
- - **Severity**: MINOR
552
- - **File**: `src/view/elements/DropDownSelectionView.js:55-68,141-143`
553
- - **Defect**: `handleAdded(el, index)` ignores `index` and always `appendChild`s, while `setSelectedValue` does
554
- `this.el.selectedIndex = this.model.indexOf(v)`. The two orderings only agree when elements are appended.
555
- (`getSelectedValue` correctly resolves through the id map, so the two accessors disagree.) `handleRemoved` also
556
- never deletes the entry from `this.mapping`.
557
- - **Failure scenario**: `model.insert(0, x)` on a populated list — `x`'s `<option>` lands last while `model.indexOf(x)`
558
- is `0`, so `setSelectedValue(x)` selects whatever element was originally first.
559
- - **Fix**: honour `index` in `handleAdded` (`insertBefore` the option at `index`), and delete the mapping entry in
560
- `handleRemoved`.
561
- - **Confidence**: Confirmed
562
-
563
- ### VIEW-35 `MinimapCameraView.castTerrainRay` jitters an origin it never uses
564
- - **Severity**: MINOR
565
- - **File**: `src/view/minimap/dom/MinimapCameraView.js:99-117`
566
- - **Defect**: The retry loop perturbs `oX/oY/oZ` but calls
567
- `terrain.raycastFirstSync(rayContact, originX, originY, originZ, …)` with the *unperturbed* origin every iteration.
568
- `oX/oY/oZ` are written and never read.
569
- - **Failure scenario**: A frustum corner ray that lands exactly on a terrain triangle edge misses. The stated purpose
570
- of the loop — "jitter origin in case of mathematical error at polygon edges" — never happens; instead the identical
571
- raycast runs 10 times and then falls back to the flat `y = 0` plane. On elevated terrain that corner of the minimap
572
- camera-frustum polygon is drawn at the ground-plane intersection instead of the terrain surface, so the frustum
573
- outline visibly snaps outward for that corner.
574
- - **Fix**: pass `oX, oY, oZ` to `raycastFirstSync`.
575
- - **Confidence**: Confirmed
576
-
577
- ### VIEW-36 `DOM.prototype.clear()` does not remove text nodes
578
- - **Severity**: MINOR
579
- - **File**: `src/view/DOM.js:131-137`
580
- - **Defect**: The loop iterates `el.children` (elements only), so text nodes survive a method documented as
581
- "removes all children".
582
- - **Failure scenario**: `const d = domify('div'); d.text('Loading…'); d.clear(); d.append(other);` → the element still
583
- reads "Loading…" followed by the appended content. This is reachable through
584
- `LocalizedLabelView.update()` (`$el.text(value)` on the non-GML path) followed by a switch to a GML-compiled value,
585
- which calls `removeAllChildren()` and then appends compiled views next to the leftover text node; also
586
- `MinimapView.link()` (`minimap/Minimap.js:217-219`) relies on `clear()` before appending the WebGL canvas.
587
- - **Fix**: `while (el.firstChild) el.removeChild(el.firstChild);`
588
- - **Confidence**: Confirmed
589
-
590
- ### VIEW-37 `setElementTransform.js` exports nothing
591
- - **Severity**: MINOR
592
- - **File**: `src/view/setElementTransform.js:13`
593
- - **Defect**: The module declares `function setElementTransform(...)` with no `export` and no default export, so the
594
- file's only purpose is unreachable.
595
- - **Failure scenario**: `import { setElementTransform } from '.../setElementTransform.js'` →
596
- `SyntaxError: The requested module does not provide an export named 'setElementTransform'` at build time.
597
- - **Fix**: `export function setElementTransform(...)`.
598
- - **Confidence**: Confirmed
599
-
600
- ### VIEW-38 `DatGuiUtils.makeDatController` references an undeclared `p` in its cycle branch
601
- - **Severity**: MINOR
602
- - **File**: `src/view/controller/dat/DatGuiUtils.js:377-380`
603
- - **Defect**: ``console.warn(`Detected cycle at "${p}" …`)`` — `p` is the loop variable of `makeDatControllerForObject`,
604
- not of this function. Modules are strict-mode, so this is a `ReferenceError`, not `undefined`. The intended
605
- identifier is `propertyName`.
606
- - **Failure scenario**: `makeDatController` is exported (`:451`). A direct call
607
- `makeDatController(gui, obj, 'child', pathContainingObjChild)` hits the cycle branch and throws
608
- `ReferenceError: p is not defined` instead of warning and returning `0`, aborting the whole controller build.
609
- - **Fix**: use `${propertyName}`.
610
- - **Confidence**: Confirmed
611
-
612
- ### VIEW-39 `GroupView.remove()` leaves the removed child linked; `update()` calls a method `View` does not have
613
- - **Severity**: MINOR
614
- - **File**: `src/view/elements/Group.js:8,11-30`
615
- - **Defect**: `add`/`remove` bypass `View.addChild`/`View.removeChild`: `child.parent` is never set and `remove` never
616
- calls `child.unlink()`. `update()` invokes `c.update()` on each child, but `View` defines no `update`.
617
- - **Failure scenario**: `group.add(labelView); group.link(); group.remove(labelView);` — the label's DOM node is
618
- detached but the view stays linked, so its `bindSignal` subscriptions keep firing and keep writing to a node that is
619
- no longer in the document. `group.update()` with any plain `EmptyView` child →
620
- `TypeError: c.update is not a function`.
621
- - **Fix**: delegate to `View.addChild`/`View.removeChild` (and drop the `this.children = []` reassignment); remove
622
- `update()` or make it guard on the method existing.
623
- - **Confidence**: Confirmed
624
-
625
- ### VIEW-40 `WindRoseDiagram` sizes itself for icons that may not exist, and re-registers tooltips on every draw
626
- - **Severity**: MINOR
627
- - **File**: `src/view/elements/windrose/WindRoseDiagram.js:90-94,197-336`
628
- - **Defect**: (a) `const has_icons = axes.some(isDefined)` tests whether each *axis object* is defined, not whether it
629
- has an `icon`; for any non-empty `axes` array this is always `true`. (b) `draw_canvas()` calls
630
- `container.removeAllChildren()` and rebuilds every label/icon, then calls `this.__tooltips.add(view, …)` for each —
631
- `DomTooltipManager.add` links a `DomTooltipObserver` immediately and is never paired with `remove`.
632
- - **Failure scenario**: (a) `new WindRoseDiagram({axes: [{name:'a'},{name:'b'},{name:'c'}], radius_outer: 100,
633
- icon_size: 32})` (no icons at all) → `size = 200 + 32*1.207*2 ≈ 277` instead of `200`; the widget claims 77 px more
634
- in both axes than it draws, pushing neighbours around in a flex row. (b) `draw()` runs on every `on.linked`; after
635
- 10 open/close cycles each axis label has 10 live `DomTooltipObserver`s with `mouseenter`/`mouseleave` listeners on
636
- detached elements.
637
- - **Fix**: `axes.some(a => a.icon !== undefined)`; use `tooltips.manage(view, …)` (which self-registers on
638
- link/unlink) rather than `add`.
639
- - **Confidence**: Confirmed
640
-
641
- ### VIEW-41 `ImageView`/`VideoView` never re-apply an observed URL on link
642
- - **Severity**: MINOR
643
- - **File**: `src/view/elements/image/ImageView.js:65-71`, `src/view/elements/video/VideoView.js:77-83`
644
- - **Defect**: The `src` is baked into the cache key at construction and thereafter only updated by the
645
- `url.onChanged` → `__setSource` binding, which is a `bindSignal` and therefore inactive while unlinked. There is no
646
- `on.linked` initial-apply.
647
- - **Failure scenario**: An `ImageView` bound to an `ObservedString` icon URL sits in a panel. Close the panel (view
648
- unlinks, binding detaches), the underlying model swaps the icon (equip a different item), reopen the panel — the
649
- binding re-links but is never invoked, so the `<img>` still shows the previous icon until the URL happens to change
650
- again while the panel is open.
651
- - **Fix**: add `this.on.linked.add(() => this.__setSource(url.getValue()), this)` in the observed-URL branch (mirroring
652
- `LabelView.link()`, which re-runs `updateTransform()`).
653
- - **Confidence**: Confirmed
654
-
655
- ### VIEW-42 `ButtonView` never applies its initial enabled/disabled class
656
- - **Severity**: MINOR
657
- - **File**: `src/view/elements/button/ButtonView.js:94,101-110`
658
- - **Defect**: `__enabled` is initialised by direct field assignment, bypassing the setter, and the setter early-returns
659
- when the value is unchanged. A button that is enabled from birth therefore carries **neither** `.enabled` nor
660
- `.disabled`.
661
- - **Failure scenario**: `.ui-button-view.disabled { opacity: .4 }` + `.ui-button-view.enabled { cursor: pointer }`
662
- style rules — a freshly created enabled button matches neither. `createInterfaceCommandButton` masks this because
663
- its `on.linked` handler calls `updateEnableStatus()`, but that only helps when the command's `enabled` differs from
664
- `true`; a permanently-enabled command's button never gets the class.
665
- - **Fix**: set the class explicitly at the end of the constructor (`this.setClass('enabled', true);
666
- this.setClass('disabled', false);`) rather than relying on the setter's change detection.
667
- - **Confidence**: Likely
1
+ # Correctness review — `meep/src/view/`
2
+
3
+ Scope: all 111 non-spec source files under `H:/git/moh/app/src/mir-engine/meep/src/view/`.
4
+ Excluded: `editor/`, `prototype*.js`, `*.spec.js`, `.d.ts`.
5
+
6
+ Notes on evidence used while reviewing:
7
+ - `View.unlink()` **clears the `Linked` flag before dispatching `on.unlinked`** (`View.js:325` then `:347`). Several
8
+ findings below depend on that ordering.
9
+ - `Signal` keeps handlers in a `Map` keyed by the handler function; iteration is insertion-ordered, and a handler
10
+ removed mid-dispatch by an earlier handler is **not** invoked (`core/events/signal/Signal.js:378-425`).
11
+ - `Vector1`/`ObservedInteger` extend `Number` and implement `valueOf()`, so arithmetic directly on them is valid.
12
+ - `segment2_segment_compute_intersection_array_2d` leaves `result` **untouched** and returns `false` on a miss.
13
+
14
+ ---
15
+
16
+ ### VIEW-1 `DomTooltipObserver.unlink()` never actually detaches, because the view is already unlinked
17
+ - **Severity**: CRITICAL
18
+ - **File**: `src/view/tooltip/DomTooltipObserver.js:156-165`, driven from `src/view/tooltip/DomTooltipManager.js:109-117,178-194`
19
+ - **Defect**: `unlink()` only runs `__handleViewUnlinked()` `if (view.isLinked)`. On the `manage()` path the call
20
+ arrives from inside the `view.on.unlinked` dispatch, at which point `View.unlink()` has already cleared the
21
+ `Linked` flag — so the guard is always false and the teardown is skipped entirely. The observer's own
22
+ `on.unlinked` handler cannot compensate: `manage()`'s handler was subscribed first, and it calls
23
+ `observer.unlink()`, which does `view.on.unlinked.remove(this.__handleViewUnlinked, this)` mid-dispatch, deleting
24
+ the not-yet-visited Map entry so it never fires.
25
+ - **Failure scenario**: `gui.viewTooltips.manage(button, factory)` (used in ~20 places, e.g.
26
+ `interaction/createInterfaceCommandButton.js:106`, `view/game/scene/strategy/shop/ItemShopView.js:185`). Link the
27
+ panel, then unlink it. `mouseenter`/`mouseleave` listeners stay on `button.el`, and the 4 `SignalBinding`s on
28
+ `view.position.onChanged`, `view.size.onChanged` and the `DomSizeObserver` stay linked forever. Re-open the panel
29
+ and `manage()`'s linked handler calls `add()` again, creating a *second* observer with a second pair of DOM
30
+ listeners on the same element. Ten open/close cycles leave ten live observers per button. Worse: hover a button,
31
+ and inside the 128 ms `requestShow` delay close the panel — `remove()` calls `hide()` (no-op, tip not added yet),
32
+ the observer teardown is skipped so nothing calls `cancelShowRequest()`, the timeout fires, `tipManager.add(tip)`
33
+ builds a tooltip for a detached view, and because the element no longer receives mouse events nothing will ever
34
+ fire `on.exited` → the tooltip is stuck on screen for the rest of the session.
35
+ - **Fix**: drop the `view.isLinked` guard in `unlink()` and make `__handleViewUnlinked()` idempotent (track an
36
+ internal `#attached` boolean set in `__handleViewLinked`), and remove the `view.on.*` handlers *before* calling
37
+ `__handleViewUnlinked()`. Additionally call `this.cancelShowRequest()` in `DomTooltipManager.remove()`.
38
+ - **Confidence**: Confirmed
39
+
40
+ ### VIEW-2 `SvgImageView` cannot be imported and crashes on every `link()`
41
+ - **Severity**: CRITICAL
42
+ - **File**: `src/view/elements/image/SvgImageView.js:1,64-73`
43
+ - **Defect**: Two independent hard errors. (a) `import AABB2 from "../../../core/geom/AABB2.js"` — that file does not
44
+ exist; the real path is `core/geom/2d/aabb/AABB2.js`, so the module fails to resolve. (b) `update()` is a class
45
+ method but its body references `resize` and `self`, which are `const`/`let` bindings local to the *constructor*.
46
+ `link()` calls `this.update()` unconditionally.
47
+ - **Failure scenario**: any module that does `import SvgImageView from '.../SvgImageView.js'` fails at bundle/resolve
48
+ time. If the import path is fixed, `new SvgImageView(url, {assetManager}); parent.addChild(v)` on a linked parent →
49
+ `link()` → `update()` → `ReferenceError: resize is not defined` (caught by Signal only if it were dispatched from a
50
+ signal; here it propagates out of `addChild`).
51
+ - **Fix**: correct the import path; promote `resize` and the icon element to instance state (`#resize()` reading
52
+ `this.#elIcon`, `this.size`) so `update()` can reach them.
53
+ - **Confidence**: Confirmed
54
+
55
+ ### VIEW-3 `MinimapMarkerView` throws on construction — `this` used before `super()`
56
+ - **Severity**: CRITICAL
57
+ - **File**: `src/view/minimap/dom/MinimapMarkerView.js:17,51-64`
58
+ - **Defect**: `super(entity, this.marker, this.transform, this.worldScale)` dereferences `this` before the base
59
+ constructor has run, which is a `ReferenceError` in every ES2015+ engine. Even past that, the three handler methods
60
+ reference `setPosition` and `size`, which are constructor-local bindings, and they are bound via `bindSignal(...)`
61
+ **without a context argument**, so `this` inside them would be `undefined`.
62
+ - **Failure scenario**: `new MinimapMarkerView(entity, marker, transform, worldScale)` →
63
+ `ReferenceError: Must call super constructor in derived class before accessing 'this'`. The class is unusable.
64
+ - **Fix**: `super()` with no arguments; move `setPosition` to a method and pass `this` as the context to every
65
+ `bindSignal` call; read `this.size` instead of the free `size`.
66
+ - **Confidence**: Confirmed
67
+
68
+ ### VIEW-4 `MinimapTerrainView.__setTerrain` references an undefined identifier and has no context
69
+ - **Severity**: CRITICAL
70
+ - **File**: `src/view/minimap/dom/MinimapTerrainView.js:126,133-143`
71
+ - **Defect**: `this.terrain.onChanged.add(this.__setTerrain)` subscribes a *method* with no context, and the method
72
+ body calls `updatePreview()` — a function declared inside the constructor and therefore not in scope. It also
73
+ dereferences `terrain.preview` with no null check even though `ObservedValue(null)` is the initial state and
74
+ `set(null)` is a legal transition.
75
+ - **Failure scenario**: `minimapTerrainView.terrain.set(someTerrain)` → `__setTerrain` runs →
76
+ `ReferenceError: updatePreview is not defined` (swallowed by Signal's try/catch and logged) → the terrain preview
77
+ image is never set, the view renders an empty `<img>`. `terrain.set(null)` →
78
+ `TypeError: Cannot read properties of null (reading 'preview')`.
79
+ - **Fix**: make `updatePreview`/`setPreview` instance methods, subscribe with `add(this.__setTerrain, this)`, and
80
+ guard the `terrain === null` case.
81
+ - **Confidence**: Confirmed
82
+
83
+ ### VIEW-5 `ViewGroup.remove()` calls a non-existent `Set.remove`; `disconnect()` adds instead of removes
84
+ - **Severity**: CRITICAL
85
+ - **File**: `src/view/ViewGroup.js:34,74-89`
86
+ - **Defect**: `this.elements` is a `Set`; `Set` has `delete`, not `remove`. Separately, `disconnect()` iterates every
87
+ member and calls `this.container.addChild(view)` where the whole point of the method is to detach them.
88
+ - **Failure scenario**: `group.remove(view)` → `TypeError: this.elements.remove is not a function`.
89
+ `group.connect(a); group.connect(b)` → `connect` calls `disconnect()`, which re-adds every view to container `a`
90
+ (pushing a duplicate entry into `a.children` and re-appending the DOM node), sets `this.container = null`, then
91
+ `connect` adds them all to `b`. Container `a` is left with duplicate `children` entries pointing at views whose
92
+ DOM nodes now live under `b`; a later `a.removeAllChildren()` calls `a.el.removeChild(child.el)` on a node that is
93
+ no longer its child → `NotFoundError` DOMException.
94
+ - **Fix**: `this.elements.delete(view)`; `disconnect()` must call `this.container.removeChild(view)`.
95
+ - **Confidence**: Confirmed
96
+
97
+ ### VIEW-6 `MinimapView.clear()` adds children instead of removing them
98
+ - **Severity**: CRITICAL
99
+ - **File**: `src/view/minimap/Minimap.js:183-188` (called from `unlink()` at `:236`)
100
+ - **Defect**: The method is documented "remove all existing markers" / "clear out all camera views" but its body is
101
+ `this.__worldView.addChild(v)` for each camera view — the views are already children, so each `unlink()` pushes a
102
+ duplicate entry into `__worldView.children`.
103
+ - **Failure scenario**: Open the minimap, close it, open it again (each cycle = one link/unlink pair). After N
104
+ cycles `__worldView.children` holds each `MinimapCameraView` N+1 times. Now the camera entity is destroyed:
105
+ `cameraRemoved` → `__worldView.removeChild(cameraView)` splices out *one* entry and detaches the DOM node, leaving
106
+ stale duplicates. On the next `unlink()`, `clear()` runs `addChild` on that stale duplicate, which does
107
+ `this.el.appendChild(child.el)` — re-inserting the frustum polygon of a camera that no longer exists back into the
108
+ minimap, and re-linking it on the next `link()` so it keeps updating against a dead `Transform`.
109
+ - **Fix**: `this.__worldView.removeChild(v)` and iterate a copy (or iterate backwards) since `removeChild` mutates.
110
+ - **Confidence**: Confirmed
111
+
112
+ ### VIEW-7 `TaskProgressView` displays progress where remaining time belongs
113
+ - **Severity**: MAJOR
114
+ - **File**: `src/view/task/TaskProgressView.js:127-131`
115
+ - **Defect**: `const estimate = Number.isNaN(computedEstimate) ? 0 : computedProgressValue;` — the non-NaN branch uses
116
+ `computedProgressValue` (the 0..1 progress fraction) instead of `computedEstimate` (the estimator's output). The
117
+ computed estimate is discarded.
118
+ - **Failure scenario**: A 60-second load at 20% progress. `remainingTimeEstimator.estimate()` returns ~48, but the
119
+ `.remaining-time` label is fed `0.2` and formatted with `toFixed(0)` → it reads `0`. The loading screen shows
120
+ "0 seconds remaining" for the entire load, then jumps to "1" at completion.
121
+ - **Fix**: `const estimate = Number.isNaN(computedEstimate) ? 0 : computedEstimate;`
122
+ - **Confidence**: Confirmed
123
+
124
+ ### VIEW-8 `ColorPickerView` unsubscribes from the new colour instead of the old one
125
+ - **Severity**: MAJOR
126
+ - **File**: `src/view/elements/ColorPickerView.js:282-294`
127
+ - **Defect**:
128
+ ```js
129
+ this.model.onChanged.add(function (v, _v) {
130
+ if (v !== null) { modelValueChanged(...); v.onChanged.add(modelValueChanged); }
131
+ if (_v !== null) { v.onChanged.remove(modelValueChanged); } // <-- v, should be _v
132
+ });
133
+ ```
134
+ The removal targets the *new* value. The old value keeps the listener forever, and the new value gets `add`
135
+ immediately followed by `remove`.
136
+ - **Failure scenario**: `picker.model.set(colorA)` then `picker.model.set(colorB)`. Afterwards, changing `colorB`
137
+ externally does not move the H/S/L/A gauges (its listener was removed), while changing `colorA` — which the picker
138
+ no longer edits — does move them. Additionally `picker.model.set(null)` after having a colour executes
139
+ `null.onChanged.remove(...)` → `TypeError: Cannot read properties of null (reading 'onChanged')`.
140
+ - **Fix**: `if (_v !== null) { _v.onChanged.remove(modelValueChanged); }`, and perform the removal before the add.
141
+ - **Confidence**: Confirmed
142
+
143
+ ### VIEW-9 `ColorPickerView` value-channel write lock uses a key that does not exist
144
+ - **Severity**: MAJOR
145
+ - **File**: `src/view/elements/ColorPickerView.js:156-161,214,224,229,257,266`
146
+ - **Defect**: `writeLocks` is declared with keys `h, s, l, a`. The `colorV` handler checks and sets `writeLocks.v`
147
+ (undefined key), while `modelValueChanged` checks `writeLocks.l`. The lock protecting the value/lightness channel
148
+ therefore never engages in either direction.
149
+ - **Failure scenario**: Pick a saturated red (h≈0, s=1, v=1), then drag the **L** gauge to 0. `colorV.onChanged` runs
150
+ unguarded (`writeLocks.v` is `undefined`), writes rgb `(0,0,0)` into the model, which dispatches
151
+ `modelValueChanged`; that handler's guard reads `writeLocks.l` — also never set by the V handler — so it proceeds
152
+ and pushes `rgb2hsv(0,0,0)` back into the gauges, snapping H and S to 0. The user's hue and saturation are
153
+ destroyed by moving the lightness slider, and cannot be recovered by dragging L back up.
154
+ - **Fix**: use one consistent key (`v`) in the declaration, the `colorV` handler, and `modelValueChanged`.
155
+ - **Confidence**: Confirmed
156
+
157
+ ### VIEW-10 `Vector1Control` binds the write-back handler to the model's change signal
158
+ - **Severity**: MAJOR
159
+ - **File**: `src/view/controller/controls/Vector1Control.js:61-81`
160
+ - **Defect**: `subscribe(v1)` does `v1.onChanged.add(writeBack)`. `writeBack` is the *controller → model* direction
161
+ (`vector1.set(v)`); the *model → controller* direction is `syncForward`, which is only ever called once, inside
162
+ `subscribe`. `unsubscribe` symmetrically removes `writeBack`, so the mismatch is consistent and silent.
163
+ - **Failure scenario**: Bind a `Vector1Control` to a `Vector1` that some other system writes (e.g. an animated
164
+ property). The number field shows the value present at subscribe time and never updates again: each external change
165
+ invokes `writeBack(newValue)` which writes `newValue` straight back into the same vector (a no-op) instead of
166
+ refreshing `cNumber.value`.
167
+ - **Fix**: `v1.onChanged.add(syncForward)` in `subscribe` and `v1.onChanged.remove(syncForward)` in `unsubscribe`;
168
+ keep `lockForward` to break the echo.
169
+ - **Confidence**: Confirmed
170
+
171
+ ### VIEW-11 `ListController` removes the wrong view, so deleted rows stay on screen
172
+ - **Severity**: MAJOR
173
+ - **File**: `src/view/controller/controls/ListController.js:48-74`
174
+ - **Defect**: `handleItemAdded` wraps `guiControl` in a `vElementContainer` and adds *that* to `vContainer`.
175
+ `handleItemRemoved` then calls `vContainer.removeChild(guiControl)` — `guiControl` is a child of
176
+ `vElementContainer`, not of `vContainer`, so `children.indexOf()` returns `-1` and `removeChild` returns `false`
177
+ without doing anything.
178
+ - **Failure scenario**: Click the `.close` button next to a list item. The item leaves the model
179
+ (`list.removeOneOf(item)`), `elementControllers` drops the entry, `guiControl.model.set(null)` blanks the control —
180
+ but the row (control + close button) remains in the DOM permanently. Clicking its close button again calls
181
+ `list.removeOneOf(item)` on an item that is no longer present. Rebinding the controller to a different list via
182
+ `detachList` leaves every old row visible on top of the new ones.
183
+ - **Fix**: keep a `Map<item, vElementContainer>` (or store the wrapper on the control) and remove the wrapper.
184
+ - **Confidence**: Confirmed
185
+
186
+ ### VIEW-12 `HTMLElementCacheKey.initializeFromElement` wipes the styles it just read (shadowed loop variable)
187
+ - **Severity**: MAJOR
188
+ - **File**: `src/view/common/HTMLElementCacheKey.js:189-217`
189
+ - **Defect**:
190
+ ```js
191
+ let i = 0;
192
+ ...
193
+ for (let i = 0; i < styleCount; i++) { ... this.style[i] = pair; } // inner `i` shadows outer
194
+ this.style.splice(i, this.style.length - i); // outer i is still 0
195
+ ```
196
+ The truncation call meant to drop leftover entries instead removes the entire array. (The attribute loop below uses
197
+ `for (i = 0; ...)` without `let`, so it truncates correctly — proving the intent.) The key therefore always reports
198
+ "no inline styles", while `hash()`/`equals()` treat that as a real property of the element.
199
+ - **Failure scenario**: `imageViewA.css({ filter: 'grayscale(1)' })` on an `<img src="x.png" class="icon">`, then
200
+ `imageViewA.destroy()` → `key.initializeFromElement(el)` records the tag and attributes but **not** the filter →
201
+ the element is pooled under a key that claims no styles. Later `new ImageView('x.png', {classList:['icon']})`
202
+ builds a style-less key, `view_pool.get(key)` matches, and the recycled element is returned still carrying
203
+ `filter: grayscale(1)` → the new image renders greyed out.
204
+ - **Fix**: rename the inner loop variable (or hoist it) so the splice truncates from `styleCount`.
205
+ - **Confidence**: Confirmed
206
+
207
+ ### VIEW-13 `TabbedView` never attaches its toggle and panel containers — it renders nothing
208
+ - **Severity**: MAJOR
209
+ - **File**: `src/view/common/TabbedView.js:49-57`
210
+ - **Defect**: The constructor creates `this.el`, then `this.__panelContainer` and `this.__toggleContainer`, but never
211
+ calls `this.addChild(...)` on either, and neither does `link()`. Every toggle and panel is added to a container
212
+ that is not in the view tree.
213
+ - **Failure scenario**: `const t = new TabbedView({tabs}); parent.addChild(t);` → a bare empty `<div>`. Tab toggles
214
+ and the active panel exist as detached DOM and are never linked (so their signal bindings never activate either).
215
+ - **Fix**: `this.addChild(this.__toggleContainer); this.addChild(this.__panelContainer);` in the constructor.
216
+ - **Confidence**: Confirmed
217
+
218
+ ### VIEW-14 `MinimapFogOfWar.enforceAspectRatio` computes the wrong growth in the "too wide" branch
219
+ - **Severity**: MAJOR
220
+ - **File**: `src/view/minimap/gl/MinimapFogOfWar.js:16-38`
221
+ - **Defect**: When `aspectRatioDelta <= 0` the code grows the width by `-aabbWidth * aspectRatioDelta`. Solving,
222
+ the resulting ratio is `aabbHeight / (aabbWidth * (1 + aAR - vAR))`, which only equals `vAR` by coincidence. The
223
+ height branch is correct (`aabbWidth * delta` yields exactly `aabbWidth * vAR`); the width branch is not the
224
+ mirror of it.
225
+ - **Failure scenario**: minimap viewport 200×100 (`vAR = 0.5`), revealed fog region a 100×100 square (`aAR = 1`).
226
+ `delta = -0.5`, `d = 50`, new bounds 150×100 → ratio 0.667, not 0.5. `focusArea` is set to that region and drives
227
+ the orthographic camera in `MinimapWorldGL.updateCameraFocus`, so the minimap world is squashed horizontally by
228
+ ~33%: terrain, entity markers and the camera frustum polygon (which are positioned from `worldScale`) no longer
229
+ line up with the fog-of-war overlay.
230
+ - **Fix**: `const d = aabbHeight / viewportAspectRatio - aabbWidth;` (equivalently grow to `aabbHeight / vAR`).
231
+ - **Confidence**: Confirmed
232
+
233
+ ### VIEW-15 `ListView.insertOne` dereferences an undefined sibling view when a filter is in play
234
+ - **Severity**: MAJOR
235
+ - **File**: `src/view/common/ListView.js:182-197`
236
+ - **Defect**: For a non-terminal insert it looks up `this.model.get(index + 1)` and calls `nextChild.el` without
237
+ checking that a view exists for it. `getChildByElement` returns `undefined` whenever the next element was skipped
238
+ by `this.filter` (or when the list contains duplicate elements — `viewMapping` is keyed by element identity, so a
239
+ duplicate overwrites the previous entry).
240
+ - **Failure scenario**: `new ListView(model, {elementFactory, filter: e => e.visible})`. Model is `[A(visible),
241
+ C(hidden)]`; insert `B(visible)` at index 1. `insertOne` creates B's view, sees `model.length (3) !== index+1 (2)`,
242
+ fetches `C`, `getChildByElement(C)` → `undefined` → `TypeError: Cannot read properties of undefined (reading 'el')`
243
+ inside the `model.on.added` dispatch. Signal logs it and swallows it, so the symptom is a silently mis-ordered list
244
+ (B stays appended at the end) plus a console error on every filtered insert.
245
+ - **Fix**: scan forward from `index + 1` for the first element that has a view; if none, leave the child appended.
246
+ - **Confidence**: Confirmed
247
+
248
+ ### VIEW-16 `DomSizeObserver.attach()` unobserves the new element and never observes it
249
+ - **Severity**: MAJOR
250
+ - **File**: `src/view/util/DomSizeObserver.js:147-153`
251
+ - **Defect**:
252
+ ```js
253
+ attach(element) {
254
+ this.element = element; // old reference already lost
255
+ if (this.running) { this.__dom_resize_observer.unobserve(this.element); } // unobserves the NEW element
256
+ }
257
+ ```
258
+ The old element is never unobserved (it stays in the `ResizeObserver`), and the new element is never observed
259
+ because `attach` only ever calls `unobserve`.
260
+ - **Failure scenario**: `o.attach(elA); o.start();` then `o.attach(elB)` while running. `unobserve(elB)` is a no-op
261
+ (B was never observed), A remains observed. Resizing B produces no callback at all — `o.dimensions` goes stale.
262
+ Resizing A *does* fire the callback, which then measures **B** via `resizeAABB2ToFitBoundingClientRect(this.element…)`
263
+ for the position but takes `rect.width/height` from **A's** `contentRect` → `dimensions` is a mix of two elements.
264
+ - **Fix**: capture the previous element, `unobserve(previous)` if running, assign, then `observe(element)` if running.
265
+ - **Confidence**: Confirmed
266
+
267
+ ### VIEW-17 `SimpleWindowView` resize handler accumulates the full drag delta on every pointer move
268
+ - **Severity**: MAJOR
269
+ - **File**: `src/view/elements/SimpleWindow.js:47-73`
270
+ - **Defect**: `anchor` is captured once on pointer-down and never advanced, yet the move handler does
271
+ `view.size.add(position - anchor)` — an *incremental* mutation fed an *absolute* delta. Compare
272
+ `BottomLeftResizeHandleView` (`elements/BottomLeftResizeHandleView.js:31-40`), which correctly does
273
+ `lastPosition.copy(position)` each move.
274
+ - **Failure scenario**: `new SimpleWindowView(content, {resizable: true})`. Grab the bottom-right 10 px corner and
275
+ drag 10 px right over 5 pointer-move events (deltas 2, 4, 6, 8, 10 relative to the fixed anchor) → the width grows
276
+ by 30 px instead of 10. A slow 200 px drag over 100 events grows the window by ~10 000 px; the window runs away
277
+ from the cursor and cannot be resized back down.
278
+ - **Fix**: either update `anchor` to `position` at the end of each move, or capture `originalSize` on pointer-down and
279
+ use `view.size.copy(originalSize).add(delta)`.
280
+ - **Confidence**: Confirmed
281
+
282
+ ### VIEW-18 `ToastLogView` registers every notification twice in `children`
283
+ - **Severity**: MAJOR
284
+ - **File**: `src/view/elements/notify/ToastLogView.js:47,72-88`
285
+ - **Defect**: The constructor reassigns `this.children = []` (shadowing the base `View.children` array), and `addOne`
286
+ then does **both** `self.addChild(childView)` — which pushes onto `this.children` — **and**
287
+ `self.children.push(childView)`. Every toast appears twice in the array. `removeChildView` splices out one
288
+ occurrence and bypasses `View.removeChild`, so the second entry survives with its DOM node already detached.
289
+ - **Failure scenario**: Two notifications A then B. `children` = `[A, A, B, B]`, so `updatePositions` computes
290
+ `maxIndex = 3`: A ends at `-(3-1)*24 = -48 px` and B at `0`, instead of `-24` and `0` → a 24 px gap opens between
291
+ the two toasts and the stack floats one row too high. After A's fade-out, `children` = `[A, B, B]` and A's stale
292
+ entry keeps skewing every subsequent layout. If the view is ever destroyed, `View.destroy`/`removeAllChildren`
293
+ walks the duplicates and calls `this.el.removeChild(A.el)` on an already-detached node → `NotFoundError`.
294
+ - **Fix**: delete the `this.children = []` reassignment and the manual `push`; use `View.removeChild` in
295
+ `removeChildView`. Also cancel the pending `setTimeout` handles on unlink and unsubscribe
296
+ `model.elements.on.added` (currently a permanent subscription, `:90`).
297
+ - **Confidence**: Confirmed
298
+
299
+ ### VIEW-19 `RadialProgressView` subscribes to its external model permanently
300
+ - **Severity**: MAJOR
301
+ - **File**: `src/view/elements/radial/RadialProgressView.js:55-68`
302
+ - **Defect**: `model.on.changed.add(update)` / `model[0].onChanged.add(redraw)` / `model[1].onChanged.add(redraw)` are
303
+ raw subscriptions on caller-owned objects, made in the constructor and never removed — the class has no `unlink()`
304
+ or `destroy()` override, and does not use `bindSignal`.
305
+ - **Failure scenario**: `view/units/UnitRadialPreview.js:23` builds
306
+ `new RadialProgressView([unit.healthCurrent, unit.stats.healthMax], …)`. The unit outlives the preview widget
307
+ (health is model state). Every time a unit preview is created and discarded, the unit's `healthCurrent` signal
308
+ retains `redraw`, which closes over the view, its SVG element and its `thickness` observable — the whole widget is
309
+ unreclaimable, and every health tick redraws N dead widgets. Cycling a roster panel a few hundred times leaks
310
+ hundreds of SVG subtrees.
311
+ - **Fix**: route all three through `this.bindSignal(...)` so they follow the view's link lifecycle.
312
+ - **Confidence**: Confirmed
313
+
314
+ ### VIEW-20 `createInterfaceCommandButton` subscribes to the command's feature signals twice, one of them forever
315
+ - **Severity**: MAJOR
316
+ - **File**: `src/view/interaction/createInterfaceCommandButton.js:91-99`
317
+ - **Defect**:
318
+ ```js
319
+ if (interaction.features !== undefined) {
320
+ interaction.features.on.added.add(addCommandFeature); // permanent
321
+ interaction.features.on.removed.add(removeCommandFeature); // permanent
322
+ }
323
+ button.bindSignal(interaction.features.on.added, addCommandFeature); // link-scoped (correct)
324
+ button.bindSignal(interaction.features.on.removed, removeCommandFeature); // link-scoped (correct)
325
+ ```
326
+ `InteractionCommand` always constructs `this.features = new List(features)` (`interaction/InteractionCommand.js:40`),
327
+ so the `if` is always taken and the first pair is always added. Nothing ever removes them.
328
+ - **Failure scenario**: `InteractionCommand` instances are long-lived and shared — `InteractionCommandSet` keys them
329
+ by id. A command bar that is rebuilt on every selection change produces a new `ButtonView` per command each time;
330
+ each one permanently registers two closures on the shared command's feature list. After 100 selection changes,
331
+ `interaction.setFeature('highlighted', true)` invokes `addCommandFeature` on 100 discarded buttons, and all 100
332
+ button subtrees are unreclaimable.
333
+ - **Fix**: delete the raw `on.added`/`on.removed` subscriptions; the `bindSignal` pair already covers the live case
334
+ and `button.on.linked` already replays the current features.
335
+ - **Confidence**: Confirmed
336
+
337
+ ### VIEW-21 `MeshPreview` multiplies its pointer handlers on every link, and dereferences a null camera
338
+ - **Severity**: MAJOR
339
+ - **File**: `src/view/elements/MeshPreview.js:204-234`
340
+ - **Defect**: (a) `link()` attaches a fresh `self.pContents.then(...)` continuation each time. Because `pContents` is
341
+ already settled after the first load, every subsequent link immediately runs `__addInteraction`, which creates a
342
+ **new** `PointerDevice`, calls `start()` on it, and adds another `dragStart`/`drag` pair that mutates
343
+ `contents.group.rotation` — none of which is ever stopped in `unlink()`. (b) `__update_renderer_size` guards on
344
+ `this.renderer !== null` but then touches `this.camera.aspect`; `camera` is only assigned in the asset callback.
345
+ - **Failure scenario (a)**: Open a unit-detail panel containing a `MeshPreview`, close it, open it again. Two
346
+ `PointerDevice`s are now live on the pooled canvas; one drag rotates the model twice as fast. After ten cycles the
347
+ model spins ~10× per pixel of drag. (b): `preview.size.set(256, 256)` after linking but before the glTF resolves —
348
+ the bound `size.onChanged` fires with `renderer` set and `camera` still `null` →
349
+ `TypeError: Cannot set properties of null (setting 'aspect')`.
350
+ - **Fix**: attach the `pContents` continuation once in the constructor and have it store `contents.group`; create the
351
+ `PointerDevice` once and `start()`/`stop()` it from `link`/`unlink`. Guard `__update_renderer_size` on
352
+ `this.camera !== null` as well (it is genuinely null until the async load lands).
353
+ - **Confidence**: Confirmed
354
+
355
+ ### VIEW-22 `renderModel` caches the caller's live `size`/`focus` objects, so resizes return the stale image
356
+ - **Severity**: MAJOR
357
+ - **File**: `src/view/renderModel.js:15-29,85-92`
358
+ - **Defect**: The cache entry stores `size: size` and `focus: focus` by reference, and `findInCache` compares with
359
+ `piece.size.equals(size)` / component-wise on `focus`. When the caller passes a mutable vector, the cached entry's
360
+ key mutates in lockstep with the query, so the comparison always succeeds.
361
+ - **Failure scenario**: `MeshView.render()` (`common/MeshView.js:61`) passes `this.size` and `this.focus` straight
362
+ through. Render a mesh preview at 50×50 — cached with `piece.size === view.size`. Resize the view to 200×200:
363
+ `update()` sees the change and calls `render()`, `findInCache(url, this.size, this.focus)` compares `this.size`
364
+ against itself → hit → the 50×50 `dataURL` is returned and stretched to 200×200 (blurry), and no re-render is ever
365
+ scheduled. The cache also has no eviction (`cache.push` only), so it grows without bound.
366
+ - **Fix**: store `size.clone()` and a copied `AABB2` in the cache entry; add an eviction policy (the codebase already
367
+ has `core/cache/Cache`).
368
+ - **Confidence**: Confirmed
369
+
370
+ ### VIEW-23 `MeshView` never reacts to its own model
371
+ - **Severity**: MAJOR
372
+ - **File**: `src/view/common/MeshView.js:72-92`
373
+ - **Defect**: The view observes `this.size` only. `update()`'s change test compares `size` and `focus` against
374
+ `renderedParams` and ignores the model entirely, so even an explicit `update()` after a model change does nothing.
375
+ `this.model.onChanged` is never bound.
376
+ - **Failure scenario**: `meshView.model.set('models/sword.gltf')` on a linked `MeshView` currently showing
377
+ `models/axe.gltf` → nothing happens; a manual `meshView.update()` also short-circuits on "no change". The view keeps
378
+ displaying the axe until the element is resized.
379
+ - **Fix**: `this.bindSignal(this.model.onChanged, this.render, this)`, and include the rendered URL in
380
+ `renderedParams` so `update()` detects it.
381
+ - **Confidence**: Confirmed
382
+
383
+ ### VIEW-24 `RectangularPieProgressView` assumes a square element; on any other aspect the path becomes invalid
384
+ - **Severity**: MAJOR
385
+ - **File**: `src/view/elements/progress/RectangularPieProgressView.js:77-107`
386
+ - **Defect**: The fraction thresholds `.125 / .375 / .625 / .875` place the corner transitions at 45°, which is only
387
+ where the corners are for a square. For a non-square element the sweep ray exits through a different edge than the
388
+ branch tests, `segment2_segment_compute_intersection_array_2d` returns `false` and leaves `p` empty, and the path
389
+ string is built from `p[0]`/`p[1]` === `undefined`.
390
+ - **Failure scenario**: `v.size.set(100, 50); v.model.set(13); v.max.set(100)` (fraction 0.13 → branch 2, which tests
391
+ the **right** edge). `angle ≈ 43°` from the centre `(50,25)`: reaching `x = 100` needs `Δy = -47`, i.e. `y = -22`,
392
+ outside the edge segment — the ray actually exits through the **top** edge at `x ≈ 76.6`. No intersection is
393
+ written, so `d` becomes `"M 50 0 L 50 25 L undefined undefined L 100 50 L 0 50 L 0 0 Z"`. Browsers reject the whole
394
+ `d` attribute → the cooldown overlay disappears entirely for that fraction range.
395
+ (In-repo the only caller, `view/units/ability/CombatAbilityView.js:30`, sizes it 64×64, so the game path is safe —
396
+ but this is a public class with a `size` the caller controls.)
397
+ - **Fix**: compute the corner fractions from the actual aspect (`atan2(size_y, size_x)` etc.) instead of hard-coded
398
+ eighths, or pick the edge by testing all four and taking whichever intersects.
399
+ - **Confidence**: Confirmed
400
+
401
+ ### VIEW-25 `EmptyView.absolute` nests the caller's CSS instead of spreading it
402
+ - **Severity**: MAJOR
403
+ - **File**: `src/view/elements/EmptyView.js:54-72`
404
+ - **Defect**:
405
+ ```js
406
+ css: {
407
+ css, // shorthand -> a property literally named "css"
408
+ ...CSS_ABSOLUTE_POSITIONING
409
+ }
410
+ ```
411
+ The intent is clearly `...css`. `View.css(hash)` then executes `this.el.style['css'] = {…}`, which the CSSOM
412
+ ignores.
413
+ - **Failure scenario**: `EmptyView.absolute({ css: { width: '100px', backgroundColor: 'red' } })` produces an element
414
+ with only `position/top/left` applied; width and background are silently dropped, so the element collapses to zero
415
+ size. No error is raised anywhere.
416
+ - **Fix**: `css: { ...css, ...CSS_ABSOLUTE_POSITIONING }`.
417
+ - **Confidence**: Confirmed
418
+
419
+ ### VIEW-26 `TileGridView` subscribes to the model and the DnD context outside the view lifecycle
420
+ - **Severity**: MAJOR
421
+ - **File**: `src/view/elements/tiles2d/TileGrid.js:135-136,301-338,411-419`
422
+ - **Defect**: `model.tiles.on.added.add(this.addTile, this)` and `.on.removed.add(this.removeTile, this)` are raw
423
+ subscriptions (not `bindSignal`) with no counterpart anywhere. Likewise every slot registers a `DropTarget` into
424
+ `this.__dragAndDropContext` via `addTarget` (which immediately `link()`s DOM listeners) and every tile registers a
425
+ `Draggable` via `addElement`; neither `removeTarget` nor `removeElement` is ever called, and the context is a
426
+ constructor parameter, i.e. typically shared across grids.
427
+ - **Failure scenario**: An inventory panel builds a 10×6 `TileGridView` against a shared `DragAndDropContext` each
428
+ time it opens. Every open/close cycle permanently adds 60 `DropTarget`s (each with 4 DOM listeners) and one
429
+ `Draggable` per item to `context.targets`/`context.elements`, and leaves the grid subscribed to `model.tiles`. After
430
+ 20 cycles, `DragAndDropContext.finalizeDrag` iterates 1200+ targets on every drop, `getElementById` scans hundreds
431
+ of dead draggables, and adding an item to the inventory while all panels are closed calls `addTile` on 20 detached
432
+ grids. Removing an item calls `removeTile` on grids where `findTileView` returns `undefined`, so
433
+ `this.__hookTileRemoved(undefined, tile)` fires with an undefined view.
434
+ - **Fix**: route the two model subscriptions through `bindSignal`; add an `unlink()` that calls
435
+ `context.removeTarget(slotView)` for each slot and `context.removeElement(draggable)` for each tile, and rebuild on
436
+ `link()`.
437
+ - **Confidence**: Confirmed
438
+
439
+ ### VIEW-27 `LocalizedLabelView.update()` dereferences a null localization outside the try
440
+ - **Severity**: MAJOR
441
+ - **File**: `src/view/common/LocalizedLabelView.js:122-154`
442
+ - **Defect**: `localization = null` is the constructor default and the class explicitly tests for it at `:60`, so it
443
+ is an anticipated state. `update()` wraps only `localization.getString(...)` in `try/catch`; line 143
444
+ (`this.__localeKey = localization.locale.getValue()`) and the `$el.text(value)` fallback that follows are outside
445
+ it. The throw at 143 skips the fallback text.
446
+ - **Failure scenario**: `new TaskProgressView({ task })` — `localization` defaults to `null`
447
+ (`task/TaskProgressView.js:20,29-33`) — then link. The `on.linked` handler calls `update()`, `getString` throws,
448
+ the catch sets `value = "failed to localize @…"`, then line 143 throws `TypeError: Cannot read properties of null
449
+ (reading 'locale')` before the text is written. Signal's dispatch try/catch swallows it, so the loading screen's
450
+ task-name label renders completely blank with two console errors per link.
451
+ - **Fix**: return early (writing the raw `@id` fallback) when `localization === null`, and move the `__localeKey`
452
+ assignment after a successful `getString`.
453
+ - **Confidence**: Confirmed
454
+
455
+ ### VIEW-28 `MarkerGL` leaks atlas patch references acquired across shutdown / rapid icon changes
456
+ - **Severity**: MAJOR
457
+ - **File**: `src/view/minimap/gl/MarkerGL.js:57-87,109-118`
458
+ - **Defect**: `updateIcon` releases the *current* `this.patch`, then awaits `atlasManager.acquire(newURL)`. The
459
+ continuation assigns `this.patch = patch` and then bails on `!this.active` — but the freshly acquired reference is
460
+ never released on that path. Similarly, two `updateIcon` calls in flight both release `Reference.NULL` up front and
461
+ the first resolved patch is overwritten (and leaked) by the second.
462
+ - **Failure scenario**: A unit with a minimap marker is killed while its icon texture is still being fetched
463
+ (`MinimapMarkersGL.removeElement` → `markerGL.shutdown()` → `active = false`, releases `Reference.NULL`). The
464
+ `acquire` promise then resolves, stores the patch on the dead marker and returns without releasing it → the
465
+ `ManagedAtlas` never frees that icon's slot. Repeated over a battle with many short-lived markers, the atlas fills
466
+ up and later markers fail to get a patch.
467
+ - **Fix**: in the continuation, if `!this.active`, call `patch.release()` before returning; also release the previous
468
+ `this.patch` when overwriting it rather than at call time.
469
+ - **Confidence**: Confirmed
470
+
471
+ ### VIEW-29 `DropTarget` drag-enter tracking has no dedup and splices with `-1`
472
+ - **Severity**: MAJOR
473
+ - **File**: `src/view/common/dnd/DropTarget.js:72-92,212-236`
474
+ - **Defect**: `handleDragEnter` pushes into `isInState_ENTER` unconditionally, and
475
+ `attachDropValidityIndicators.handleDragEnter` unconditionally appends a `{draggable, bindings}` record with a fresh
476
+ `SignalBinding` on `draggable.on.dragFinalized`. `removeDraggable` removes exactly one record per call.
477
+ `handleDragLeave` additionally does `isInState_ENTER.splice(indexOf(e), 1)` without checking for `-1`, and
478
+ `splice(-1, 1)` removes the *last* element.
479
+ - **Failure scenario**: `Draggable.link()` explicitly routes `dragenter` to the parent drop target
480
+ (`common/dnd/Draggable.js:103-106`) *and* the event bubbles to the drop target's own listener — so dragging an item
481
+ over another item inside the same slot fires `handleDragEnter` twice for one enter. `current` gains two records and
482
+ two live bindings. On drop, `dragFinalized` fires once, `removeDraggable` clears one record, and `update()` still
483
+ sees a non-empty `current` → the slot keeps its `drop-target-hover-valid` class permanently after the drag ends,
484
+ and each further hover leaks another `SignalBinding` on the draggable.
485
+ - **Fix**: dedup on enter (skip if the draggable is already tracked), loop `removeDraggable` until it returns false on
486
+ finalize, and guard the `indexOf === -1` case before splicing.
487
+ - **Confidence**: Likely
488
+
489
+ ### VIEW-30 A throwing tooltip factory disables tooltips globally for the rest of the session
490
+ - **Severity**: MAJOR
491
+ - **File**: `src/view/tooltip/TooltipManager.js:129-138`
492
+ - **Defect**:
493
+ ```js
494
+ gml.pushState();
495
+ gml.setTooltipsEnabled(false);
496
+ const factoryProduct = tip.factory.call(tip.factoryContext); // may throw
497
+ gml.popState();
498
+ ```
499
+ There is no `try/finally`. `GMLEngine.compile`/`compileAsText` both use `try { … } finally { this.popState(); }`
500
+ (`tooltip/gml/GMLEngine.js:481-493,512-525`), so the omission here is clearly unintended.
501
+ - **Failure scenario**: A single tooltip factory throws (e.g. an item tooltip for an item whose data row is missing).
502
+ `popState()` is skipped, so `__tooltipsEnabled` stays `false` and one orphan frame stays on `__contextStack`. Every
503
+ reference compiler that consults `gml.getTooltipsEnabled()` from then on sees `false` → nested tooltips stop being
504
+ attached anywhere in the UI until reload.
505
+ - **Fix**: wrap the factory call in `try { … } finally { gml.popState(); }`.
506
+ - **Confidence**: Confirmed
507
+
508
+ ### VIEW-31 `RadialMenu.init()` leaves the previous element views attached, and shared icon views get stolen
509
+ - **Severity**: MAJOR
510
+ - **File**: `src/view/elements/radial/RadialMenu.js:194-223`, `src/view/elements/radial/RadialMenuElement.js:70`
511
+ - **Defect**: `init()` resets `this.elements = []` but never removes the previously created `RadialMenuElement`
512
+ children from `this.vElementContainer`. Separately, `RadialMenuElement`'s constructor does
513
+ `this.addChild(description.iconView)` — the icon `View` lives on the caller-owned
514
+ `RadialMenuElementDefinition`, and `View.addChild` re-parents it (`child.parent = this; this.el.appendChild(child.el)`).
515
+ - **Failure scenario**: (a) `menu.init(newItems)` on an existing menu — the old wedges, labels and icons stay in the
516
+ DOM underneath the new ones, and `selectByAngle`/`render` only touch the new set, so the stale wedges are frozen in
517
+ place and never highlight. (b) Building two `RadialMenu`s from the same `items` array (definitions are plain data
518
+ objects that are easy to reuse) — the second menu's `addChild` moves every `iconView`'s DOM node out of the first
519
+ menu, leaving the first menu iconless while both `children` arrays still list it.
520
+ - **Fix**: `this.vElementContainer.removeAllChildren()` at the top of `init()`; and either clone the icon view per
521
+ element or document/enforce one definition per menu.
522
+ - **Confidence**: Confirmed
523
+
524
+ ### VIEW-32 `ConfirmationDialogView` builds a class name that can contain a space
525
+ - **Severity**: MAJOR
526
+ - **File**: `src/view/elements/ConfirmationDialogView.js:38`
527
+ - **Defect**: `"button-" + option.name.replace(' ', '-')` — `String.replace` with a string pattern replaces only the
528
+ **first** occurrence. The result is handed to `ButtonView`'s `classList`, which reaches `DOMTokenList.add()`.
529
+ - **Failure scenario**: `new ConfirmationDialogView(content, [{name: 'cancel all now', displayName: 'Cancel', …}])`
530
+ → class token `"button-cancel-all now"` → `classList.add` throws
531
+ `InvalidCharacterError: The string contains invalid characters`, aborting the whole dialog construction so no
532
+ confirmation dialog is shown at all.
533
+ - **Fix**: `option.name.replace(/\s+/g, '-')`, or reuse `string_tag_to_css_class_name`.
534
+ - **Confidence**: Confirmed
535
+
536
+ ### VIEW-33 `VirtualListView` disables the scrollbar one row too early, and `AlignmentOption.Center` does nothing
537
+ - **Severity**: MINOR
538
+ - **File**: `src/view/common/VirtualListView.js:181-196`
539
+ - **Defect**: The "everything fits" test is
540
+ `row_height * (last_visible_line - first_visible_line) < this.size.y`, i.e. it measures `n-1` rows instead of `n`.
541
+ Separately, `AlignmentOption.Center` is exported and accepted as `verticalAlignment` but the offset block only
542
+ handles `End`, so `Center` silently behaves like `Start`.
543
+ - **Failure scenario**: `lineSize = 20, lineSpacing = 0`, 5 elements, `size.y = 90` (content 100 px). `l0 = 0`,
544
+ `l1 = 4 = numTotalElements - 1`, and `20 * (4 - 0) = 80 < 90` → `__setScrollBar(false)` and `rowWidth` is not
545
+ reduced. The list declares itself fully visible while the 5th row is clipped by 10 px and cannot be scrolled to.
546
+ - **Fix**: compare `row_height * (last - first + 1) <= this.size.y`; implement the `Center` branch
547
+ (`line_offset_y = (this.size.y - total_lines_height) / 2`).
548
+ - **Confidence**: Confirmed
549
+
550
+ ### VIEW-34 `DropDownSelectionView.setSelectedValue` uses the model index against always-appended options
551
+ - **Severity**: MINOR
552
+ - **File**: `src/view/elements/DropDownSelectionView.js:55-68,141-143`
553
+ - **Defect**: `handleAdded(el, index)` ignores `index` and always `appendChild`s, while `setSelectedValue` does
554
+ `this.el.selectedIndex = this.model.indexOf(v)`. The two orderings only agree when elements are appended.
555
+ (`getSelectedValue` correctly resolves through the id map, so the two accessors disagree.) `handleRemoved` also
556
+ never deletes the entry from `this.mapping`.
557
+ - **Failure scenario**: `model.insert(0, x)` on a populated list — `x`'s `<option>` lands last while `model.indexOf(x)`
558
+ is `0`, so `setSelectedValue(x)` selects whatever element was originally first.
559
+ - **Fix**: honour `index` in `handleAdded` (`insertBefore` the option at `index`), and delete the mapping entry in
560
+ `handleRemoved`.
561
+ - **Confidence**: Confirmed
562
+
563
+ ### VIEW-35 `MinimapCameraView.castTerrainRay` jitters an origin it never uses
564
+ - **Severity**: MINOR
565
+ - **File**: `src/view/minimap/dom/MinimapCameraView.js:99-117`
566
+ - **Defect**: The retry loop perturbs `oX/oY/oZ` but calls
567
+ `terrain.raycastFirstSync(rayContact, originX, originY, originZ, …)` with the *unperturbed* origin every iteration.
568
+ `oX/oY/oZ` are written and never read.
569
+ - **Failure scenario**: A frustum corner ray that lands exactly on a terrain triangle edge misses. The stated purpose
570
+ of the loop — "jitter origin in case of mathematical error at polygon edges" — never happens; instead the identical
571
+ raycast runs 10 times and then falls back to the flat `y = 0` plane. On elevated terrain that corner of the minimap
572
+ camera-frustum polygon is drawn at the ground-plane intersection instead of the terrain surface, so the frustum
573
+ outline visibly snaps outward for that corner.
574
+ - **Fix**: pass `oX, oY, oZ` to `raycastFirstSync`.
575
+ - **Confidence**: Confirmed
576
+
577
+ ### VIEW-36 `DOM.prototype.clear()` does not remove text nodes
578
+ - **Severity**: MINOR
579
+ - **File**: `src/view/DOM.js:131-137`
580
+ - **Defect**: The loop iterates `el.children` (elements only), so text nodes survive a method documented as
581
+ "removes all children".
582
+ - **Failure scenario**: `const d = domify('div'); d.text('Loading…'); d.clear(); d.append(other);` → the element still
583
+ reads "Loading…" followed by the appended content. This is reachable through
584
+ `LocalizedLabelView.update()` (`$el.text(value)` on the non-GML path) followed by a switch to a GML-compiled value,
585
+ which calls `removeAllChildren()` and then appends compiled views next to the leftover text node; also
586
+ `MinimapView.link()` (`minimap/Minimap.js:217-219`) relies on `clear()` before appending the WebGL canvas.
587
+ - **Fix**: `while (el.firstChild) el.removeChild(el.firstChild);`
588
+ - **Confidence**: Confirmed
589
+
590
+ ### VIEW-37 `setElementTransform.js` exports nothing
591
+ - **Severity**: MINOR
592
+ - **File**: `src/view/setElementTransform.js:13`
593
+ - **Defect**: The module declares `function setElementTransform(...)` with no `export` and no default export, so the
594
+ file's only purpose is unreachable.
595
+ - **Failure scenario**: `import { setElementTransform } from '.../setElementTransform.js'` →
596
+ `SyntaxError: The requested module does not provide an export named 'setElementTransform'` at build time.
597
+ - **Fix**: `export function setElementTransform(...)`.
598
+ - **Confidence**: Confirmed
599
+
600
+ ### VIEW-38 `DatGuiUtils.makeDatController` references an undeclared `p` in its cycle branch
601
+ - **Severity**: MINOR
602
+ - **File**: `src/view/controller/dat/DatGuiUtils.js:377-380`
603
+ - **Defect**: ``console.warn(`Detected cycle at "${p}" …`)`` — `p` is the loop variable of `makeDatControllerForObject`,
604
+ not of this function. Modules are strict-mode, so this is a `ReferenceError`, not `undefined`. The intended
605
+ identifier is `propertyName`.
606
+ - **Failure scenario**: `makeDatController` is exported (`:451`). A direct call
607
+ `makeDatController(gui, obj, 'child', pathContainingObjChild)` hits the cycle branch and throws
608
+ `ReferenceError: p is not defined` instead of warning and returning `0`, aborting the whole controller build.
609
+ - **Fix**: use `${propertyName}`.
610
+ - **Confidence**: Confirmed
611
+
612
+ ### VIEW-39 `GroupView.remove()` leaves the removed child linked; `update()` calls a method `View` does not have
613
+ - **Severity**: MINOR
614
+ - **File**: `src/view/elements/Group.js:8,11-30`
615
+ - **Defect**: `add`/`remove` bypass `View.addChild`/`View.removeChild`: `child.parent` is never set and `remove` never
616
+ calls `child.unlink()`. `update()` invokes `c.update()` on each child, but `View` defines no `update`.
617
+ - **Failure scenario**: `group.add(labelView); group.link(); group.remove(labelView);` — the label's DOM node is
618
+ detached but the view stays linked, so its `bindSignal` subscriptions keep firing and keep writing to a node that is
619
+ no longer in the document. `group.update()` with any plain `EmptyView` child →
620
+ `TypeError: c.update is not a function`.
621
+ - **Fix**: delegate to `View.addChild`/`View.removeChild` (and drop the `this.children = []` reassignment); remove
622
+ `update()` or make it guard on the method existing.
623
+ - **Confidence**: Confirmed
624
+
625
+ ### VIEW-40 `WindRoseDiagram` sizes itself for icons that may not exist, and re-registers tooltips on every draw
626
+ - **Severity**: MINOR
627
+ - **File**: `src/view/elements/windrose/WindRoseDiagram.js:90-94,197-336`
628
+ - **Defect**: (a) `const has_icons = axes.some(isDefined)` tests whether each *axis object* is defined, not whether it
629
+ has an `icon`; for any non-empty `axes` array this is always `true`. (b) `draw_canvas()` calls
630
+ `container.removeAllChildren()` and rebuilds every label/icon, then calls `this.__tooltips.add(view, …)` for each —
631
+ `DomTooltipManager.add` links a `DomTooltipObserver` immediately and is never paired with `remove`.
632
+ - **Failure scenario**: (a) `new WindRoseDiagram({axes: [{name:'a'},{name:'b'},{name:'c'}], radius_outer: 100,
633
+ icon_size: 32})` (no icons at all) → `size = 200 + 32*1.207*2 ≈ 277` instead of `200`; the widget claims 77 px more
634
+ in both axes than it draws, pushing neighbours around in a flex row. (b) `draw()` runs on every `on.linked`; after
635
+ 10 open/close cycles each axis label has 10 live `DomTooltipObserver`s with `mouseenter`/`mouseleave` listeners on
636
+ detached elements.
637
+ - **Fix**: `axes.some(a => a.icon !== undefined)`; use `tooltips.manage(view, …)` (which self-registers on
638
+ link/unlink) rather than `add`.
639
+ - **Confidence**: Confirmed
640
+
641
+ ### VIEW-41 `ImageView`/`VideoView` never re-apply an observed URL on link
642
+ - **Severity**: MINOR
643
+ - **File**: `src/view/elements/image/ImageView.js:65-71`, `src/view/elements/video/VideoView.js:77-83`
644
+ - **Defect**: The `src` is baked into the cache key at construction and thereafter only updated by the
645
+ `url.onChanged` → `__setSource` binding, which is a `bindSignal` and therefore inactive while unlinked. There is no
646
+ `on.linked` initial-apply.
647
+ - **Failure scenario**: An `ImageView` bound to an `ObservedString` icon URL sits in a panel. Close the panel (view
648
+ unlinks, binding detaches), the underlying model swaps the icon (equip a different item), reopen the panel — the
649
+ binding re-links but is never invoked, so the `<img>` still shows the previous icon until the URL happens to change
650
+ again while the panel is open.
651
+ - **Fix**: add `this.on.linked.add(() => this.__setSource(url.getValue()), this)` in the observed-URL branch (mirroring
652
+ `LabelView.link()`, which re-runs `updateTransform()`).
653
+ - **Confidence**: Confirmed
654
+
655
+ ### VIEW-42 `ButtonView` never applies its initial enabled/disabled class
656
+ - **Severity**: MINOR
657
+ - **File**: `src/view/elements/button/ButtonView.js:94,101-110`
658
+ - **Defect**: `__enabled` is initialised by direct field assignment, bypassing the setter, and the setter early-returns
659
+ when the value is unchanged. A button that is enabled from birth therefore carries **neither** `.enabled` nor
660
+ `.disabled`.
661
+ - **Failure scenario**: `.ui-button-view.disabled { opacity: .4 }` + `.ui-button-view.enabled { cursor: pointer }`
662
+ style rules — a freshly created enabled button matches neither. `createInterfaceCommandButton` masks this because
663
+ its `on.linked` handler calls `updateEnableStatus()`, but that only helps when the command's `enabled` differs from
664
+ `true`; a permanently-enabled command's button never gets the class.
665
+ - **Fix**: set the class explicitly at the end of the constructor (`this.setClass('enabled', true);
666
+ this.setClass('disabled', false);`) rather than relying on the setter's change detection.
667
+ - **Confidence**: Likely