@woosh/meep-engine 3.0.2 → 3.2.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 (1823) hide show
  1. package/LICENSE +188 -188
  2. package/README.md +152 -145
  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/core/binary/BitImage2.js +246 -246
  134. package/src/core/binary/align_32.js +21 -21
  135. package/src/core/binary/data_view/DataType2DataViewReaders.js +23 -23
  136. package/src/core/binary/data_view/DataType2DataViewWriters.js +25 -25
  137. package/src/core/binary/hash/XXH128Hash.js +55 -55
  138. package/src/core/binary/hash/XXH3_SECRET.js +25 -25
  139. package/src/core/binary/hash/xxh3_128.js +341 -341
  140. package/src/core/binary/hash/xxh3_64.js +241 -241
  141. package/src/core/binary/hash/xxh3_common.js +476 -476
  142. package/src/core/binary/lz4/LZ4_MAX_INPUT_SIZE.js +9 -9
  143. package/src/core/binary/lz4/lz4_compress_block.js +385 -385
  144. package/src/core/binary/lz4/lz4_compress_bound.js +25 -25
  145. package/src/core/binary/lz4/lz4_decompress_block.js +139 -139
  146. package/src/core/binary/lz4/lz4_decompress_bound.js +30 -30
  147. package/src/core/binary/meshopt/MESHOPT_GROUP_SIZE.js +18 -18
  148. package/src/core/binary/meshopt/MeshoptCompressionFilter.js +30 -30
  149. package/src/core/binary/meshopt/MeshoptCompressionMode.js +21 -21
  150. package/src/core/binary/meshopt/__meshopt_test_streams.js +237 -237
  151. package/src/core/binary/meshopt/meshopt_decode.js +73 -73
  152. package/src/core/binary/meshopt/meshopt_decode_byte_group.js +67 -67
  153. package/src/core/binary/meshopt/meshopt_decode_data_block.js +59 -59
  154. package/src/core/binary/meshopt/meshopt_decode_filter_color.js +69 -69
  155. package/src/core/binary/meshopt/meshopt_decode_filter_exponential.js +43 -43
  156. package/src/core/binary/meshopt/meshopt_decode_filter_octahedral.js +60 -60
  157. package/src/core/binary/meshopt/meshopt_decode_filter_quaternion.js +71 -71
  158. package/src/core/binary/meshopt/meshopt_decode_index_buffer.js +294 -294
  159. package/src/core/binary/meshopt/meshopt_decode_index_sequence.js +115 -115
  160. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +381 -381
  161. package/src/core/binary/meshopt/meshopt_read_uint_var.js +59 -59
  162. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -13
  163. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -14
  164. package/src/core/binary/type/DataType2TypedArrayConstructorMapping.js +35 -35
  165. package/src/core/bvh2/bvh3/ebvh_geometry_query_any_triangle_ray.js +149 -149
  166. package/src/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +96 -96
  167. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -101
  168. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +77 -77
  169. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +90 -90
  170. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray_segment.js +94 -94
  171. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +86 -86
  172. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +101 -101
  173. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +92 -92
  174. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray.js +96 -96
  175. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray_segment.js +100 -100
  176. package/src/core/bvh2/visual/BVHGeometry.js +131 -131
  177. package/src/core/bvh8/BVH8.js +436 -436
  178. package/src/core/bvh8/aabb3_round_to_float32.js +22 -22
  179. package/src/core/bvh8/build/BVH8Converter.js +588 -588
  180. package/src/core/bvh8/build/TriangleCluster.js +122 -122
  181. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +28 -28
  182. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +17 -17
  183. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -303
  184. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -256
  185. package/src/core/bvh8/build/byte.js +9 -9
  186. package/src/core/bvh8/build/encode_bounds_e.js +11 -11
  187. package/src/core/bvh8/bvh8_convert_to_dot.js +132 -132
  188. package/src/core/bvh8/bvh8_count_primitives.js +98 -98
  189. package/src/core/bvh8/bvh8_geometry_validate.js +138 -138
  190. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +166 -166
  191. package/src/core/bvh8/bvh8_get_node_bounds.js +34 -34
  192. package/src/core/bvh8/bvh8_get_node_child_bounds.js +52 -52
  193. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -18
  194. package/src/core/bvh8/bvh8_node_count_triangles.js +27 -27
  195. package/src/core/bvh8/bvh8_quality.js +72 -72
  196. package/src/core/bvh8/bvh8_validate_structure.js +87 -87
  197. package/src/core/clipboard/obtainClipBoard.js +29 -29
  198. package/src/core/clipboard/safeClipboardReadText.js +55 -55
  199. package/src/core/clipboard/safeClipboardWriteText.js +23 -23
  200. package/src/core/collection/array/typed/typed_array_value_denormalize.js +52 -52
  201. package/src/core/collection/array/typed/typed_array_value_normalize.js +51 -51
  202. package/src/core/collection/union-find/union_find.js +79 -79
  203. package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -20
  204. package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -17
  205. package/src/core/color/colormap/MAGMA_LUT.js +26 -26
  206. package/src/core/color/illuminant/D65_TRISTIMULUS_XYZ.js +19 -19
  207. package/src/core/color/lab/lab_apply_hunt_adjustment.js +27 -27
  208. package/src/core/color/lab/lab_distance_hyab.js +23 -23
  209. package/src/core/color/lab/xyz_to_lab.js +62 -62
  210. package/src/core/color/operations/color_darken.js +24 -24
  211. package/src/core/color/operations/color_desaturate.js +24 -24
  212. package/src/core/color/operations/color_lighten.js +24 -24
  213. package/src/core/color/operations/color_saturate.js +24 -24
  214. package/src/core/color/operations/color_scale_okhsv_channel.js +45 -45
  215. package/src/core/color/tonemap/tonemap_aces.js +41 -41
  216. package/src/core/color/ycxcz/xyz_to_ycxcz.js +28 -28
  217. package/src/core/color/ycxcz/ycxcz_to_xyz.js +19 -19
  218. package/src/core/dom/isImageBitmap.js +12 -12
  219. package/src/core/function/frameThrottle.js +23 -23
  220. package/src/core/geom/2d/aabb/aabb2_array_combine.js +7 -7
  221. package/src/core/geom/2d/aabb/aabb2_compute_area.js +7 -7
  222. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +7 -7
  223. package/src/core/geom/2d/aabb/aabb2_compute_overlap.js +7 -7
  224. package/src/core/geom/2d/aabb/aabb2_from_v2_array.js +7 -7
  225. package/src/core/geom/2d/aabb/aabb2_intersects_point.js +7 -7
  226. package/src/core/geom/2d/aabb/aabb2_overlap_exists.js +7 -7
  227. package/src/core/geom/2d/circle/circle_compute_circle_intersection.js +7 -7
  228. package/src/core/geom/2d/circle/circle_compute_circle_penetration.js +7 -7
  229. package/src/core/geom/2d/circle/circle_intersects_point.js +7 -7
  230. package/src/core/geom/2d/compute_polygon_area_2d.js +7 -7
  231. package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +7 -7
  232. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +7 -7
  233. package/src/core/geom/2d/convex-hull/orientation3_array.js +7 -7
  234. package/src/core/geom/2d/intersect_ray_2d.js +7 -7
  235. package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +7 -7
  236. package/src/core/geom/2d/line/line2_segment_intersection_fraction_2d.js +44 -44
  237. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +7 -7
  238. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +7 -7
  239. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +7 -7
  240. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +7 -7
  241. package/src/core/geom/2d/line/line_segment_intersection_fraction_2d.js +7 -7
  242. package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +7 -7
  243. package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -25
  244. package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -46
  245. package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -52
  246. package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -69
  247. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -433
  248. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.js +51 -51
  249. package/src/core/geom/2d/polygon/polygon2_clip_halfplane.js +50 -50
  250. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -84
  251. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -52
  252. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -86
  253. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -1280
  254. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -77
  255. package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -39
  256. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -101
  257. package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -7
  258. package/src/core/geom/2d/rectangle_to_aabb.js +7 -7
  259. package/src/core/geom/2d/spline_bezier2_2d.js +7 -7
  260. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +99 -99
  261. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -35
  262. package/src/core/geom/2d/triangle2d_compute_area.js +7 -7
  263. package/src/core/geom/2d/triangle2d_contains_point.js +7 -7
  264. package/src/core/geom/2d/triangle2d_get_barycentric.js +7 -7
  265. package/src/core/geom/2d/v2_morton_encode.js +23 -23
  266. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_degree.js +7 -7
  267. package/src/core/geom/3d/aabb/aabb3_box_surface_area_2.js +7 -7
  268. package/src/core/geom/3d/aabb/aabb3_build_frustum.js +5 -5
  269. package/src/core/geom/3d/aabb/aabb3_closest_point_on_surface.js +57 -57
  270. package/src/core/geom/3d/aabb/aabb3_combined_surface_area.js +7 -7
  271. package/src/core/geom/3d/aabb/aabb3_compute_half_surface_area.js +7 -7
  272. package/src/core/geom/3d/aabb/aabb3_compute_projected_area.js +7 -7
  273. package/src/core/geom/3d/aabb/aabb3_compute_surface_area.js +7 -7
  274. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +7 -7
  275. package/src/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +7 -7
  276. package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +7 -7
  277. package/src/core/geom/3d/aabb/aabb3_from_triangle_group.js +46 -46
  278. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_degree.js +7 -7
  279. package/src/core/geom/3d/aabb/aabb3_intersects_line_segment.js +7 -7
  280. package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +7 -7
  281. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +7 -7
  282. package/src/core/geom/3d/aabb/aabb3_ray_segment_entry_distance.js +95 -95
  283. package/src/core/geom/3d/aabb/aabb3_raycast.js +7 -7
  284. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -93
  285. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.js +82 -82
  286. package/src/core/geom/3d/aabb/compute_aabb_from_points.js +7 -7
  287. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +7 -7
  288. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -486
  289. package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -174
  290. package/src/core/geom/3d/atlas/Chart.js +77 -77
  291. package/src/core/geom/3d/atlas/REVIEW_02.md +392 -392
  292. package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -315
  293. package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -16
  294. package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -188
  295. package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -107
  296. package/src/core/geom/3d/atlas/atlas_generate.js +50 -50
  297. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -266
  298. package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -36
  299. package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -62
  300. package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -33
  301. package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -50
  302. package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -39
  303. package/src/core/geom/3d/atlas/io/bt_loop_uv.js +35 -35
  304. package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -46
  305. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +269 -269
  306. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +209 -209
  307. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -38
  308. package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -86
  309. package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -183
  310. package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -66
  311. package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -40
  312. package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -136
  313. package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -30
  314. package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -77
  315. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +116 -116
  316. package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +271 -271
  317. package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +191 -191
  318. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -35
  319. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_closed.js +67 -67
  320. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_iterative.js +137 -137
  321. package/src/core/geom/3d/compute_circle_bounding_box.js +7 -7
  322. package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -7
  323. package/src/core/geom/3d/cone/computeConePlaneSide.js +7 -7
  324. package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +7 -7
  325. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts +38 -0
  326. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts.map +1 -0
  327. package/src/core/geom/3d/cylinder/cylinder3_raycast.js +105 -0
  328. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -18
  329. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -24
  330. package/src/core/geom/3d/frustum/clipping_volume_matrix4_project.js +7 -7
  331. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +7 -7
  332. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +117 -117
  333. package/src/core/geom/3d/frustum/frustum_matrix4_project.js +7 -7
  334. package/src/core/geom/3d/frustum/hexahedron_from_aabb.js +7 -7
  335. package/src/core/geom/3d/frustum/read_frustum_corner.js +17 -17
  336. package/src/core/geom/3d/frustum/read_three_planes_to_array.js +7 -7
  337. package/src/core/geom/3d/frustum/slice_frustum_linear_to_points.js +7 -7
  338. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +146 -146
  339. package/src/core/geom/3d/gjk/gjk.js +430 -430
  340. package/src/core/geom/3d/gjk/gjk_epa_penetration.js +520 -520
  341. package/src/core/geom/3d/gjk/minkowski_support.js +71 -71
  342. package/src/core/geom/3d/gjk/mpr.js +368 -368
  343. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +7 -7
  344. package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.js +7 -7
  345. package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -64
  346. package/src/core/geom/3d/line/line3_compute_segment_closest_point_to_aabb3_t.js +153 -153
  347. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_aabb3_t.js +7 -7
  348. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_point_t.js +7 -7
  349. package/src/core/geom/3d/line/line3_compute_segment_segment_closest_points.js +88 -88
  350. package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -71
  351. package/src/core/geom/3d/line/segment3_point_distance_to_segments.js +25 -25
  352. package/src/core/geom/3d/mat4/allocate_m4.js +7 -7
  353. package/src/core/geom/3d/mat4/apply_mat4_transform_to_direction_v3_array.js +7 -7
  354. package/src/core/geom/3d/mat4/apply_mat4_transform_to_v3_array.js +7 -7
  355. package/src/core/geom/3d/mat4/compose_matrix4_array.js +7 -7
  356. package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +7 -7
  357. package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +7 -7
  358. package/src/core/geom/3d/mat4/m4_compose.js +22 -22
  359. package/src/core/geom/3d/mat4/m4_compute_normal_matrix3.js +7 -7
  360. package/src/core/geom/3d/mat4/m4_decompose.js +64 -64
  361. package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -157
  362. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +32 -32
  363. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -67
  364. package/src/core/geom/3d/mat4/m4_linear_matrix3.js +29 -29
  365. package/src/core/geom/3d/mat4/m4_look_at.js +96 -96
  366. package/src/core/geom/3d/mat4/m4_make_rotation_x.js +47 -47
  367. package/src/core/geom/3d/mat4/m4_make_rotation_y.js +47 -47
  368. package/src/core/geom/3d/mat4/m4_make_rotation_z.js +47 -47
  369. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +39 -39
  370. package/src/core/geom/3d/mat4/m4_perspective.js +66 -66
  371. package/src/core/geom/3d/mat4/m4_transpose.js +48 -48
  372. package/src/core/geom/3d/morton/mortonEncode_LUT.js +7 -7
  373. package/src/core/geom/3d/morton/mortonEncode_magicbits.js +7 -7
  374. package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -5
  375. package/src/core/geom/3d/normal/hemioct/encode_unit_to_hemioct.js +28 -28
  376. package/src/core/geom/3d/normal/lambert_azimuth/decode_azimuth_to_unit.js +30 -30
  377. package/src/core/geom/3d/normal/lambert_azimuth/encode_unit_to_azimuth.js +19 -19
  378. package/src/core/geom/3d/normal/spherical/decode_spheremap_to_unit.js +38 -38
  379. package/src/core/geom/3d/normal/spherical/encode_unit_to_spheremap.js +30 -30
  380. package/src/core/geom/3d/plane/is_point_within_planes.js +7 -7
  381. package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -47
  382. package/src/core/geom/3d/plane/plane3_compute_convex_3_plane_intersection.js +7 -7
  383. package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +7 -7
  384. package/src/core/geom/3d/plane/plane3_intersect_plane.js +7 -7
  385. package/src/core/geom/3d/plane/plane3_three_compute_convex_3_plane_intersection.js +7 -7
  386. package/src/core/geom/3d/point/point3_raycast.d.ts +33 -0
  387. package/src/core/geom/3d/point/point3_raycast.d.ts.map +1 -0
  388. package/src/core/geom/3d/point/point3_raycast.js +47 -0
  389. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -60
  390. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -94
  391. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts +40 -0
  392. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts.map +1 -0
  393. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.js +94 -0
  394. package/src/core/geom/3d/quadric/QUADRIC3_SIZE.js +14 -14
  395. package/src/core/geom/3d/quadric/Quadric3.js +282 -282
  396. package/src/core/geom/3d/quadric/quadric3_add.js +33 -33
  397. package/src/core/geom/3d/quadric/quadric3_clear.js +25 -25
  398. package/src/core/geom/3d/quadric/quadric3_copy.js +27 -27
  399. package/src/core/geom/3d/quadric/quadric3_distance.js +36 -36
  400. package/src/core/geom/3d/quadric/quadric3_evaluate.js +25 -25
  401. package/src/core/geom/3d/quadric/quadric3_optimize.js +45 -45
  402. package/src/core/geom/3d/quadric/quadric3_scale.js +32 -32
  403. package/src/core/geom/3d/quadric/quadric3_set_from_plane_through_point.js +30 -30
  404. package/src/core/geom/3d/quadric/quadric3_set_from_vector4.js +35 -35
  405. package/src/core/geom/3d/quadric/quadric3_sub.js +36 -36
  406. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3.js +28 -28
  407. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3_inverse.js +56 -56
  408. package/src/core/geom/3d/quadric/quadric3_to_vector3.js +19 -19
  409. package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +7 -7
  410. package/src/core/geom/3d/quaternion/quat3_integrate.js +62 -62
  411. package/src/core/geom/3d/quaternion/quat3_multiply.js +31 -31
  412. package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -72
  413. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -69
  414. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +7 -7
  415. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +7 -7
  416. package/src/core/geom/3d/ray/ray3_array_compose.js +7 -7
  417. package/src/core/geom/3d/ray/ray3_compute_nearest_point_to_point.js +7 -7
  418. package/src/core/geom/3d/ray/ray3_distance_to_point.js +7 -7
  419. package/src/core/geom/3d/ray/ray3_shift_origin_along_direction.js +7 -7
  420. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +17 -0
  421. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  422. package/src/core/geom/3d/shape/ConvexHullShape3D.js +43 -0
  423. package/src/core/geom/3d/shape/CylinderShape3D.d.ts +1 -0
  424. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  425. package/src/core/geom/3d/shape/CylinderShape3D.js +21 -0
  426. package/src/core/geom/3d/shape/PointShape3D.d.ts +7 -0
  427. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
  428. package/src/core/geom/3d/shape/PointShape3D.js +88 -63
  429. package/src/core/geom/3d/shape/PosedShape3D.d.ts +6 -0
  430. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  431. package/src/core/geom/3d/shape/PosedShape3D.js +27 -0
  432. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
  433. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  434. package/src/core/geom/3d/shape/TransformedShape3D.js +13 -0
  435. package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -0
  436. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
  437. package/src/core/geom/3d/shape/Triangle3D.js +26 -0
  438. package/src/core/geom/3d/shape/UnionShape3D.d.ts +6 -0
  439. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  440. package/src/core/geom/3d/shape/UnionShape3D.js +7 -0
  441. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -45
  442. package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -44
  443. package/src/core/geom/3d/shape/shape3_mesh_from_geometry.js +64 -64
  444. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +7 -7
  445. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -51
  446. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +7 -7
  447. package/src/core/geom/3d/sphere/compute_bounding_sphere_of_2_spheres.js +7 -7
  448. package/src/core/geom/3d/sphere/harmonics/sh3_convolve_with_zh.js +53 -53
  449. package/src/core/geom/3d/sphere/harmonics/sh3_ggx_zh.js +30 -30
  450. package/src/core/geom/3d/sphere/harmonics/sh3_rotate_bl.js +7 -7
  451. package/src/core/geom/3d/sphere/harmonics/sh_compute_K.js +7 -7
  452. package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +7 -7
  453. package/src/core/geom/3d/sphere/sphere_array_intersects_ray.js +7 -7
  454. package/src/core/geom/3d/sphere/sphere_intersects_point.js +7 -7
  455. package/src/core/geom/3d/sphere/sphere_matrix4_transform.js +5 -5
  456. package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +7 -7
  457. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +7 -7
  458. package/src/core/geom/3d/sphere/spherical_from_cartesian.js +7 -7
  459. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +174 -174
  460. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +7 -7
  461. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_volume.js +7 -7
  462. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +7 -7
  463. package/src/core/geom/3d/tetrahedra/graphics/build_tetrahedral_mesh_geometry.js +39 -39
  464. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -48
  465. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +173 -173
  466. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_compute_tet_quality.js +22 -22
  467. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -146
  468. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -232
  469. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -255
  470. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -387
  471. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -140
  472. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +7 -7
  473. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -97
  474. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -66
  475. package/src/core/geom/3d/tetrahedra/triangle/triangle_decode_depth.js +59 -59
  476. package/src/core/geom/3d/tetrahedra/triangle/triangle_rasterized_depth_sample_index.js +54 -54
  477. package/src/core/geom/3d/tetrahedra/validate_neighbour.js +70 -70
  478. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +314 -314
  479. package/src/core/geom/3d/topology/struct/binary/BinaryDataLayer.js +364 -364
  480. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +567 -567
  481. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1085 -1085
  482. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -73
  483. package/src/core/geom/3d/topology/struct/binary/io/bt_loop_kill.js +35 -35
  484. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_append.js +119 -119
  485. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +84 -84
  486. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +172 -172
  487. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +56 -56
  488. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadratics.js +7 -7
  489. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +227 -227
  490. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +161 -161
  491. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +490 -490
  492. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +120 -120
  493. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +120 -120
  494. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_collapse.js +52 -52
  495. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +115 -115
  496. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_flip.js +142 -142
  497. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -21
  498. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +92 -92
  499. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_split.js +179 -179
  500. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_swap_vertex_slots.js +28 -28
  501. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_kill_only_edge.js +8 -8
  502. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_fuse_duplicate_edges.js +83 -83
  503. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +89 -89
  504. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_kill.js +25 -25
  505. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +127 -127
  506. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -268
  507. package/src/core/geom/3d/topology/struct/binary/io/face/bt_kill_only_face.js +8 -8
  508. package/src/core/geom/3d/topology/struct/binary/io/face/bt_mesh_kill_degenerate_faces.js +72 -72
  509. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_kill_only_vert.js +7 -7
  510. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_merge_verts_by_distance.js +7 -7
  511. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_relative_merge_distance.js +48 -48
  512. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_split_pinched_vertices.js +256 -256
  513. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_vertex_merge_distance.js +77 -77
  514. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_fuse_duplicate_edges.js +7 -7
  515. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_kill.js +7 -7
  516. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +148 -148
  517. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_kill_only.js +7 -7
  518. package/src/core/geom/3d/topology/struct/binary/query/bt_collect_boundary_segments.js +29 -29
  519. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_breaks_link_condition.js +107 -107
  520. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_is_legal.js +41 -41
  521. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_would_fold.js +120 -120
  522. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -42
  523. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_is_boundary.js +20 -20
  524. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_read_diamond.js +96 -96
  525. package/src/core/geom/3d/topology/struct/binary/query/bt_face_compute_newell_normal.js +72 -72
  526. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_attached_faces.js +7 -7
  527. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces.js +39 -39
  528. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces_weighted.js +93 -93
  529. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_neighbour_faces.js +7 -7
  530. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_shared_loop.js +48 -48
  531. package/src/core/geom/3d/topology/struct/binary/query/bt_face_island_flood_fill.js +45 -45
  532. package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -66
  533. package/src/core/geom/3d/topology/struct/binary/query/bt_faces_shared_loop.js +7 -7
  534. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -44
  535. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_euclidean_distance_field.js +32 -32
  536. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_compute_face_islands.js +53 -53
  537. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -703
  538. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +181 -181
  539. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +133 -133
  540. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -82
  541. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -599
  542. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -108
  543. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +7 -7
  544. package/src/core/geom/3d/triangle/computeTriangleClosestPointToPointBarycentric.js +7 -7
  545. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +7 -7
  546. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +7 -7
  547. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +7 -7
  548. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricGeometry.js +7 -7
  549. package/src/core/geom/3d/triangle/compute_triangle_area_3d.js +7 -7
  550. package/src/core/geom/3d/triangle/compute_triangle_normal.js +7 -7
  551. package/src/core/geom/3d/triangle/rayTriangleIntersection.js +7 -7
  552. package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -65
  553. package/src/core/geom/3d/triangle/tri3_closest_point_barycentric.js +171 -171
  554. package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -79
  555. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +160 -160
  556. package/src/core/geom/3d/triangle/tri3_ray_intersection_barycentric.js +96 -96
  557. package/src/core/geom/3d/triangle/tri3_raycast.d.ts +42 -0
  558. package/src/core/geom/3d/triangle/tri3_raycast.d.ts.map +1 -0
  559. package/src/core/geom/3d/triangle/tri3_raycast.js +94 -0
  560. package/src/core/geom/3d/triangle/triangle3_incenter.js +7 -7
  561. package/src/core/geom/3d/triangle/triangle_compute_plane_side.js +7 -7
  562. package/src/core/geom/3d/triangle/triangle_compute_signed_volume.js +7 -7
  563. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +7 -7
  564. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +7 -7
  565. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +7 -7
  566. package/src/core/geom/3d/util/make_justified_point_grid.js +7 -7
  567. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +381 -381
  568. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +684 -684
  569. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -554
  570. package/src/core/geom/mat3/m3_cm_from_translation.js +7 -7
  571. package/src/core/geom/mat3/m3_cm_invert.js +7 -7
  572. package/src/core/geom/mat3/m3_make_rotation.js +5 -5
  573. package/src/core/geom/mat3/m3_make_rotation_TBN.js +31 -31
  574. package/src/core/geom/mat3/m3_multiply_vec3.js +7 -7
  575. package/src/core/geom/packing/computeBoundingSphereOfSpheres.js +7 -7
  576. package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +7 -7
  577. package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +7 -7
  578. package/src/core/geom/packing/max-rect/cutArea.js +7 -7
  579. package/src/core/geom/packing/max-rect/findBestContainer.js +7 -7
  580. package/src/core/geom/packing/max-rect/packMaxRectangles.js +7 -7
  581. package/src/core/geom/packing/max-rect/packOneBox.js +7 -7
  582. package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +7 -7
  583. package/src/core/geom/packing/max-rect/removeRedundantBoxesArray.js +7 -7
  584. package/src/core/geom/random/randomPointInBox.js +7 -7
  585. package/src/core/geom/random/randomPointInCircle.js +7 -7
  586. package/src/core/geom/random/randomPointInPoint.js +7 -7
  587. package/src/core/geom/random/randomPointInSphere.js +7 -7
  588. package/src/core/geom/random/randomPointOnBox.js +7 -7
  589. package/src/core/geom/random/randomPointOnSphere.js +7 -7
  590. package/src/core/geom/random/random_orthonormal_basis.js +31 -31
  591. package/src/core/geom/vec/vector_axpy.js +15 -15
  592. package/src/core/geom/vec/vector_axpy_offset.js +20 -20
  593. package/src/core/geom/vec/vector_copy.js +7 -7
  594. package/src/core/geom/vec/vector_dot_offset.js +25 -25
  595. package/src/core/geom/vec/vector_scale_array.js +7 -7
  596. package/src/core/geom/vec2/v2_rotate.js +21 -21
  597. package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -21
  598. package/src/core/geom/vec3/v3_angle_atan2_between.js +7 -7
  599. package/src/core/geom/vec3/v3_angle_between.js +7 -7
  600. package/src/core/geom/vec3/v3_angle_cos_between.js +7 -7
  601. package/src/core/geom/vec3/v3_array_add_in_place.js +7 -7
  602. package/src/core/geom/vec3/v3_array_centroid.js +7 -7
  603. package/src/core/geom/vec3/v3_array_copy.js +7 -7
  604. package/src/core/geom/vec3/v3_array_displace_in_direction.js +7 -7
  605. package/src/core/geom/vec3/v3_array_equals.js +7 -7
  606. package/src/core/geom/vec3/v3_array_immediate_add.js +7 -7
  607. package/src/core/geom/vec3/v3_array_matrix4_rotate.js +7 -7
  608. package/src/core/geom/vec3/v3_array_normalize.js +7 -7
  609. package/src/core/geom/vec3/v3_array_scale.js +7 -7
  610. package/src/core/geom/vec3/v3_compute_interior_angle.js +7 -7
  611. package/src/core/geom/vec3/v3_cotangent.js +33 -33
  612. package/src/core/geom/vec3/v3_dot_array_array.js +7 -7
  613. package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -30
  614. package/src/core/geom/vec3/v3_matrix3_rotate.js +49 -49
  615. package/src/core/geom/vec3/v3_matrix4_rotate.js +7 -7
  616. package/src/core/geom/vec3/v3_multiply.js +23 -23
  617. package/src/core/geom/vec3/v3_multiply_scalar.js +7 -7
  618. package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.js +49 -49
  619. package/src/core/geom/vec3/v3_quat3_apply.js +7 -7
  620. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +7 -7
  621. package/src/core/geom/vec3/v3_quaternion_apply.js +39 -39
  622. package/src/core/geom/vec3/v3_quaternion_apply_inverse.js +41 -41
  623. package/src/core/geom/vec3/v3_reflect.js +24 -24
  624. package/src/core/geom/vec3/v3_scale_array.js +18 -18
  625. package/src/core/geom/vec3/v3_triple_cross.js +45 -45
  626. package/src/core/geom/vec3/v3_triple_cross_product.js +7 -7
  627. package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -21
  628. package/src/core/geom/vec4/v4_multiply_mat4.js +7 -7
  629. package/src/core/graph/csr/csr_graph_build_distance_field.js +112 -112
  630. package/src/core/graph/csr/csr_graph_find_edge.js +25 -25
  631. package/src/core/graph/csr/csr_graph_find_shortest_path.js +105 -105
  632. package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -94
  633. package/src/core/graph/graph_k_means_cluster.js +250 -250
  634. package/src/core/graph/layout/CircleLayout.js +1 -1
  635. package/src/core/graph/layout/box/BoxLayouter.js +1 -1
  636. package/src/core/graph/layout/graph_peel_topological_layer.js +45 -45
  637. package/src/core/graph/metis/BinaryTopologyFaceGraph.js +49 -49
  638. package/src/core/graph/metis/bt_mesh_build_face_graph.js +111 -111
  639. package/src/core/graph/metis/cluster_mesh_metis.js +137 -137
  640. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -100
  641. package/src/core/graph/metis/native/bisection/compute_2way_params.js +86 -86
  642. package/src/core/graph/metis/native/bisection/fm_2way.js +297 -297
  643. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -137
  644. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -119
  645. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -94
  646. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -158
  647. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -175
  648. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -122
  649. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -170
  650. package/src/core/graph/metis/native/metis_partition_kway.js +126 -126
  651. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -53
  652. package/src/core/graph/metis/native/refine/fm_kway.js +487 -487
  653. package/src/core/graph/metis/native/refine/project_kway.js +43 -43
  654. package/src/core/graph/metis/native/refine/refine_kway.js +43 -43
  655. package/src/core/lang/reactive/pegjs/parser.js +3458 -3458
  656. package/src/core/math/complex/complex_horner_eval.js +31 -31
  657. package/src/core/math/computeWholeDivisorLow.js +33 -33
  658. package/src/core/math/f32_next_down.js +24 -24
  659. package/src/core/math/f32_next_up.js +27 -27
  660. package/src/core/math/hash/hash_mix2.js +22 -22
  661. package/src/core/math/hash/hash_mix3.js +19 -19
  662. package/src/core/math/linalg/cg/cg_solve.js +106 -106
  663. package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -59
  664. package/src/core/math/linalg/cubic_residual_times_derivative_accumulate.js +43 -43
  665. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +122 -122
  666. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +190 -190
  667. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -117
  668. package/src/core/math/linalg/givens/givens_apply_rows.js +28 -28
  669. package/src/core/math/linalg/givens/givens_apply_rows_offset.js +30 -30
  670. package/src/core/math/linalg/givens/givens_rotation_coefficients.js +39 -39
  671. package/src/core/math/linalg/lu_factor_linear_system.js +108 -108
  672. package/src/core/math/linalg/lu_solve_linear_system.js +53 -53
  673. package/src/core/math/linalg/polynomial_add_into.js +29 -29
  674. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +159 -159
  675. package/src/core/math/linalg/polynomial_cubic_derivative_eval.js +16 -16
  676. package/src/core/math/linalg/polynomial_cubic_horner_eval.js +19 -19
  677. package/src/core/math/linalg/polynomial_cubic_second_derivative_eval.js +14 -14
  678. package/src/core/math/linalg/polynomial_multiply.js +41 -41
  679. package/src/core/math/linalg/polynomial_real_roots_in_interval.js +211 -211
  680. package/src/core/math/linalg/polynomial_root_bound_cauchy.js +30 -30
  681. package/src/core/math/linalg/polynomial_scale_into.js +17 -17
  682. package/src/core/math/linalg/polynomial_sub_into.js +29 -29
  683. package/src/core/math/linalg/solve_linear_system_GEPP_2x2.js +96 -96
  684. package/src/core/math/linalg/sor_optimal_omega.js +42 -42
  685. package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -88
  686. package/src/core/math/linalg/sparse/spm_matvec.js +22 -22
  687. package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -29
  688. package/src/core/math/lookup/LUT_HEATMAP.js +30 -30
  689. package/src/core/math/lookup/ParameterLookupTable.js +495 -495
  690. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -6
  691. package/src/core/math/noise/curl_noise_3d.js +18 -18
  692. package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -28
  693. package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -48
  694. package/src/core/math/physics/kinematics/computeInterceptPoint.js +79 -79
  695. package/src/core/math/random/randomSeed.js +16 -16
  696. package/src/core/math/random/random_pick_weighted_index.js +26 -26
  697. package/src/core/math/round_half_away_from_zero.js +13 -13
  698. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -107
  699. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +125 -125
  700. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +50 -50
  701. package/src/core/math/spline/spline3_hermite_reverse.js +49 -49
  702. package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -37
  703. package/src/core/math/statistics/hammersley_sequence.js +53 -53
  704. package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
  705. package/src/core/path/convertPathToURL.js +107 -107
  706. package/src/core/process/delay.js +16 -16
  707. package/src/core/science/units/MEASUREMENT_UNITS_SCIENTIFIC.js +87 -87
  708. package/src/core/science/units/MEASUREMENT_UNITS_SI.js +17 -17
  709. package/src/core/science/units/NamedUnit.js +48 -48
  710. package/src/core/science/units/UNIT_DIMENSION_MAPPING.js +29 -29
  711. package/src/core/science/units/UnitDimension.js +28 -28
  712. package/src/core/science/units/format_quantity.js +74 -74
  713. package/src/core/science/units/magnitude_prefix.js +127 -127
  714. package/src/core/science/units/si/AMPERE.js +13 -13
  715. package/src/core/science/units/si/CANDELA.js +13 -13
  716. package/src/core/science/units/si/DIMENSIONLESS.js +14 -14
  717. package/src/core/science/units/si/KELVIN.js +13 -13
  718. package/src/core/science/units/si/KILOGRAM.js +13 -13
  719. package/src/core/science/units/si/METER.js +13 -13
  720. package/src/core/science/units/si/MOLE.js +13 -13
  721. package/src/core/science/units/si/SECOND.js +13 -13
  722. package/src/core/science/units/si/derived/BECQUEREL.js +16 -16
  723. package/src/core/science/units/si/derived/COULOMB.js +13 -13
  724. package/src/core/science/units/si/derived/FARAD.js +13 -13
  725. package/src/core/science/units/si/derived/GRAY.js +16 -16
  726. package/src/core/science/units/si/derived/HENRY.js +13 -13
  727. package/src/core/science/units/si/derived/HERTZ.js +16 -16
  728. package/src/core/science/units/si/derived/JOULE.js +13 -13
  729. package/src/core/science/units/si/derived/KATAL.js +13 -13
  730. package/src/core/science/units/si/derived/LUMEN.js +14 -14
  731. package/src/core/science/units/si/derived/LUX.js +13 -13
  732. package/src/core/science/units/si/derived/NEWTON.js +13 -13
  733. package/src/core/science/units/si/derived/OHM.js +13 -13
  734. package/src/core/science/units/si/derived/PASCAL.js +13 -13
  735. package/src/core/science/units/si/derived/SIEMENS.js +13 -13
  736. package/src/core/science/units/si/derived/SIEVERT.js +16 -16
  737. package/src/core/science/units/si/derived/TESLA.js +13 -13
  738. package/src/core/science/units/si/derived/VOLT.js +13 -13
  739. package/src/core/science/units/si/derived/WATT.js +13 -13
  740. package/src/core/science/units/si/derived/WEBER.js +13 -13
  741. package/src/core/science/units/unit_matrix_to_string.js +403 -403
  742. package/src/engine/Engine.js +726 -726
  743. package/src/engine/EngineHarness.js +590 -590
  744. package/src/engine/REVIEW_2026_07_03.md +211 -211
  745. package/src/engine/animation/AnimatedActions.js +81 -81
  746. package/src/engine/animation/AnimationUtils.js +252 -252
  747. package/src/engine/animation/async/TimeSeries.js +300 -300
  748. package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -60
  749. package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -22
  750. package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -38
  751. package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -22
  752. package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -22
  753. package/src/engine/asset/GameAssetType.d.ts +0 -1
  754. package/src/engine/asset/GameAssetType.js +0 -1
  755. package/src/engine/asset/load_model_scene_bundle.js +27 -27
  756. package/src/engine/asset/loaders/font/FontAsset.js +21 -21
  757. package/src/engine/asset/loaders/font/FontAssetLoader.js +20 -20
  758. package/src/engine/asset/loaders/gltf_test_fixtures.js +358 -358
  759. package/src/engine/asset/loaders/image/ImageBitmapAssetLoader.js +52 -52
  760. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +94 -94
  761. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.js +59 -59
  762. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +55 -55
  763. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.js +74 -74
  764. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +34 -34
  765. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +46 -46
  766. package/src/engine/control/first-person/DESIGN.md +640 -640
  767. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -563
  768. package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -134
  769. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2045 -2045
  770. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -30
  771. package/src/engine/control/first-person/math/Spring.js +71 -71
  772. package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -23
  773. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -41
  774. package/src/engine/control/first-person/math/computeMassRatios.js +44 -44
  775. package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -34
  776. package/src/engine/control/first-person/math/dampedSpringStep.js +72 -72
  777. package/src/engine/control/first-person/math/jumpDynamics.js +108 -108
  778. package/src/engine/control/first-person/math/stepTowards.js +20 -20
  779. package/src/engine/control/first-person/pose/FirstPersonPose.js +137 -137
  780. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -27
  781. package/src/engine/control/first-person/test/buildTestPlayer.js +36 -36
  782. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +531 -531
  783. package/src/engine/ecs/EntityManager.d.ts +7 -3
  784. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  785. package/src/engine/ecs/EntityManager.js +10 -5
  786. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  787. package/src/engine/ecs/async/SystemWorkerHost.js +329 -329
  788. package/src/engine/ecs/async/SystemWorkerLoopback.js +143 -143
  789. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +246 -246
  790. package/src/engine/ecs/async/WorkerSystem.js +702 -702
  791. package/src/engine/ecs/async/WorkerSystemProtocol.js +150 -150
  792. package/src/engine/ecs/fow/FogOfWar.js +707 -707
  793. package/src/engine/ecs/fow/FogOfWarEdgeMode.js +40 -40
  794. package/src/engine/ecs/fow/fog_of_war_mask_world_bounds.js +24 -24
  795. package/src/engine/ecs/fow/fog_of_war_uv_transform.js +30 -30
  796. package/src/engine/ecs/gui/hud/testHudEdgeStick.js +132 -134
  797. package/src/engine/ecs/hierarchy/EntityChildIndex.js +140 -140
  798. package/src/engine/ecs/ik/IKProblem.js +42 -42
  799. package/src/engine/ecs/ik/InverseKinematicsSystem.js +193 -193
  800. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +134 -134
  801. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +97 -97
  802. package/src/engine/ecs/ik/ik_bone_chain.js +85 -85
  803. package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -119
  804. package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
  805. package/src/engine/ecs/parent/EntityNode.js +2 -2
  806. package/src/engine/ecs/parent/ParentEntitySystem.js +255 -255
  807. package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
  808. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  809. package/src/engine/ecs/speaker/VoiceSystem.js +13 -7
  810. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +269 -269
  811. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -315
  812. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -331
  813. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -199
  814. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -57
  815. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -56
  816. package/src/engine/ecs/storage/binary/object-v2/README.md +110 -110
  817. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -48
  818. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -44
  819. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +265 -265
  820. package/src/engine/ecs/terrain/TerrainClouds.js +97 -97
  821. package/src/engine/ecs/terrain/ecs/StubTerrainBuildWorker.js +65 -65
  822. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +4 -0
  823. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  824. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  825. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +209 -209
  826. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +316 -316
  827. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +416 -416
  828. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +525 -525
  829. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +302 -302
  830. package/src/engine/ecs/terrain/tiles/TerrainTile.js +561 -561
  831. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +896 -896
  832. package/src/engine/ecs/terrain/tiles/tile_geometry_to_meshlets.js +36 -36
  833. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  834. package/src/engine/ecs/transform/Transform64.js +814 -814
  835. package/src/engine/ecs/transform/t64_copy_from_transform.js +35 -35
  836. package/src/engine/ecs/transform/t64_equals_transform.js +55 -55
  837. package/src/engine/ecs/transform/t64_look_rotation.js +36 -36
  838. package/src/engine/ecs/transform/t64_transform_direction.js +25 -25
  839. package/src/engine/ecs/transform/transform_copy_from_t64.js +28 -28
  840. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +345 -345
  841. package/src/engine/ecs/transform-attachment/transform_attachment_find_descendant_by_name.js +65 -65
  842. package/src/engine/ecs/transform-attachment/transform_attachment_parent_of.js +24 -24
  843. package/src/engine/ecs/util/hideEntityGracefully.js +208 -208
  844. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -446
  845. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -14
  846. package/src/engine/graphics/FrameThrottle.js +2 -2
  847. package/src/engine/graphics/ecs/animation/animator/graph/AnimationState.js +207 -207
  848. package/src/engine/graphics/ecs/animation/animator/graph/AnimationTransition.js +151 -151
  849. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -22
  850. package/src/engine/graphics/ecs/camera/Camera.js +165 -165
  851. package/src/engine/graphics/ecs/camera/camera_active_frustum.js +25 -25
  852. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  853. package/src/engine/graphics/ecs/camera/camera_traverse_active.js +18 -18
  854. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +170 -170
  855. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -68
  856. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +296 -296
  857. package/src/engine/graphics/ecs/decal/v2/Decal.js +220 -220
  858. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +56 -56
  859. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js +38 -38
  860. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -62
  861. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +77 -77
  862. package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -33
  863. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -88
  864. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  865. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +303 -303
  866. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.d.ts +1 -1
  867. package/src/engine/graphics/ecs/mesh-v2/aggregate/serialization/SGMeshSerializationAdapter.js +39 -39
  868. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +36 -36
  869. package/src/engine/graphics/ecs/path/tube/build/GeometryStream.js +94 -94
  870. package/src/engine/graphics/ecs/path/tube/build/build_stream_catmullrom.js +310 -310
  871. package/src/engine/graphics/ecs/path/tube/build/build_stream_linear.js +73 -73
  872. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +199 -199
  873. package/src/engine/graphics/ecs/path/tube/build/makeTubeStream.js +217 -217
  874. package/src/engine/graphics/ecs/path/tube/build/make_cap.js +340 -340
  875. package/src/engine/graphics/ecs/path/tube/build/make_ring_faces.js +40 -40
  876. package/src/engine/graphics/ecs/path/tube/build/make_ring_vertices.js +153 -153
  877. package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -64
  878. package/src/engine/graphics/ecs/trail3d/Trail3D.js +483 -483
  879. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +26 -26
  880. package/src/engine/graphics/ecs/trail3d/advance_trail.js +42 -42
  881. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +58 -58
  882. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +90 -90
  883. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +75 -75
  884. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +19 -19
  885. package/src/engine/graphics/ecs/water/Water.js +104 -104
  886. package/src/engine/graphics/geometry/AttributeData.js +84 -84
  887. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +49 -49
  888. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +288 -288
  889. package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -87
  890. package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -102
  891. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_buffered_geometry.js +52 -52
  892. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +20 -20
  893. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +19 -19
  894. package/src/engine/graphics/geometry/optimization/geometry_optimize_uv_tension.js +135 -135
  895. package/src/engine/graphics/impostors/voxel/README.md +149 -149
  896. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -141
  897. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -20
  898. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +2 -0
  899. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +1 -1
  900. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +2 -0
  901. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +1 -1
  902. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +2 -0
  903. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +1 -1
  904. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +1 -2
  905. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +1 -1
  906. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +2 -0
  907. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +1 -1
  908. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +2 -0
  909. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +1 -1
  910. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +2 -0
  911. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +1 -1
  912. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +2 -0
  913. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +1 -1
  914. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +2 -0
  915. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +1 -1
  916. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +2 -0
  917. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +1 -1
  918. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +2 -0
  919. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +1 -1
  920. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +2 -0
  921. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +1 -1
  922. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +2 -0
  923. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +1 -1
  924. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +2 -0
  925. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +1 -1
  926. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +2 -0
  927. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +1 -1
  928. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +2 -0
  929. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +1 -1
  930. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -45
  931. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +229 -229
  932. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -10
  933. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  934. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1149 -1149
  935. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +472 -472
  936. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
  937. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -2
  938. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.d.ts.map +1 -1
  939. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.js +3 -5
  940. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +135 -135
  941. package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -168
  942. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +18 -18
  943. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -2
  944. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +219 -219
  945. package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
  946. package/src/engine/graphics/render/frame_graph/FrameGraphScope.js +72 -72
  947. package/src/engine/graphics/render/frame_graph/FrameGraphState.js +39 -39
  948. package/src/engine/graphics/render/frame_graph/ResourceEntry.js +96 -96
  949. package/src/engine/graphics/render/gizmo/GizmoShapeBuffer.js +105 -105
  950. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +162 -162
  951. package/src/engine/graphics/render/layers/RenderLayer.js +95 -95
  952. package/src/engine/graphics/sh3/build_injected_shader.js +56 -56
  953. package/src/engine/graphics/sh3/grid_dilate_average.js +175 -175
  954. package/src/engine/graphics/sh3/path_tracer/BufferedGeometryBVH.js +506 -506
  955. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +161 -161
  956. package/src/engine/graphics/sh3/path_tracer/PathTracedRenderer.js +205 -205
  957. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +698 -698
  958. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +490 -490
  959. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -2
  960. package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -45
  961. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +73 -73
  962. package/src/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +32 -32
  963. package/src/engine/graphics/sh3/path_tracer/texture/apply_texture_clamping_to_coordinate.js +28 -28
  964. package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +142 -142
  965. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -70
  966. package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -388
  967. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -277
  968. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -57
  969. package/src/engine/graphics/shadows/vsm.glsl.js +43 -43
  970. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -81
  971. package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -15
  972. package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -26
  973. package/src/engine/graphics/texture/isImageBitmap.js +2 -2
  974. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -189
  975. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -51
  976. package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
  977. package/src/engine/graphics/texture/sampler/Sampler2DArray.js +172 -172
  978. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +466 -466
  979. package/src/engine/graphics/texture/sampler/compare/flip/FlipParameters.js +18 -18
  980. package/src/engine/graphics/texture/sampler/compare/flip/FlipPooling.js +33 -33
  981. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_feature_kernel.js +147 -147
  982. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_spatial_kernel.js +177 -177
  983. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_color_difference.js +104 -104
  984. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_feature_difference.js +76 -76
  985. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_pixels_per_degree.js +34 -34
  986. package/src/engine/graphics/texture/sampler/compare/flip/flip_constants.js +77 -77
  987. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_feature.js +48 -48
  988. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_spatial.js +86 -86
  989. package/src/engine/graphics/texture/sampler/compare/flip/flip_pool.js +71 -71
  990. package/src/engine/graphics/texture/sampler/compare/flip/flip_srgb_to_ycxcz.js +55 -55
  991. package/src/engine/graphics/texture/sampler/compare/flip/sampler2d_flip_ldr.js +80 -80
  992. package/src/engine/graphics/texture/sampler/filter/SeparableKernel.js +82 -82
  993. package/src/engine/graphics/texture/sampler/filter/sampler2d_convolve_separable.js +122 -122
  994. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +148 -148
  995. package/src/engine/graphics/texture/sampler/sampler2d_channel_apply_lut.js +82 -82
  996. package/src/engine/graphics/texture/sampler/sampler2d_combine.js +67 -67
  997. package/src/engine/graphics/texture/sampler/sampler2d_linear_f16_to_srgb_u8.js +54 -54
  998. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -63
  999. package/src/engine/graphics/texture/sampler/sampler2d_srgb_to_linear.js +33 -33
  1000. package/src/engine/graphics/texture/sampler/sampler2d_srgb_u8_to_linear_f16.js +68 -68
  1001. package/src/engine/graphics/texture/shade_image_preview.js +103 -103
  1002. package/src/engine/graphics/trail/TrailSpawnMode.js +20 -20
  1003. package/src/engine/graphics/trail/tube/TubeX.js +573 -573
  1004. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +58 -58
  1005. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +34 -34
  1006. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +69 -69
  1007. package/src/engine/graphics/trail/tube/tube_frame.js +83 -83
  1008. package/src/engine/graphics3/AnimationGraphSystem3.js +329 -329
  1009. package/src/engine/graphics3/AnimationSystem3.js +352 -352
  1010. package/src/engine/graphics3/CameraSystem3.js +170 -170
  1011. package/src/engine/graphics3/DecalSystem3.js +441 -441
  1012. package/src/engine/graphics3/FogOfWarSystem3.js +265 -265
  1013. package/src/engine/graphics3/GraphicsEngine3.js +776 -776
  1014. package/src/engine/graphics3/HighlightSystem3.js +241 -241
  1015. package/src/engine/graphics3/LightSystem3.js +211 -211
  1016. package/src/engine/graphics3/MeshSystem3.js +646 -646
  1017. package/src/engine/graphics3/ParticleEmitterSystem3.js +289 -289
  1018. package/src/engine/graphics3/PathDisplaySystem3.js +309 -309
  1019. package/src/engine/graphics3/PickingQuery.js +48 -48
  1020. package/src/engine/graphics3/PickingResult.js +47 -47
  1021. package/src/engine/graphics3/PickingSystem3.js +273 -273
  1022. package/src/engine/graphics3/ShadeCameraAdapter.js +55 -55
  1023. package/src/engine/graphics3/ShadedGeometrySystem3.js +169 -169
  1024. package/src/engine/graphics3/TerrainSystem3.js +566 -566
  1025. package/src/engine/graphics3/TooltipComponentSystem3.js +328 -328
  1026. package/src/engine/graphics3/Trail3DSystem3.js +221 -221
  1027. package/src/engine/graphics3/WaterSystem3.js +293 -293
  1028. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  1029. package/src/engine/graphics3/animation/wrap_clip_time.js +23 -23
  1030. package/src/engine/graphics3/animation/write_graph_playback.js +48 -48
  1031. package/src/engine/graphics3/camera_sync_from_transform.js +29 -29
  1032. package/src/engine/graphics3/debug/gizmo_view_from_camera.js +48 -48
  1033. package/src/engine/graphics3/decal/DECAL_CLUSTER.js +61 -61
  1034. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +117 -117
  1035. package/src/engine/graphics3/decal/DecalAtlas.js +194 -194
  1036. package/src/engine/graphics3/decal/DecalAtlasFill.js +32 -32
  1037. package/src/engine/graphics3/decal/GPUDecalRenderer.js +360 -360
  1038. package/src/engine/graphics3/decal/chunk_decal_intersects_frustum.js +59 -59
  1039. package/src/engine/graphics3/decal/chunk_decal_sampling_info.js +57 -57
  1040. package/src/engine/graphics3/decal/chunk_decal_surface_frame.js +54 -54
  1041. package/src/engine/graphics3/decal/decal_atlas_border.js +69 -69
  1042. package/src/engine/graphics3/decal/decal_gpu_records.js +120 -120
  1043. package/src/engine/graphics3/decal/decal_material_samplers.js +109 -109
  1044. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +212 -212
  1045. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +207 -207
  1046. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +108 -108
  1047. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +151 -151
  1048. package/src/engine/graphics3/highlight/HIGHLIGHT_OUTLINE.js +23 -23
  1049. package/src/engine/graphics3/highlight/chunk_highlight_lookup.js +53 -53
  1050. package/src/engine/graphics3/highlight/pack_highlight_color.js +44 -44
  1051. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  1052. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  1053. package/src/engine/graphics3/load_cube_environment.js +68 -68
  1054. package/src/engine/graphics3/make_default_environment.js +107 -107
  1055. package/src/engine/graphics3/particles/particle_gpu_records.js +221 -221
  1056. package/src/engine/graphics3/path/build_tube_path_streams.js +98 -98
  1057. package/src/engine/graphics3/path/tube_stream_write_geometry.js +90 -90
  1058. package/src/engine/graphics3/preview/ModelPreviewFraming.js +35 -35
  1059. package/src/engine/graphics3/preview/make_model_preview_scene.js +154 -154
  1060. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  1061. package/src/engine/graphics3/preview/model_preview_framing.js +70 -70
  1062. package/src/engine/graphics3/shade_bundle_bounds.js +55 -55
  1063. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  1064. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  1065. package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.js +481 -481
  1066. package/src/engine/graphics3/terrain/chunk_terrain_grid_overlay.js +61 -61
  1067. package/src/engine/graphics3/terrain/chunk_terrain_splat_mix.js +66 -66
  1068. package/src/engine/graphics3/terrain/pack_terrain_row_table.js +53 -53
  1069. package/src/engine/graphics3/terrain/shader_terrain_splat.js +215 -215
  1070. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +158 -158
  1071. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts +2 -2
  1072. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts.map +1 -1
  1073. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
  1074. package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
  1075. package/src/engine/input/devices/GamepadDevice.js +466 -466
  1076. package/src/engine/input/devices/ManualInputDevice.js +152 -152
  1077. package/src/engine/input/devices/PointerCoordinates.js +26 -26
  1078. package/src/engine/input/devices/events/GamepadEvents.js +10 -10
  1079. package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
  1080. package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
  1081. package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
  1082. package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
  1083. package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
  1084. package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
  1085. package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
  1086. package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
  1087. package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
  1088. package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
  1089. package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
  1090. package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
  1091. package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
  1092. package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
  1093. package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
  1094. package/src/engine/input/ecs/components/Input.js +118 -118
  1095. package/src/engine/input/ecs/components/InputController.js +78 -78
  1096. package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
  1097. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
  1098. package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
  1099. package/src/engine/input/ecs/ism/InputBinding.js +71 -71
  1100. package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
  1101. package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
  1102. package/src/engine/input/ecs/ism/InputDirection.js +33 -33
  1103. package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
  1104. package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
  1105. package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
  1106. package/src/engine/input/ecs/ism/InputSource.js +67 -67
  1107. package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
  1108. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
  1109. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
  1110. package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
  1111. package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
  1112. package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
  1113. package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
  1114. package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
  1115. package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
  1116. package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
  1117. package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
  1118. package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
  1119. package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
  1120. package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
  1121. package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
  1122. package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
  1123. package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
  1124. package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
  1125. package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
  1126. package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
  1127. package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
  1128. package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
  1129. package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
  1130. package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
  1131. package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
  1132. package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
  1133. package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
  1134. package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
  1135. package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
  1136. package/src/engine/input/ecs/systems/InputSystem.js +162 -162
  1137. package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
  1138. package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
  1139. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
  1140. package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
  1141. package/src/engine/interpolation/Interpoland.js +49 -49
  1142. package/src/engine/interpolation/Interpolated.js +149 -149
  1143. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
  1144. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
  1145. package/src/engine/interpolation/pose_interpoland.js +27 -27
  1146. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  1147. package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
  1148. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
  1149. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
  1150. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
  1151. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
  1152. package/src/engine/network/CONGESTION_CONTROL.md +87 -87
  1153. package/src/engine/network/README.md +52 -52
  1154. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
  1155. package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
  1156. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
  1157. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
  1158. package/src/engine/network/convertPathToURL.js +2 -2
  1159. package/src/engine/network/core/MalformedPacketError.js +26 -26
  1160. package/src/engine/network/core/quantize/quantize_float.js +73 -73
  1161. package/src/engine/network/core/quantize/quantize_position.js +65 -65
  1162. package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
  1163. package/src/engine/network/core/sequence/seq16.js +69 -69
  1164. package/src/engine/network/core/sequence/seq32.js +73 -73
  1165. package/src/engine/network/ecs/NetworkSystem.js +84 -84
  1166. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
  1167. package/src/engine/network/ecs/owner_authorization.js +55 -55
  1168. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
  1169. package/src/engine/network/replication/ScopeFilter.js +71 -71
  1170. package/src/engine/network/sim/ActionLog.js +152 -152
  1171. package/src/engine/network/sim/SimAction.js +273 -273
  1172. package/src/engine/network/sim/Snapshotter.js +222 -222
  1173. package/src/engine/network/state/FrameBufferRing.js +168 -168
  1174. package/src/engine/network/state/InputRing.js +134 -134
  1175. package/src/engine/network/state/PriorityAccumulator.js +180 -180
  1176. package/src/engine/network/time/TimeDilation.js +62 -62
  1177. package/src/engine/network/transport/Channel.js +336 -336
  1178. package/src/engine/network/transport/Transport.js +203 -203
  1179. package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
  1180. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
  1181. package/src/engine/network/transport/fragments/fragment_send.js +147 -147
  1182. package/src/engine/network/transport/fragments/packet_size.js +101 -101
  1183. package/src/engine/network/xhr.js +23 -23
  1184. package/src/engine/physics/BULLET_REVIEW.md +945 -945
  1185. package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
  1186. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
  1187. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
  1188. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
  1189. package/src/engine/physics/JOLT_REVIEW.md +913 -913
  1190. package/src/engine/physics/PLAN.md +1120 -1094
  1191. package/src/engine/physics/RAPIER_REVIEW.md +934 -934
  1192. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
  1193. package/src/engine/physics/REVIEW_002.md +151 -151
  1194. package/src/engine/physics/REVIEW_003.md +166 -166
  1195. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
  1196. package/src/engine/physics/constraint/DofMode.js +35 -35
  1197. package/src/engine/physics/constraint/solve_constraints.js +1 -1
  1198. package/src/engine/physics/contact/combine_material.js +35 -35
  1199. package/src/engine/physics/ecs/BodyKind.js +29 -29
  1200. package/src/engine/physics/ecs/Collider.js +177 -177
  1201. package/src/engine/physics/ecs/ColliderFlags.js +15 -15
  1202. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
  1203. package/src/engine/physics/ecs/Joint.js +475 -475
  1204. package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
  1205. package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
  1206. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  1207. package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
  1208. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
  1209. package/src/engine/physics/ecs/SleepState.js +12 -12
  1210. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
  1211. package/src/engine/physics/fluid/FluidField.js +867 -867
  1212. package/src/engine/physics/fluid/FluidSimulator.js +832 -832
  1213. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
  1214. package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
  1215. package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
  1216. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
  1217. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
  1218. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
  1219. package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
  1220. package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
  1221. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
  1222. package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
  1223. package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
  1224. package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
  1225. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
  1226. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
  1227. package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
  1228. package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
  1229. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
  1230. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
  1231. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
  1232. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
  1233. package/src/engine/physics/fluid/prototype.js +126 -126
  1234. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
  1235. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
  1236. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
  1237. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
  1238. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
  1239. package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
  1240. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
  1241. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
  1242. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
  1243. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
  1244. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
  1245. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
  1246. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
  1247. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
  1248. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
  1249. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
  1250. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
  1251. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
  1252. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
  1253. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
  1254. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
  1255. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
  1256. package/src/engine/physics/integration/integrate_position.js +97 -97
  1257. package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
  1258. package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
  1259. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
  1260. package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
  1261. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
  1262. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
  1263. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  1264. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
  1265. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
  1266. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
  1267. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  1268. package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
  1269. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
  1270. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
  1271. package/src/engine/physics/persistence/solver_caches.js +309 -309
  1272. package/src/engine/physics/queries/overlap_shape.js +187 -187
  1273. package/src/engine/physics/queries/raycast.d.ts +7 -4
  1274. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  1275. package/src/engine/physics/queries/raycast.js +11 -5
  1276. package/src/engine/physics/queries/shape_cast.js +417 -417
  1277. package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
  1278. package/src/engine/physics/solver/friction_cone.js +37 -37
  1279. package/src/engine/physics/solver/solve_contacts.js +1 -1
  1280. package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
  1281. package/src/engine/platform/WebEnginePlatform.js +1 -2
  1282. package/src/engine/scene/SerializedScene.d.ts +2 -2
  1283. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  1284. package/src/engine/scene/transitionToScene.js +121 -121
  1285. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  1286. package/src/engine/simulation/Ticker.js +33 -0
  1287. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
  1288. package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
  1289. package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
  1290. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
  1291. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
  1292. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
  1293. package/src/engine/sound/simulation/README.md +277 -277
  1294. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
  1295. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
  1296. package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
  1297. package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
  1298. package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
  1299. package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
  1300. package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
  1301. package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
  1302. package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
  1303. package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
  1304. package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
  1305. package/src/engine/sound/simulation/core/RayHit.js +50 -50
  1306. package/src/engine/sound/simulation/core/VolumeField.js +149 -149
  1307. package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
  1308. package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
  1309. package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
  1310. package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
  1311. package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
  1312. package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
  1313. package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
  1314. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
  1315. package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
  1316. package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
  1317. package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
  1318. package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
  1319. package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
  1320. package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
  1321. package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
  1322. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
  1323. package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
  1324. package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
  1325. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
  1326. package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
  1327. package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
  1328. package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
  1329. package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
  1330. package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
  1331. package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
  1332. package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
  1333. package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
  1334. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
  1335. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
  1336. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
  1337. package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
  1338. package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
  1339. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
  1340. package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
  1341. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
  1342. package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
  1343. package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
  1344. package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
  1345. package/src/engine/sound/sopra/README.md +643 -643
  1346. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  1347. package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
  1348. package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
  1349. package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
  1350. package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
  1351. package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
  1352. package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
  1353. package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
  1354. package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
  1355. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
  1356. package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
  1357. package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
  1358. package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
  1359. package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
  1360. package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
  1361. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
  1362. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
  1363. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
  1364. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
  1365. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
  1366. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
  1367. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
  1368. package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
  1369. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
  1370. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
  1371. package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
  1372. package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
  1373. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
  1374. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  1375. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
  1376. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
  1377. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
  1378. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
  1379. package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
  1380. package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
  1381. package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
  1382. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
  1383. package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
  1384. package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
  1385. package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
  1386. package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
  1387. package/src/engine/sound/sopra/runtime/Voice.js +145 -145
  1388. package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
  1389. package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
  1390. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
  1391. package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
  1392. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
  1393. package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
  1394. package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
  1395. package/src/engine/ui/DraggableAspect.js +115 -115
  1396. package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
  1397. package/src/generation/COORDINATES.md +54 -54
  1398. package/src/generation/GridGenerationResource.js +24 -24
  1399. package/src/generation/GridTaskGroup.js +214 -214
  1400. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
  1401. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
  1402. package/src/generation/automata/CellularAutomata.js +22 -22
  1403. package/src/generation/compute_writes_union.js +25 -25
  1404. package/src/generation/filtering/CellFilter.js +117 -117
  1405. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
  1406. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
  1407. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
  1408. package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
  1409. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
  1410. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
  1411. package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
  1412. package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
  1413. package/src/generation/grid/GridData.js +233 -233
  1414. package/src/generation/grid/coords/grid_to_texel.js +10 -10
  1415. package/src/generation/grid/coords/texel_to_grid.js +10 -10
  1416. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
  1417. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
  1418. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
  1419. package/src/generation/grid/generation/GridTaskSequence.js +58 -58
  1420. package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
  1421. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
  1422. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
  1423. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
  1424. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
  1425. package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
  1426. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
  1427. package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
  1428. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
  1429. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
  1430. package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
  1431. package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
  1432. package/src/generation/placement/action/GridCellAction.js +45 -45
  1433. package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
  1434. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
  1435. package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
  1436. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
  1437. package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
  1438. package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
  1439. package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
  1440. package/src/generation/theme/ThemeEngine.js +666 -666
  1441. package/src/shade/RENDERER_CONTRACT.md +568 -0
  1442. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
  1443. package/src/shade/device/ShadeDeviceFailure.js +104 -104
  1444. package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
  1445. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
  1446. package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
  1447. package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
  1448. package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
  1449. package/src/shade/device/mock/SoftwareGPUError.js +63 -63
  1450. package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
  1451. package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
  1452. package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
  1453. package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
  1454. package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
  1455. package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
  1456. package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
  1457. package/src/shade/device/mock/texture_copy.js +287 -287
  1458. package/src/shade/device/timing/GPUTimer.js +285 -285
  1459. package/src/shade/device/timing/GPUTimerArray.js +205 -205
  1460. package/src/shade/playground/add_random_lights.js +49 -49
  1461. package/src/shade/playground/add_random_meshes.js +83 -83
  1462. package/src/shade/playground/animation_prototype.js +508 -508
  1463. package/src/shade/playground/animation_prototype_skinning.js +647 -647
  1464. package/src/shade/playground/animation_prototype_stress.js +765 -765
  1465. package/src/shade/playground/enable_picker.js +59 -59
  1466. package/src/shade/playground/gltf_skinned_prototype.js +560 -560
  1467. package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
  1468. package/src/shade/playground/gltf_viewer.js +282 -282
  1469. package/src/shade/playground/load_default_environment.js +19 -19
  1470. package/src/shade/playground/main.js +2727 -2727
  1471. package/src/shade/playground/make_animated_instances.js +117 -117
  1472. package/src/shade/playground/prototype_virtual_texture.js +274 -274
  1473. package/src/shade/playground/prototype_volumetrics_01.js +206 -206
  1474. package/src/shade/playground/sample.js +234 -234
  1475. package/src/shade/playground/sample_load_gltf.js +102 -102
  1476. package/src/shade/playground/spread_node3d_grid.js +19 -19
  1477. package/src/shade/renderer/Renderer.js +2436 -2436
  1478. package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
  1479. package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
  1480. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
  1481. package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
  1482. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
  1483. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
  1484. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
  1485. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
  1486. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
  1487. package/src/shade/renderer/binding/BindGroupManager.js +282 -282
  1488. package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
  1489. package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
  1490. package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
  1491. package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
  1492. package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
  1493. package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
  1494. package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
  1495. package/src/shade/renderer/camera/Camera.js +281 -281
  1496. package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
  1497. package/src/shade/renderer/camera/orbital/README.md +84 -84
  1498. package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
  1499. package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
  1500. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
  1501. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  1502. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
  1503. package/src/shade/renderer/extension/FrameContext.js +263 -263
  1504. package/src/shade/renderer/extension/FramePhase.js +104 -104
  1505. package/src/shade/renderer/extension/FrameRecord.js +126 -126
  1506. package/src/shade/renderer/extension/GBufferTextures.js +83 -83
  1507. package/src/shade/renderer/extension/PresentTarget.js +34 -34
  1508. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  1509. package/src/shade/renderer/extension/RenderExtension.js +69 -69
  1510. package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
  1511. package/src/shade/renderer/extension/SceneColor.js +40 -40
  1512. package/src/shade/renderer/extension/ViewTextures.js +78 -78
  1513. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
  1514. package/src/shade/renderer/geometry/Geometry.js +608 -608
  1515. package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
  1516. package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
  1517. package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
  1518. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
  1519. package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
  1520. package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
  1521. package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
  1522. package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
  1523. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
  1524. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
  1525. package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
  1526. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
  1527. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
  1528. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
  1529. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
  1530. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
  1531. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
  1532. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
  1533. package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
  1534. package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
  1535. package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
  1536. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
  1537. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
  1538. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
  1539. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
  1540. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
  1541. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
  1542. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
  1543. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
  1544. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
  1545. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
  1546. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
  1547. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
  1548. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
  1549. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
  1550. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
  1551. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
  1552. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
  1553. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
  1554. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
  1555. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
  1556. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
  1557. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
  1558. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
  1559. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
  1560. package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
  1561. package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
  1562. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
  1563. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
  1564. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
  1565. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
  1566. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
  1567. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
  1568. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
  1569. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
  1570. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
  1571. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
  1572. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
  1573. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
  1574. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
  1575. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
  1576. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
  1577. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
  1578. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
  1579. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
  1580. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
  1581. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
  1582. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
  1583. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
  1584. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
  1585. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
  1586. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
  1587. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
  1588. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
  1589. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
  1590. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
  1591. package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
  1592. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
  1593. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
  1594. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
  1595. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
  1596. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
  1597. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
  1598. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
  1599. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
  1600. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
  1601. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
  1602. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
  1603. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
  1604. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
  1605. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
  1606. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
  1607. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
  1608. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
  1609. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
  1610. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
  1611. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
  1612. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
  1613. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
  1614. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
  1615. package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
  1616. package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
  1617. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
  1618. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
  1619. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
  1620. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
  1621. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
  1622. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
  1623. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
  1624. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
  1625. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
  1626. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
  1627. package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
  1628. package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
  1629. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
  1630. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
  1631. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
  1632. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
  1633. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
  1634. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
  1635. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
  1636. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
  1637. package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
  1638. package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
  1639. package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
  1640. package/src/shade/renderer/light/make_sunlight.js +35 -35
  1641. package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
  1642. package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
  1643. package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
  1644. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
  1645. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
  1646. package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
  1647. package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
  1648. package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
  1649. package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
  1650. package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
  1651. package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
  1652. package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
  1653. package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
  1654. package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
  1655. package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
  1656. package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
  1657. package/src/shade/renderer/loader/usd/UsdError.js +33 -33
  1658. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
  1659. package/src/shade/renderer/loader/usd/load_usd.js +226 -226
  1660. package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
  1661. package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
  1662. package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
  1663. package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
  1664. package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
  1665. package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
  1666. package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
  1667. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
  1668. package/src/shade/renderer/material/ShadeMaterial.js +2 -2
  1669. package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
  1670. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  1671. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
  1672. package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
  1673. package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
  1674. package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
  1675. package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
  1676. package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
  1677. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
  1678. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
  1679. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
  1680. package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
  1681. package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
  1682. package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
  1683. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
  1684. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
  1685. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
  1686. package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
  1687. package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
  1688. package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
  1689. package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
  1690. package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
  1691. package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
  1692. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
  1693. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
  1694. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
  1695. package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
  1696. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
  1697. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
  1698. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
  1699. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
  1700. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
  1701. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
  1702. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
  1703. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
  1704. package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
  1705. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
  1706. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
  1707. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
  1708. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
  1709. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
  1710. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
  1711. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
  1712. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
  1713. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
  1714. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
  1715. package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
  1716. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
  1717. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
  1718. package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
  1719. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
  1720. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
  1721. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
  1722. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
  1723. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
  1724. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  1725. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
  1726. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
  1727. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
  1728. package/src/shade/renderer/scene/DynamicMesh.js +70 -70
  1729. package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
  1730. package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
  1731. package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
  1732. package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
  1733. package/src/shade/renderer/scene/TransformAuthority.js +33 -33
  1734. package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
  1735. package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
  1736. package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
  1737. package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
  1738. package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
  1739. package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
  1740. package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
  1741. package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
  1742. package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
  1743. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
  1744. package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
  1745. package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
  1746. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
  1747. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
  1748. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
  1749. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
  1750. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
  1751. package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
  1752. package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
  1753. package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
  1754. package/src/shade/renderer/texture/virtual/README.md +276 -276
  1755. package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
  1756. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
  1757. package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
  1758. package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
  1759. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
  1760. package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
  1761. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
  1762. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
  1763. package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
  1764. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
  1765. package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
  1766. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
  1767. package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
  1768. package/src/shade/renderer/water/shader_water.js +246 -246
  1769. package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
  1770. package/src/shade/vitest.setup.mjs +89 -89
  1771. package/src/shade/wgsl/validate_wgsl_source.js +316 -316
  1772. package/src/view/controller/controls/NumericIntervalControl.js +90 -90
  1773. package/src/view/controller/controls/Vector2Control.js +83 -83
  1774. package/src/view/controller/controls/Vector3Control.js +90 -90
  1775. package/src/view/elements/Group.js +56 -56
  1776. package/src/view/elements/drawCheckers.js +33 -33
  1777. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  1778. package/src/view/graphics/WebGLContextFailureView.js +76 -76
  1779. package/src/view/layout/DockPanel.js +51 -51
  1780. package/src/view/layout/SplitView.js +365 -365
  1781. package/src/view/layout/show_popup_menu.js +81 -81
  1782. package/src/view/minimap/MinimapCanvasView.js +411 -411
  1783. package/src/view/minimap/MinimapImageCache.js +88 -88
  1784. package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
  1785. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  1786. package/src/view/minimap/MinimapMarkerCollection.js +180 -180
  1787. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  1788. package/src/view/minimap/minimap_focus_area.js +97 -97
  1789. package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
  1790. package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
  1791. package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
  1792. package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
  1793. package/src/engine/ecs/attachment/Attachment.js +0 -57
  1794. package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
  1795. package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
  1796. package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
  1797. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
  1798. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
  1799. package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
  1800. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
  1801. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
  1802. package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
  1803. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
  1804. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
  1805. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
  1806. package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
  1807. package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
  1808. package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
  1809. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
  1810. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
  1811. package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
  1812. package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
  1813. package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
  1814. package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
  1815. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
  1816. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
  1817. package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
  1818. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
  1819. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
  1820. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
  1821. package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
  1822. package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
  1823. package/src/shade/renderer/animation/_dump_resolve.mjs +0 -5
@@ -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