@woosh/meep-engine 3.16.0 → 3.17.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 (410) hide show
  1. package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
  2. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  3. package/editor/particles/effect/ParticleEffectDocument.js +38 -17
  4. package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
  5. package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
  6. package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
  7. package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
  8. package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
  9. package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
  10. package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
  11. package/editor/view/node-graph/NodeGraphView.js +84 -8
  12. package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
  13. package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
  14. package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
  15. package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
  16. package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
  17. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
  18. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
  19. package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
  20. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  21. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
  22. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
  23. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
  24. package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
  25. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
  26. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
  27. package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
  28. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  29. package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
  30. package/editor/view/particles/effect/particle-editor.css +123 -35
  31. package/package.json +1 -1
  32. package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
  33. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  34. package/src/core/binary/allocator/OffsetAllocator.js +10 -1
  35. package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
  36. package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
  37. package/src/core/collection/array/typed/float32_array_hash.js +38 -0
  38. package/src/core/graph/csr/CSRGraph.d.ts +8 -1
  39. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
  40. package/src/core/graph/csr/CSRGraph.js +14 -6
  41. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
  42. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
  43. package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
  44. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
  45. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
  46. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
  47. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
  48. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
  49. package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
  50. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
  51. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
  52. package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
  53. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
  54. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
  55. package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
  56. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
  57. package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
  58. package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
  59. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
  60. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
  61. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
  62. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
  63. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
  64. package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
  65. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
  66. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
  67. package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
  68. package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
  69. package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
  70. package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
  71. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
  72. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
  73. package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
  74. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
  75. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
  76. package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
  77. package/src/engine/animation/AnimationUtils.js +246 -246
  78. package/src/engine/animation/Animations.js +74 -74
  79. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
  80. package/src/engine/ecs/EventType.d.ts +0 -1
  81. package/src/engine/ecs/EventType.js +1 -26
  82. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
  83. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
  84. package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
  85. package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
  86. package/src/engine/ecs/parent/EntityNode.js +4 -9
  87. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
  88. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
  89. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
  90. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
  91. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
  92. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
  93. package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
  94. package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
  95. package/src/engine/ecs/transform/t64_announce_change.js +12 -12
  96. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
  97. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
  98. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
  99. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
  100. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
  101. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  102. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
  103. package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
  104. package/src/engine/graphics3/LightSystem.js +4 -8
  105. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  106. package/src/engine/graphics3/MeshSystem.js +9 -19
  107. package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
  108. package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
  109. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  110. package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
  111. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
  112. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
  113. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
  114. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
  115. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  116. package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
  117. package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
  118. package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
  119. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
  120. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
  121. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
  122. package/src/shade/playground/particle_editor/README.md +43 -2
  123. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  124. package/src/shade/playground/particle_system/particle_prototype.js +4 -5
  125. package/src/shade/playground/particle_system/particle_scene.js +4 -4
  126. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  127. package/src/shade/renderer/Renderer.js +13 -1
  128. package/src/shade/renderer/particles/DESIGN.md +104 -19
  129. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
  130. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  131. package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
  132. package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
  133. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  134. package/src/shade/renderer/particles/ParticleConstants.js +66 -23
  135. package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
  136. package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
  137. package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
  138. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  139. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
  140. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
  141. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
  142. package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
  143. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
  144. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
  145. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
  146. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
  147. package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
  148. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
  149. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  150. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
  151. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
  153. package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
  155. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
  156. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +6 -0
  157. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
  158. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +294 -319
  159. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
  160. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
  161. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
  162. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
  163. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
  164. package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
  165. package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
  166. package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
  167. package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
  168. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
  169. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
  170. package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
  171. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
  172. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
  173. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
  174. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
  175. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  176. package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
  177. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  178. package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
  179. package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
  180. package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
  181. package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
  182. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
  183. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
  184. package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
  185. package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
  186. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  187. package/src/shade/renderer/particles/graph_particles.js +105 -262
  188. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  189. package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
  190. package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
  191. package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
  192. package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
  193. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
  194. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  195. package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
  196. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
  197. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
  198. package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
  199. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
  200. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  201. package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
  202. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
  203. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  204. package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
  205. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
  206. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
  207. package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
  208. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
  209. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
  210. package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
  211. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
  212. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
  213. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
  214. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
  215. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
  216. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
  217. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
  218. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
  219. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
  220. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
  221. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
  222. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
  223. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
  224. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
  225. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
  226. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
  227. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
  228. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
  229. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
  230. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
  231. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
  232. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
  233. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
  234. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
  235. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
  236. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
  237. package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
  238. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
  239. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
  240. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
  241. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
  242. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
  243. package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
  244. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
  245. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  246. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
  247. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
  248. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
  249. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
  250. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
  251. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  252. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
  253. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
  254. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
  255. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
  256. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
  257. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
  258. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
  259. package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
  260. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
  261. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
  262. package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
  263. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
  264. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
  265. package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
  266. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
  267. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
  268. package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
  269. package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
  270. package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
  271. package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
  272. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
  273. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
  274. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
  275. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
  276. package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
  277. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
  278. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
  279. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
  280. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
  281. package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
  282. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
  283. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  284. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
  285. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
  286. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
  287. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
  288. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
  289. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  290. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
  291. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +26 -0
  292. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +1 -1
  293. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
  294. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
  295. package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
  296. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
  297. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
  298. package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
  299. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
  300. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
  301. package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
  302. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
  303. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
  304. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
  305. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
  306. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
  307. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
  308. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
  309. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  310. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
  311. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
  312. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
  313. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
  314. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
  315. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  316. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
  317. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
  318. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
  319. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
  320. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
  321. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
  322. package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
  323. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
  324. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
  325. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
  326. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
  327. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  328. package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
  329. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  330. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
  331. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
  332. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
  333. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
  334. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
  335. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
  336. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
  337. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
  338. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
  339. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
  340. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
  341. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
  342. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
  343. package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
  344. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
  345. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
  346. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
  347. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
  348. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
  349. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
  350. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
  351. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
  352. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
  353. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
  354. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
  355. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
  356. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
  357. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
  358. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
  359. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
  360. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
  361. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
  362. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
  363. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
  364. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
  365. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
  366. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
  367. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
  368. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
  369. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
  370. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
  371. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
  372. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
  373. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
  374. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
  375. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
  376. package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
  377. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
  378. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  379. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
  380. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  381. package/src/view/minimap/dom/MinimapCameraView.js +4 -9
  382. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
  383. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
  384. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
  385. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
  386. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
  387. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
  388. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
  389. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
  390. package/src/engine/ecs/transform/__probe.d.ts +0 -4
  391. package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
  392. package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
  393. package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
  394. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
  395. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
  396. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
  397. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
  398. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
  399. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
  400. package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
  401. package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
  402. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
  403. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
  404. package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
  405. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
  406. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
  407. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
  408. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
  409. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
  410. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts.map +0 -1
@@ -1,242 +1,405 @@
1
- import { BitSet } from "../../../../binary/BitSet.js";
2
- import { binarySearchLowIndex } from "../../../../collection/array/binarySearchLowIndex.js";
3
- import { isValueBetween } from "../../../../math/interval/isValueBetween.js";
4
- import { overlap1D } from "../../../../math/interval/overlap1D.js";
5
- import { number_compare_ascending } from "../../../../primitives/numbers/number_compare_ascending.js";
6
-
7
- /**
8
- * The space wires are allowed to occupy.
9
- *
10
- * A **sparse grid**: not a fine mesh over the drawing, but the few horizontal and vertical lines
11
- * that are actually worth travelling along — the edges of the boxes and a margin around them, the
12
- * heights the ports sit at, the lanes the layout reserved for wires passing through a column, and a
13
- * handful of tracks across each channel. Every route that is worth having runs along some of these
14
- * and turns where two of them meet, so a grid made of only these has every good route in it and is
15
- * a hundredth the size of a mesh fine enough to hold them.
16
- *
17
- * This is the Hanan grid of the obstacles, which is the standard construction: for a set of
18
- * rectangles, an optimal rectilinear route between any two points on it exists on the grid their
19
- * own edges induce, so nothing is lost by refusing to leave it.
20
- *
21
- * **Obstacles block edges, not vertices.** A wire crosses a box by travelling along a line that
22
- * passes through it, and whether that is possible is a property of the line between two grid
23
- * points rather than of the points themselves — both ends of a line straddling a box are outside
24
- * it. Marking the crossing itself is what makes a box solid, and it is also what lets the grid stay
25
- * sparse: a grid that had to make every crossing land on a blocked vertex would need a line at
26
- * every box edge, and there are four of those per box.
27
- *
28
- * **Occupancy is per edge as well**, for the same reason: two wires sharing a length of line
29
- * overlap and are drawn on top of each other, and two wires meeting at a point merely cross, which
30
- * is legal and costs the reader nothing. Counting points would make the router pay to avoid a
31
- * crossing and then take a detour to do it.
32
- *
33
- * @author Alex Goldring
34
- * @copyright Company Named Limited (c) 2026
35
- */
36
- export class RouteGrid {
37
-
38
- /**
39
- * Ascending, distinct.
40
- * @type {Float64Array}
41
- */
42
- xs;
43
-
44
- /**
45
- * @type {Float64Array}
46
- */
47
- ys;
48
-
49
- /**
50
- * @type {number}
51
- */
52
- nx = 0;
53
-
54
- /**
55
- * @type {number}
56
- */
57
- ny = 0;
58
-
59
- /**
60
- * @type {number}
61
- */
62
- vertex_count = 0;
63
-
64
- /**
65
- * Whether the line from vertex `v` to the vertex right of it passes through a box.
66
- * @type {BitSet}
67
- */
68
- blocked_h = new BitSet();
69
-
70
- /**
71
- * Whether the line from vertex `v` to the vertex below it passes through a box.
72
- * @type {BitSet}
73
- */
74
- blocked_v = new BitSet();
75
-
76
- /**
77
- * Wires currently occupying each rightward line.
78
- * @type {Int32Array}
79
- */
80
- use_h;
81
-
82
- /**
83
- * @type {Int32Array}
84
- */
85
- use_v;
86
-
87
- /**
88
- * What each rightward line remembers about having been fought over. See
89
- * {@link NodeGraphLayoutOptions#history_rate}.
90
- * @type {Float32Array}
91
- */
92
- history_h;
93
-
94
- /**
95
- * @type {Float32Array}
96
- */
97
- history_v;
98
-
99
- /**
100
- * @param {Float64Array} xs ascending, distinct
101
- * @param {Float64Array} ys ascending, distinct
102
- */
103
- constructor(xs, ys) {
104
- this.xs = xs;
105
- this.ys = ys;
106
-
107
- this.nx = xs.length;
108
- this.ny = ys.length;
109
-
110
- this.vertex_count = this.nx * this.ny;
111
-
112
- this.blocked_h.preventShrink();
113
- this.blocked_v.preventShrink();
114
-
115
- this.blocked_h.setCapacity(this.vertex_count);
116
- this.blocked_v.setCapacity(this.vertex_count);
117
-
118
- this.use_h = new Int32Array(this.vertex_count);
119
- this.use_v = new Int32Array(this.vertex_count);
120
-
121
- this.history_h = new Float32Array(this.vertex_count);
122
- this.history_v = new Float32Array(this.vertex_count);
123
- }
124
-
125
- /**
126
- * Forget every route, keeping the obstacles and everything the grid has learned about
127
- * congestion. This is what a round of rip-up and reroute starts with.
128
- * @returns {void}
129
- */
130
- clear_use() {
131
- this.use_h.fill(0);
132
- this.use_v.fill(0);
133
- }
134
-
135
- /**
136
- * Index of the grid line at or immediately below `value`.
137
- *
138
- * Clamped rather than reported as absent: a point off the end of the grid belongs to the line at
139
- * that end, which is what every caller here wants and what a bare lower bound does not say.
140
- *
141
- * @param {Float64Array} axis
142
- * @param {number} value
143
- * @returns {number}
144
- */
145
- static floor_index(axis, value) {
146
- const found = binarySearchLowIndex(axis, value, number_compare_ascending);
147
-
148
- // below every line
149
- return found === -1 ? 0 : found;
150
- }
151
-
152
- /**
153
- * Index of the grid line nearest `value`.
154
- *
155
- * @param {Float64Array} axis
156
- * @param {number} value
157
- * @returns {number}
158
- */
159
- static nearest_index(axis, value) {
160
- const low = RouteGrid.floor_index(axis, value);
161
-
162
- if (low + 1 >= axis.length) {
163
- return low;
164
- }
165
-
166
- return value - axis[low] <= axis[low + 1] - value ? low : low + 1;
167
- }
168
-
169
- /**
170
- * @param {number} x
171
- * @returns {number}
172
- */
173
- nearest_x(x) {
174
- return RouteGrid.nearest_index(this.xs, x);
175
- }
176
-
177
- /**
178
- * @param {number} y
179
- * @returns {number}
180
- */
181
- nearest_y(y) {
182
- return RouteGrid.nearest_index(this.ys, y);
183
- }
184
-
185
- /**
186
- * Mark every line crossing the given rectangle as impassable.
187
- *
188
- * A line is impassable when it enters the rectangle's interior. Lines running exactly along an
189
- * edge of it are left alone: the rectangle handed here is already the box grown by its
190
- * clearance, so its edges are where a wire is meant to run.
191
- *
192
- * @param {number} x0
193
- * @param {number} y0
194
- * @param {number} x1
195
- * @param {number} y1
196
- * @returns {void}
197
- */
198
- block_rectangle(x0, y0, x1, y1) {
199
- const xs = this.xs;
200
- const ys = this.ys;
201
-
202
- const nx = this.nx;
203
-
204
- // rightward lines: the line from column i covers [xs[i], xs[i+1]], and enters the rectangle
205
- // when that overlaps (x0, x1) while its own height is strictly inside (y0, y1)
206
- const column_first = RouteGrid.floor_index(xs, x0);
207
- const row_first = RouteGrid.floor_index(ys, y0);
208
- const column_last = RouteGrid.floor_index(xs, x1);
209
- const row_last = RouteGrid.floor_index(ys, y1);
210
-
211
- for (let j = row_first; j <= row_last && j < this.ny; j++) {
212
- if (!isValueBetween(ys[j], y0, y1)) {
213
- // the line runs along or outside an edge, which is where a wire is meant to be
214
- continue;
215
- }
216
-
217
- const row = j * nx;
218
-
219
- for (let i = column_first; i <= column_last && i + 1 < nx; i++) {
220
- if (!overlap1D(xs[i], xs[i + 1], x0, x1)) {
221
- continue;
222
- }
223
-
224
- this.blocked_h.set(row + i, true);
225
- }
226
- }
227
-
228
- for (let i = column_first; i <= column_last && i < nx; i++) {
229
- if (!isValueBetween(xs[i], x0, x1)) {
230
- continue;
231
- }
232
-
233
- for (let j = row_first; j <= row_last && j + 1 < this.ny; j++) {
234
- if (!overlap1D(ys[j], ys[j + 1], y0, y1)) {
235
- continue;
236
- }
237
-
238
- this.blocked_v.set(j * nx + i, true);
239
- }
240
- }
241
- }
242
- }
1
+ import { BitSet } from "../../../../binary/BitSet.js";
2
+ import { binarySearchLowIndex } from "../../../../collection/array/binarySearchLowIndex.js";
3
+ import { isValueBetween } from "../../../../math/interval/isValueBetween.js";
4
+ import { overlap1D } from "../../../../math/interval/overlap1D.js";
5
+ import { number_compare_ascending } from "../../../../primitives/numbers/number_compare_ascending.js";
6
+
7
+ /**
8
+ * Coordinates nearer than this to one another are the same coordinate.
9
+ *
10
+ * Two lines a fraction of a unit apart are one line to anybody looking at the drawing, and keeping
11
+ * both of them costs a whole row or column of the grid. It is also how far inside a box a line has
12
+ * to be before it counts as inside: a lane placed exactly a clearance from a box lands a rounding
13
+ * error either side of the box's own clearance line, and a line that is inside by less than this
14
+ * is on the edge.
15
+ *
16
+ * @type {number}
17
+ */
18
+ export const ROUTE_GRID_EPSILON = 0.5;
19
+
20
+ /**
21
+ * Add a wire of `net` to one line, or remove it, keeping the line's holder straight.
22
+ *
23
+ * The holder is the net that had the line first; a line vacated by its holder is up for grabs, and
24
+ * a line that never had a holder — its wires all arrived while some other net held it — gets one
25
+ * the next time a wire arrives on it empty of holder. Nothing is lost for it: those wires are of
26
+ * other nets than the one asking, and are charged as such, which they should be.
27
+ *
28
+ * @param {Int32Array} use
29
+ * @param {Int32Array} owner
30
+ * @param {Int32Array} owned
31
+ * @param {number} v
32
+ * @param {number} net
33
+ * @param {number} delta
34
+ * @returns {void}
35
+ */
36
+ function claim(use, owner, owned, v, net, delta) {
37
+ use[v] += delta;
38
+
39
+ if (delta > 0) {
40
+ if (owner[v] === -1) {
41
+ owner[v] = net;
42
+ owned[v] = 1;
43
+ } else if (owner[v] === net) {
44
+ owned[v]++;
45
+ }
46
+ } else if (owner[v] === net && --owned[v] === 0) {
47
+ owner[v] = -1;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * The space wires are allowed to occupy.
53
+ *
54
+ * A **sparse grid**: not a fine mesh over the drawing, but the few horizontal and vertical lines
55
+ * that are actually worth travelling along — the edges of the boxes and a margin around them, the
56
+ * heights the ports sit at, the lanes the layout reserved for wires passing through a column, and a
57
+ * handful of tracks across each channel. Every route that is worth having runs along some of these
58
+ * and turns where two of them meet, so a grid made of only these has every good route in it and is
59
+ * a hundredth the size of a mesh fine enough to hold them.
60
+ *
61
+ * This is the Hanan grid of the obstacles, which is the standard construction: for a set of
62
+ * rectangles, an optimal rectilinear route between any two points on it exists on the grid their
63
+ * own edges induce, so nothing is lost by refusing to leave it.
64
+ *
65
+ * **Obstacles block edges, not vertices.** A wire crosses a box by travelling along a line that
66
+ * passes through it, and whether that is possible is a property of the line between two grid
67
+ * points rather than of the points themselves — both ends of a line straddling a box are outside
68
+ * it. Marking the crossing itself is what makes a box solid, and it is also what lets the grid stay
69
+ * sparse: a grid that had to make every crossing land on a blocked vertex would need a line at
70
+ * every box edge, and there are four of those per box.
71
+ *
72
+ * **Occupancy is per edge as well**, for the same reason: two wires sharing a length of line
73
+ * overlap and are drawn on top of each other, and two wires meeting at a point merely cross, which
74
+ * is legal and costs the reader nothing. Counting points would make the router pay to avoid a
75
+ * crossing and then take a detour to do it.
76
+ *
77
+ * @author Alex Goldring
78
+ * @copyright Company Named Limited (c) 2026
79
+ */
80
+ export class RouteGrid {
81
+
82
+ /**
83
+ * Ascending, distinct.
84
+ * @type {Float64Array}
85
+ */
86
+ xs;
87
+
88
+ /**
89
+ * @type {Float64Array}
90
+ */
91
+ ys;
92
+
93
+ /**
94
+ * @type {number}
95
+ */
96
+ nx = 0;
97
+
98
+ /**
99
+ * @type {number}
100
+ */
101
+ ny = 0;
102
+
103
+ /**
104
+ * @type {number}
105
+ */
106
+ vertex_count = 0;
107
+
108
+ /**
109
+ * Whether the line from vertex `v` to the vertex right of it passes through a box.
110
+ * @type {BitSet}
111
+ */
112
+ blocked_h = new BitSet();
113
+
114
+ /**
115
+ * Whether the line from vertex `v` to the vertex below it passes through a box.
116
+ * @type {BitSet}
117
+ */
118
+ blocked_v = new BitSet();
119
+
120
+ /**
121
+ * Wires currently occupying each rightward line.
122
+ * @type {Int32Array}
123
+ */
124
+ use_h;
125
+
126
+ /**
127
+ * @type {Int32Array}
128
+ */
129
+ use_v;
130
+
131
+ /**
132
+ * What each rightward line remembers about having been fought over. See
133
+ * {@link NodeGraphLayoutOptions#history_rate}.
134
+ * @type {Float32Array}
135
+ */
136
+ history_h;
137
+
138
+ /**
139
+ * @type {Float32Array}
140
+ */
141
+ history_v;
142
+
143
+ /**
144
+ * Wires passing straight through each vertex horizontally — in along one rightward line and
145
+ * out along the next, without turning.
146
+ *
147
+ * This is what a crossing is made of. Wires are confined to the grid lines, so two of them can
148
+ * only cross at a vertex, and they cross there exactly when one goes straight through it one
149
+ * way and the other goes straight through it the other way. Every other way two wires can meet
150
+ * at a vertex is either a shared line, which {@link use_h} already counts, or two corners
151
+ * touching, which the curves they become pull apart.
152
+ *
153
+ * A wire's stub counts as the direction it arrives from: a wire leaving a port on the right of
154
+ * a box and carrying straight on has gone straight through the vertex where it met the grid.
155
+ *
156
+ * @type {Int32Array}
157
+ */
158
+ through_h;
159
+
160
+ /**
161
+ * @type {Int32Array}
162
+ */
163
+ through_v;
164
+
165
+ /**
166
+ * The net every wire on each rightward line belongs to, when they all belong to one — the
167
+ * wires that leave one port together are a net — and -1 otherwise.
168
+ *
169
+ * Wires of one net are one signal, and where they run along the same line they are one line
170
+ * that forks, not two wires drawn on top of each other. So a wire is charged for sharing a
171
+ * line only with wires of other nets, and this is what says how many of those there are: the
172
+ * wires on the line, less the ones of the net that holds it. A line with wires of several nets
173
+ * on it is held by whichever claimed it first; the others count as sharing, which they are.
174
+ *
175
+ * @type {Int32Array}
176
+ */
177
+ owner_h;
178
+
179
+ /**
180
+ * @type {Int32Array}
181
+ */
182
+ owner_v;
183
+
184
+ /**
185
+ * How many of the wires on each rightward line belong to the net that holds it.
186
+ * @type {Int32Array}
187
+ */
188
+ owned_h;
189
+
190
+ /**
191
+ * @type {Int32Array}
192
+ */
193
+ owned_v;
194
+
195
+ /**
196
+ * @param {Float64Array} xs ascending, distinct
197
+ * @param {Float64Array} ys ascending, distinct
198
+ */
199
+ constructor(xs, ys) {
200
+ this.xs = xs;
201
+ this.ys = ys;
202
+
203
+ this.nx = xs.length;
204
+ this.ny = ys.length;
205
+
206
+ this.vertex_count = this.nx * this.ny;
207
+
208
+ this.blocked_h.preventShrink();
209
+ this.blocked_v.preventShrink();
210
+
211
+ this.blocked_h.setCapacity(this.vertex_count);
212
+ this.blocked_v.setCapacity(this.vertex_count);
213
+
214
+ this.use_h = new Int32Array(this.vertex_count);
215
+ this.use_v = new Int32Array(this.vertex_count);
216
+
217
+ this.history_h = new Float32Array(this.vertex_count);
218
+ this.history_v = new Float32Array(this.vertex_count);
219
+
220
+ this.through_h = new Int32Array(this.vertex_count);
221
+ this.through_v = new Int32Array(this.vertex_count);
222
+
223
+ this.owner_h = new Int32Array(this.vertex_count).fill(-1);
224
+ this.owner_v = new Int32Array(this.vertex_count).fill(-1);
225
+
226
+ this.owned_h = new Int32Array(this.vertex_count);
227
+ this.owned_v = new Int32Array(this.vertex_count);
228
+ }
229
+
230
+ /**
231
+ * Forget every route, keeping the obstacles and everything the grid has learned about
232
+ * congestion. This is what a round of rip-up and reroute starts with.
233
+ * @returns {void}
234
+ */
235
+ clear_use() {
236
+ this.use_h.fill(0);
237
+ this.use_v.fill(0);
238
+
239
+ this.through_h.fill(0);
240
+ this.through_v.fill(0);
241
+
242
+ this.owner_h.fill(-1);
243
+ this.owner_v.fill(-1);
244
+
245
+ this.owned_h.fill(0);
246
+ this.owned_v.fill(0);
247
+ }
248
+
249
+ /**
250
+ * Wires of other nets on the rightward line from vertex `v`: what a wire of `net` shares it
251
+ * with. See {@link owner_h}.
252
+ *
253
+ * @param {number} v
254
+ * @param {number} net
255
+ * @returns {number}
256
+ */
257
+ foreign_h(v, net) {
258
+ return this.use_h[v] - (this.owner_h[v] === net ? this.owned_h[v] : 0);
259
+ }
260
+
261
+ /**
262
+ * @param {number} v
263
+ * @param {number} net
264
+ * @returns {number}
265
+ */
266
+ foreign_v(v, net) {
267
+ return this.use_v[v] - (this.owner_v[v] === net ? this.owned_v[v] : 0);
268
+ }
269
+
270
+ /**
271
+ * Put a wire of `net` on the rightward line from vertex `v`, or take it off.
272
+ *
273
+ * @param {number} v
274
+ * @param {number} net
275
+ * @param {number} delta 1 or -1
276
+ * @returns {void}
277
+ */
278
+ claim_h(v, net, delta) {
279
+ claim(this.use_h, this.owner_h, this.owned_h, v, net, delta);
280
+ }
281
+
282
+ /**
283
+ * @param {number} v
284
+ * @param {number} net
285
+ * @param {number} delta 1 or -1
286
+ * @returns {void}
287
+ */
288
+ claim_v(v, net, delta) {
289
+ claim(this.use_v, this.owner_v, this.owned_v, v, net, delta);
290
+ }
291
+
292
+ /**
293
+ * Index of the grid line at or immediately below `value`.
294
+ *
295
+ * Clamped rather than reported as absent: a point off the end of the grid belongs to the line at
296
+ * that end, which is what every caller here wants and what a bare lower bound does not say.
297
+ *
298
+ * @param {Float64Array} axis
299
+ * @param {number} value
300
+ * @returns {number}
301
+ */
302
+ static floor_index(axis, value) {
303
+ const found = binarySearchLowIndex(axis, value, number_compare_ascending);
304
+
305
+ // below every line
306
+ return found === -1 ? 0 : found;
307
+ }
308
+
309
+ /**
310
+ * Index of the grid line nearest `value`.
311
+ *
312
+ * @param {Float64Array} axis
313
+ * @param {number} value
314
+ * @returns {number}
315
+ */
316
+ static nearest_index(axis, value) {
317
+ const low = RouteGrid.floor_index(axis, value);
318
+
319
+ if (low + 1 >= axis.length) {
320
+ return low;
321
+ }
322
+
323
+ return value - axis[low] <= axis[low + 1] - value ? low : low + 1;
324
+ }
325
+
326
+ /**
327
+ * @param {number} x
328
+ * @returns {number}
329
+ */
330
+ nearest_x(x) {
331
+ return RouteGrid.nearest_index(this.xs, x);
332
+ }
333
+
334
+ /**
335
+ * @param {number} y
336
+ * @returns {number}
337
+ */
338
+ nearest_y(y) {
339
+ return RouteGrid.nearest_index(this.ys, y);
340
+ }
341
+
342
+ /**
343
+ * Mark every line crossing the given rectangle as impassable.
344
+ *
345
+ * A line is impassable when it enters the rectangle's interior. Lines running along an edge of
346
+ * it — to within {@link ROUTE_GRID_EPSILON} — are left alone: the rectangle handed here is
347
+ * already the box grown by its clearance, so its edges are where a wire is meant to run.
348
+ *
349
+ * @param {number} x0
350
+ * @param {number} y0
351
+ * @param {number} x1
352
+ * @param {number} y1
353
+ * @returns {void}
354
+ */
355
+ block_rectangle(x0, y0, x1, y1) {
356
+ const xs = this.xs;
357
+ const ys = this.ys;
358
+
359
+ const nx = this.nx;
360
+
361
+ // rightward lines: the line from column i covers [xs[i], xs[i+1]], and enters the rectangle
362
+ // when that overlaps (x0, x1) while its own height is strictly inside (y0, y1)
363
+ const column_first = RouteGrid.floor_index(xs, x0);
364
+ const row_first = RouteGrid.floor_index(ys, y0);
365
+ const column_last = RouteGrid.floor_index(xs, x1);
366
+ const row_last = RouteGrid.floor_index(ys, y1);
367
+
368
+ // what "inside" means, once lines on the edge are allowed to be a rounding error off it
369
+ const inner_x0 = x0 + ROUTE_GRID_EPSILON;
370
+ const inner_x1 = x1 - ROUTE_GRID_EPSILON;
371
+ const inner_y0 = y0 + ROUTE_GRID_EPSILON;
372
+ const inner_y1 = y1 - ROUTE_GRID_EPSILON;
373
+
374
+ for (let j = row_first; j <= row_last && j < this.ny; j++) {
375
+ if (!isValueBetween(ys[j], inner_y0, inner_y1)) {
376
+ // the line runs along or outside an edge, which is where a wire is meant to be
377
+ continue;
378
+ }
379
+
380
+ const row = j * nx;
381
+
382
+ for (let i = column_first; i <= column_last && i + 1 < nx; i++) {
383
+ if (!overlap1D(xs[i], xs[i + 1], x0, x1)) {
384
+ continue;
385
+ }
386
+
387
+ this.blocked_h.set(row + i, true);
388
+ }
389
+ }
390
+
391
+ for (let i = column_first; i <= column_last && i < nx; i++) {
392
+ if (!isValueBetween(xs[i], inner_x0, inner_x1)) {
393
+ continue;
394
+ }
395
+
396
+ for (let j = row_first; j <= row_last && j + 1 < this.ny; j++) {
397
+ if (!overlap1D(ys[j], ys[j + 1], y0, y1)) {
398
+ continue;
399
+ }
400
+
401
+ this.blocked_v.set(j * nx + i, true);
402
+ }
403
+ }
404
+ }
405
+ }