@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
@@ -24,12 +24,15 @@ import { route_to_spline } from "./route_to_spline.js";
24
24
  * not because anything measured how related they are, but because being joined is what put them in
25
25
  * neighbouring columns and being joined to the same things is what put them next to each other.
26
26
  *
27
- * **Routing** decides where the wires go, which the placement has deliberately left open. Each wire
28
- * finds its own way through the space between the boxes, avoiding them and, as far as it can, each
29
- * other. This is where the drawing stops looking like a diagram of the algorithm and starts looking
30
- * like something somebody drew: wires that run alongside each other rather than through each other,
31
- * that go around a node instead of behind it, and that leave and arrive square to the ports they
32
- * belong to.
27
+ * **Routing** decides where the wires go, which the placement has left open within the columns it
28
+ * decided. A wire that crosses a column is taken through the lane the placement reserved for it
29
+ * there — which is how the placement's crossing-minimised order reaches the drawing — and between
30
+ * one lane and the next each wire finds its own way, avoiding the boxes and, as far as it can, the
31
+ * other wires: sharing a line with one costs it something, and so does crossing one. This is where
32
+ * the drawing stops looking like a diagram of the algorithm and starts looking like something
33
+ * somebody drew: wires that run alongside each other rather than through each other, that go
34
+ * around a node instead of behind it, that do not cross what they could as easily have gone round,
35
+ * and that leave and arrive square to the ports they belong to.
33
36
  *
34
37
  * The two halves are separate on purpose. Placement can be re-run without re-routing when only the
35
38
  * structure changed, and routing can be re-run without re-placing when somebody has dragged a node
@@ -63,7 +66,11 @@ export function layout_node_graph(graph, visual, options = new NodeGraphLayoutOp
63
66
 
64
67
  const layer_count = layout_assign_layers(boxes, position);
65
68
 
66
- layout_insert_lanes(boxes);
69
+ const lane_offset = new Int32Array(boxes.link_count + 1);
70
+
71
+ layout_insert_lanes(boxes, lane_offset);
72
+
73
+ assign_lanes(problem, lane_offset);
67
74
 
68
75
  const ordering = layout_order_layers(boxes, layer_count, options.order_sweeps);
69
76
 
@@ -91,6 +98,41 @@ export function layout_node_graph(graph, visual, options = new NodeGraphLayoutOp
91
98
  return { width, height, crossings };
92
99
  }
93
100
 
101
+ /**
102
+ * Hand each connection the lanes its link was given, so that the router can take it through them.
103
+ *
104
+ * @param {LayoutProblem} problem mutated: `lane_start` and `lane_box` are written
105
+ * @param {Int32Array} lane_offset from {@link layout_insert_lanes}, per link as they stood before it
106
+ * @returns {void}
107
+ */
108
+ function assign_lanes(problem, lane_offset) {
109
+ const count = problem.connection_count;
110
+
111
+ const lane_start = problem.lane_start;
112
+
113
+ for (let i = 0; i < count; i++) {
114
+ const link = problem.link_of_connection[i];
115
+
116
+ lane_start[i + 1] = lane_start[i] + (link === -1 ? 0 : lane_offset[link + 1] - lane_offset[link]);
117
+ }
118
+
119
+ const lane_box = new Int32Array(lane_start[count]);
120
+
121
+ for (let i = 0; i < count; i++) {
122
+ const link = problem.link_of_connection[i];
123
+
124
+ if (link === -1) {
125
+ continue;
126
+ }
127
+
128
+ for (let k = lane_offset[link], at = lane_start[i]; k < lane_offset[link + 1]; k++, at++) {
129
+ lane_box[at] = k;
130
+ }
131
+ }
132
+
133
+ problem.lane_box = lane_box;
134
+ }
135
+
94
136
  /**
95
137
  * Route the wires of an already placed graph.
96
138
  *
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * Two heuristics alternating, then a local fix-up, and the best arrangement any of them reaches is
5
5
  * what is kept — a sweep can leave the drawing worse than it found it, and there is no reason to
6
- * keep the last one rather than the best one.
6
+ * keep the last one rather than the best one. Best means fewest crossings, and between
7
+ * arrangements that cross equally often, the one whose links reach least far up and down.
7
8
  *
8
9
  * - **Sweeps.** Every box moves to the average, or to the median, of where its neighbours in the
9
10
  * adjacent column sit. Median wins where a box's neighbours fall into groups, average where they
@@ -17,6 +18,15 @@
17
18
  * that — so the crossing count here is the number of crossings the drawing will actually show,
18
19
  * counted rather than estimated.
19
20
  *
21
+ * **Ports are positions, not just boxes.** A link does not meet a box, it meets a port on it, and
22
+ * a box with three inputs fed by three boxes of the column before is drawn with three wires that
23
+ * cross each other whenever those three are stacked in the wrong order — an order that looks
24
+ * perfect to anything comparing boxes alone, since all three links arrive at the same box. So
25
+ * wherever this compares where a link's far end sits, it uses the box's rank plus how far down the
26
+ * box the port is, and two links into one box are as in or out of order as the ports they meet.
27
+ * Two links leaving one port are the exception: they fan out from a single point and cannot cross,
28
+ * whichever way round their targets are.
29
+ *
20
30
  * @param {LayoutBoxGraph} graph adjacency must be current
21
31
  * @param {number} layer_count
22
32
  * @param {number} sweeps
@@ -1 +1 @@
1
- {"version":3,"file":"layout_order_layers.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/model/node-graph/visual/layout/layout_order_layers.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wEATW,MAAM,UACN,MAAM;WACI,UAAU;UAAQ,UAAU;iBAAe,UAAU;eAAa,MAAM;EAsI5F"}
1
+ {"version":3,"file":"layout_order_layers.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/model/node-graph/visual/layout/layout_order_layers.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wEATW,MAAM,UACN,MAAM;WACI,UAAU;UAAQ,UAAU;iBAAe,UAAU;eAAa,MAAM;EAyJ5F"}
@@ -10,7 +10,8 @@ const EXCHANGE_ROUNDS = 4;
10
10
  *
11
11
  * Two heuristics alternating, then a local fix-up, and the best arrangement any of them reaches is
12
12
  * what is kept — a sweep can leave the drawing worse than it found it, and there is no reason to
13
- * keep the last one rather than the best one.
13
+ * keep the last one rather than the best one. Best means fewest crossings, and between
14
+ * arrangements that cross equally often, the one whose links reach least far up and down.
14
15
  *
15
16
  * - **Sweeps.** Every box moves to the average, or to the median, of where its neighbours in the
16
17
  * adjacent column sit. Median wins where a box's neighbours fall into groups, average where they
@@ -24,6 +25,15 @@ const EXCHANGE_ROUNDS = 4;
24
25
  * that — so the crossing count here is the number of crossings the drawing will actually show,
25
26
  * counted rather than estimated.
26
27
  *
28
+ * **Ports are positions, not just boxes.** A link does not meet a box, it meets a port on it, and
29
+ * a box with three inputs fed by three boxes of the column before is drawn with three wires that
30
+ * cross each other whenever those three are stacked in the wrong order — an order that looks
31
+ * perfect to anything comparing boxes alone, since all three links arrive at the same box. So
32
+ * wherever this compares where a link's far end sits, it uses the box's rank plus how far down the
33
+ * box the port is, and two links into one box are as in or out of order as the ports they meet.
34
+ * Two links leaving one port are the exception: they fan out from a single point and cannot cross,
35
+ * whichever way round their targets are.
36
+ *
27
37
  * @param {LayoutBoxGraph} graph adjacency must be current
28
38
  * @param {number} layer_count
29
39
  * @param {number} sweeps
@@ -101,11 +111,12 @@ export function layout_order_layers(graph, layer_count, sweeps) {
101
111
  }
102
112
  }
103
113
 
114
+ // Positions carry a fraction for the port, so nothing here is an integer any more.
104
115
  const scratch = {
105
116
  weight: new Float64Array(box_count),
106
- neighbours: new Int32Array(widest_degree),
107
- sequence: new Int32Array(graph.link_count),
108
- merge: new Int32Array(graph.link_count)
117
+ neighbours: new Float64Array(widest_degree),
118
+ sequence: new Float64Array(graph.link_count),
119
+ merge: new Float64Array(graph.link_count)
109
120
  };
110
121
 
111
122
  // Sorted by comparator rather than by one of the `array_quick_sort_by_lookup_*` helpers: those
@@ -116,12 +127,15 @@ export function layout_order_layers(graph, layer_count, sweeps) {
116
127
  // links across one boundary, in order of where they leave and then of where they arrive
117
128
  const by_endpoints = (a, b) =>
118
129
  (rank[graph.link_from[a]] - rank[graph.link_from[b]])
119
- || (rank[graph.link_to[a]] - rank[graph.link_to[b]]);
130
+ || (graph.link_from_y[a] - graph.link_from_y[b])
131
+ || (rank[graph.link_to[a]] - rank[graph.link_to[b]])
132
+ || (graph.link_to_y[a] - graph.link_to_y[b]);
120
133
 
121
134
  let best = order.slice();
122
135
  let best_cost = count_crossings(graph, rank, layer_count, boundary_start, boundary_link, by_endpoints, scratch);
136
+ let best_reach = reach(graph, order, layer_start, layer_count, scratch.weight);
123
137
 
124
- for (let sweep = 0; sweep < sweeps && best_cost > 0; sweep++) {
138
+ for (let sweep = 0; sweep < sweeps; sweep++) {
125
139
  const downward = sweep % 2 === 0;
126
140
  const median = (sweep >> 1) % 2 === 0;
127
141
 
@@ -146,8 +160,23 @@ export function layout_order_layers(graph, layer_count, sweeps) {
146
160
 
147
161
  const cost = count_crossings(graph, rank, layer_count, boundary_start, boundary_link, by_endpoints, scratch);
148
162
 
149
- if (cost < best_cost) {
163
+ // Fewer crossings wins; the same number of crossings wins if the links reach less far.
164
+ // The second half matters more than it looks: the order the boxes arrive in has the lanes
165
+ // after every node, and a sweep that brings each lane up beside the wire it belongs to
166
+ // regularly crosses exactly as often as leaving it at the bottom of the column did — the
167
+ // crossings merely move from where the lane meets its wire to where it leaves its port.
168
+ // Without the tie-break the arrival order is kept, and the wire is drawn to the bottom of
169
+ // the column and back.
170
+ if (cost > best_cost) {
171
+ continue;
172
+ }
173
+
174
+ // the weights are spent by now, so their array can hold the box tops
175
+ const wander = reach(graph, order, layer_start, layer_count, scratch.weight);
176
+
177
+ if (cost < best_cost || wander < best_reach) {
150
178
  best_cost = cost;
179
+ best_reach = wander;
151
180
  best.set(order);
152
181
  }
153
182
  }
@@ -163,9 +192,52 @@ export function layout_order_layers(graph, layer_count, sweeps) {
163
192
  return { order, rank, layer_start, crossings: best_cost };
164
193
  }
165
194
 
195
+ /**
196
+ * Where a link meets a box, as a position down the column: the box's rank, and then how far down
197
+ * the box the port is as a fraction of its height.
198
+ *
199
+ * A port sits strictly inside its box, so this is strictly less than the rank after. A lane has no
200
+ * height and no ports, and is simply its rank.
201
+ *
202
+ * @param {LayoutBoxGraph} graph
203
+ * @param {Int32Array} rank
204
+ * @param {number} box
205
+ * @param {number} y offset down the box at which the link meets it
206
+ * @returns {number}
207
+ */
208
+ function position_of(graph, rank, box, y) {
209
+ const height = graph.box_h[box];
210
+
211
+ return height > 0 ? rank[box] + y / height : rank[box];
212
+ }
213
+
214
+ /**
215
+ * Where a link meets its source box, as a position down the column. See {@link position_of}.
216
+ *
217
+ * @param {LayoutBoxGraph} graph
218
+ * @param {Int32Array} rank
219
+ * @param {number} link
220
+ * @returns {number}
221
+ */
222
+ function source_position(graph, rank, link) {
223
+ return position_of(graph, rank, graph.link_from[link], graph.link_from_y[link]);
224
+ }
225
+
226
+ /**
227
+ * @param {LayoutBoxGraph} graph
228
+ * @param {Int32Array} rank
229
+ * @param {number} link
230
+ * @returns {number}
231
+ */
232
+ function target_position(graph, rank, link) {
233
+ return position_of(graph, rank, graph.link_to[link], graph.link_to_y[link]);
234
+ }
235
+
166
236
  /**
167
237
  * Give every box in one column a position to be sorted by, taken from where its neighbours in the
168
- * adjacent column sit.
238
+ * adjacent column sit — where on them, that is: a box fed from the top port of a neighbour belongs
239
+ * above a box fed from its bottom one, and three boxes feeding one neighbour belong in the order
240
+ * of the ports they feed.
169
241
  *
170
242
  * A box with no neighbours on the side being looked at keeps the position it has. Otherwise a
171
243
  * source or a sink drifts to the top of its column on every single sweep, having nothing to hold
@@ -202,7 +274,7 @@ function reweigh(graph, order, rank, layer_start, at, downward, median, scratch)
202
274
  for (let i = 0; i < count; i++) {
203
275
  const link = downward ? graph.in_link[start + i] : graph.out_link[start + i];
204
276
 
205
- neighbours[i] = rank[downward ? graph.link_from[link] : graph.link_to[link]];
277
+ neighbours[i] = downward ? source_position(graph, rank, link) : target_position(graph, rank, link);
206
278
  }
207
279
 
208
280
  if (!median) {
@@ -278,6 +350,9 @@ function exchange(graph, order, rank, layer_start, layer_count) {
278
350
  /**
279
351
  * Crossings between the links of two boxes sharing a column, given `first` sits above `second`.
280
352
  *
353
+ * Only the far ends matter. Where on `first` and `second` their own links attach decides nothing
354
+ * about whether swapping the two helps, since it is the same either way round.
355
+ *
281
356
  * @param {LayoutBoxGraph} graph
282
357
  * @param {Int32Array} rank
283
358
  * @param {number} first
@@ -290,7 +365,7 @@ function pair_crossings(graph, rank, first, second) {
290
365
  for (let side = 0; side < 2; side++) {
291
366
  const offset = side === 0 ? graph.in_offset : graph.out_offset;
292
367
  const list = side === 0 ? graph.in_link : graph.out_link;
293
- const end_of = side === 0 ? graph.link_from : graph.link_to;
368
+ const position = side === 0 ? source_position : target_position;
294
369
 
295
370
  const first_start = offset[first];
296
371
  const first_end = offset[first + 1];
@@ -299,10 +374,10 @@ function pair_crossings(graph, rank, first, second) {
299
374
  const second_end = offset[second + 1];
300
375
 
301
376
  for (let i = first_start; i < first_end; i++) {
302
- const a = rank[end_of[list[i]]];
377
+ const a = position(graph, rank, list[i]);
303
378
 
304
379
  for (let k = second_start; k < second_end; k++) {
305
- if (a > rank[end_of[list[k]]]) {
380
+ if (a > position(graph, rank, list[k])) {
306
381
  total++;
307
382
  }
308
383
  }
@@ -315,7 +390,7 @@ function pair_crossings(graph, rank, first, second) {
315
390
  /**
316
391
  * How many times two links cross, over every column boundary.
317
392
  *
318
- * Links leaving one box are gathered in ascending order of where they arrive, so two of them never
393
+ * Links leaving one port are gathered in ascending order of where they arrive, so two of them never
319
394
  * register as a crossing — they start at the same point and cannot cross. What is left is counted
320
395
  * by inversions.
321
396
  *
@@ -352,7 +427,7 @@ function count_crossings(graph, rank, layer_count, boundary_start, boundary_link
352
427
  window.sort(by_endpoints);
353
428
 
354
429
  for (let i = 0; i < count; i++) {
355
- window[i] = rank[graph.link_to[window[i]]];
430
+ window[i] = target_position(graph, rank, window[i]);
356
431
  }
357
432
 
358
433
  total += inversions(window, scratch.merge);
@@ -361,11 +436,55 @@ function count_crossings(graph, rank, layer_count, boundary_start, boundary_link
361
436
  return total;
362
437
  }
363
438
 
439
+ /**
440
+ * How far the links reach up and down the drawing, all told: the sum over every link of the
441
+ * vertical distance between its two ends, with every column packed tight from the top.
442
+ *
443
+ * What separates two arrangements that cross equally often. Crossings are blind to distance — a
444
+ * dozen wires from one port to a dozen boxes cross the same things whether those boxes are next
445
+ * to the port or at the far end of the column — and an arrangement that is no better in crossings
446
+ * but keeps linked boxes together is the one to draw. Heights rather than ranks, because a lane is
447
+ * a rank like any other and a box is not: three lanes stacked under three boxes are the height of
448
+ * a wire, and counting them as three more boxes would call a wire to the bottom of that column
449
+ * and back as short as one to the box beside it.
450
+ *
451
+ * @param {LayoutBoxGraph} graph
452
+ * @param {Int32Array} order
453
+ * @param {Int32Array} layer_start
454
+ * @param {number} layer_count
455
+ * @param {Float64Array} top scratch, one per box: written with where each box's top would be
456
+ * @returns {number}
457
+ */
458
+ function reach(graph, order, layer_start, layer_count, top) {
459
+ for (let layer = 0; layer < layer_count; layer++) {
460
+ let y = 0;
461
+
462
+ for (let k = layer_start[layer]; k < layer_start[layer + 1]; k++) {
463
+ const box = order[k];
464
+
465
+ top[box] = y;
466
+
467
+ y += graph.box_h[box];
468
+ }
469
+ }
470
+
471
+ let total = 0;
472
+
473
+ for (let i = 0; i < graph.link_count; i++) {
474
+ const from = top[graph.link_from[i]] + graph.link_from_y[i];
475
+ const to = top[graph.link_to[i]] + graph.link_to_y[i];
476
+
477
+ total += Math.abs(from - to);
478
+ }
479
+
480
+ return total;
481
+ }
482
+
364
483
  /**
365
484
  * Pairs out of order, by merge sort.
366
485
  *
367
- * @param {Int32Array} values consumed; left sorted
368
- * @param {Int32Array} buffer at least as long as `values`
486
+ * @param {Float64Array} values consumed; left sorted
487
+ * @param {Float64Array} buffer at least as long as `values`
369
488
  * @returns {number}
370
489
  */
371
490
  function inversions(values, buffer) {
@@ -24,6 +24,35 @@
24
24
  * this a graph whose wires nearly all fit spends five further rounds re-deriving the same routes,
25
25
  * and the work grows as the square of the graph rather than with the trouble in it.
26
26
  *
27
+ * **The wires leaving one port are one net, and share lines with each other for nothing.** They
28
+ * are one signal, and they leave the port along one stub whatever anybody does; charging them for
29
+ * running along the same line after it prices up the one thing they cannot help, every round,
30
+ * until they are pushed onto whichever line is left and pulled apart there in an order nobody
31
+ * chose — which is how a fan of six wires came to be drawn crossing itself. Left to share, they
32
+ * run out of the port as one line and fork where each of them leaves, which is a bus, and is what
33
+ * a fan of wires from one port looks like in any drawing done by hand. See
34
+ * {@link RouteGrid#owner_h}.
35
+ *
36
+ * **A long wire is routed through its lanes.** The placement gave every wire that crosses a column
37
+ * a lane in it — a point the ordering stage put where it crosses the fewest other wires and the
38
+ * coordinate stage lined up with the lanes either side of it — and a wire with lanes is routed as
39
+ * a chain of short searches, one per lane, each ending where the lane is and going through it
40
+ * horizontally. That is the placement's crossing-minimised order drawn, rather than left for the
41
+ * router to rediscover one wire at a time; and it is what makes a wire forty columns long cheap to
42
+ * route, where one search across the whole drawing floods the grid and gives up. A wire whose
43
+ * lanes cannot be reached is routed free, as a wire with no lanes always is.
44
+ *
45
+ * **Crossings are not an argument, and are settled afterwards.** Sharing a line is something the
46
+ * negotiation can price up until one wire leaves; crossing is allowed, merely costed, and a wire
47
+ * that crosses six others may have had no way not to. But the order the wires are first routed in
48
+ * hides most of the crossings from the wires that make them: a wire routed early sees an empty
49
+ * grid, takes whichever of its equal routes surfaces first, and is then crossed by everything
50
+ * routed after it — and since it shares nothing it is never asked again. So once nothing is shared,
51
+ * every wire something has been done to is asked once more, with all the others present, and moves
52
+ * only if the route it finds is cheaper than the one it has. That is a descent on the total cost
53
+ * of the drawing — a crossing costs both wires the same, so a wire making itself cheaper makes the
54
+ * whole cheaper — and it stops on its own when a round moves nothing.
55
+ *
27
56
  * @see McMurchie, Ebeling — *PathFinder: A Negotiation-Based Performance-Driven Router for FPGAs*
28
57
  * (1995)
29
58
  *
@@ -1 +1 @@
1
- {"version":3,"file":"route_connections.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/model/node-graph/visual/layout/route_connections.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,oFANW,sBAAsB,GACpB,QAAQ,CA4GpB;uCAhJsC,6BAA6B;yBAE3C,eAAe"}
1
+ {"version":3,"file":"route_connections.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/model/node-graph/visual/layout/route_connections.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,oFANW,sBAAsB,GACpB,QAAQ,CA0GpB;uCA3KsC,6BAA6B;yBAE3C,eAAe"}