@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.
- package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
- package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
- package/editor/particles/effect/ParticleEffectDocument.js +38 -17
- package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
- package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
- package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
- package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
- package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
- package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
- package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
- package/editor/view/node-graph/NodeGraphView.js +84 -8
- package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
- package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
- package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
- package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
- package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
- package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
- package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
- package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
- package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
- package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
- package/editor/view/particles/effect/particle-editor.css +123 -35
- package/package.json +1 -1
- package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
- package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
- package/src/core/binary/allocator/OffsetAllocator.js +10 -1
- package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
- package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
- package/src/core/collection/array/typed/float32_array_hash.js +38 -0
- package/src/core/graph/csr/CSRGraph.d.ts +8 -1
- package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
- package/src/core/graph/csr/CSRGraph.js +14 -6
- package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
- package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
- package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
- package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
- package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
- package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
- package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
- package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
- package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
- package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
- package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
- package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
- package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
- package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
- package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
- package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
- package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
- package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
- package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
- package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
- package/src/engine/animation/AnimationUtils.js +246 -246
- package/src/engine/animation/Animations.js +74 -74
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
- package/src/engine/ecs/EventType.d.ts +0 -1
- package/src/engine/ecs/EventType.js +1 -26
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
- package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
- package/src/engine/ecs/parent/EntityNode.js +4 -9
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
- package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
- package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
- package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_announce_change.js +12 -12
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
- package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
- package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
- package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
- package/src/engine/graphics3/LightSystem.js +4 -8
- package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSystem.js +9 -19
- package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
- package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
- package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
- package/src/shade/playground/particle_editor/README.md +43 -2
- package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
- package/src/shade/playground/particle_system/particle_prototype.js +4 -5
- package/src/shade/playground/particle_system/particle_scene.js +4 -4
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +13 -1
- package/src/shade/renderer/particles/DESIGN.md +104 -19
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
- package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
- package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
- package/src/shade/renderer/particles/ParticleConstants.js +66 -23
- package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
- package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
- package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
- package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
- package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
- package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
- package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +6 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +294 -319
- package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
- package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
- package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
- package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
- package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
- package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
- package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
- package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
- package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
- package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles.js +105 -262
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
- package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
- package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
- package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
- package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
- package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
- package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
- package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
- package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
- package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
- package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
- package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
- package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
- package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
- package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
- package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
- package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
- package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
- package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
- package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
- package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
- package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
- package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
- package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
- package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +26 -0
- package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
- package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
- package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
- package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
- package/src/view/minimap/dom/MinimapCameraView.js +4 -9
- package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
- package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
- package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
- package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
- package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
- package/src/engine/ecs/transform/__probe.d.ts +0 -4
- package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
- package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
- package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
- package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
- package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
- package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
- package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
- package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
- package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
- package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
- package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts.map +0 -1
|
@@ -1,309 +1,716 @@
|
|
|
1
|
-
import { LAYOUT_SIDE_BOTTOM, LAYOUT_SIDE_LEFT, LAYOUT_SIDE_RIGHT, LAYOUT_SIDE_TOP } from "./LayoutProblem.js";
|
|
2
|
-
import { NodeGraphLayoutOptions } from "./NodeGraphLayoutOptions.js";
|
|
3
|
-
import { ROUTE_AXIS_H, ROUTE_AXIS_V, RouteSearch } from "./RouteSearch.js";
|
|
4
|
-
import { RouteSet } from "./RouteSet.js";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Route every wire, letting them argue over the space until they stop.
|
|
8
|
-
*
|
|
9
|
-
* This is negotiated congestion routing — PathFinder. Every wire is routed as if the lines other
|
|
10
|
-
* wires are on merely cost a little extra rather than being forbidden, and then the whole set is
|
|
11
|
-
* ripped up and routed again with the price raised. A wire that had somewhere else to go moves; a
|
|
12
|
-
* wire with nowhere else stays and the others give way around it. Repeat until nothing is shared.
|
|
13
|
-
*
|
|
14
|
-
* The reason to do it this way rather than routing wires one at a time and forbidding what is
|
|
15
|
-
* already taken is that forbidding makes the *order* decide the drawing. The first wire routed gets
|
|
16
|
-
* the straight line through the middle and everything after it detours, whether or not it was the
|
|
17
|
-
* one that needed it. Negotiation asks each wire how much it wants the space, by seeing which of
|
|
18
|
-
* them finds an alternative when the price goes up, and that question has an answer that does not
|
|
19
|
-
* depend on who was asked first.
|
|
20
|
-
*
|
|
21
|
-
* **History is what makes it settle.** Charging only for what is currently occupied makes two wires
|
|
22
|
-
* swap routes every round for ever, each taking the one the other has just left. A line that has
|
|
23
|
-
* been fought over stays expensive after it is vacated, so the second time round the pair separates
|
|
24
|
-
* instead of trading.
|
|
25
|
-
*
|
|
26
|
-
* **Only the wires in an argument are asked again.** After the first round, a wire whose route
|
|
27
|
-
* shares nothing with anybody has already got what it wanted and is left alone; the rounds after
|
|
28
|
-
* the first cost what the remaining conflicts cost rather than what the whole graph costs. Without
|
|
29
|
-
* this a graph whose wires nearly all fit spends five further rounds re-deriving the same routes,
|
|
30
|
-
* and the work grows as the square of the graph rather than with the trouble in it.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
*
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
1
|
+
import { LAYOUT_SIDE_BOTTOM, LAYOUT_SIDE_LEFT, LAYOUT_SIDE_RIGHT, LAYOUT_SIDE_TOP } from "./LayoutProblem.js";
|
|
2
|
+
import { NodeGraphLayoutOptions } from "./NodeGraphLayoutOptions.js";
|
|
3
|
+
import { ROUTE_AXIS_H, ROUTE_AXIS_V, RouteSearch } from "./RouteSearch.js";
|
|
4
|
+
import { RouteSet } from "./RouteSet.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Route every wire, letting them argue over the space until they stop.
|
|
8
|
+
*
|
|
9
|
+
* This is negotiated congestion routing — PathFinder. Every wire is routed as if the lines other
|
|
10
|
+
* wires are on merely cost a little extra rather than being forbidden, and then the whole set is
|
|
11
|
+
* ripped up and routed again with the price raised. A wire that had somewhere else to go moves; a
|
|
12
|
+
* wire with nowhere else stays and the others give way around it. Repeat until nothing is shared.
|
|
13
|
+
*
|
|
14
|
+
* The reason to do it this way rather than routing wires one at a time and forbidding what is
|
|
15
|
+
* already taken is that forbidding makes the *order* decide the drawing. The first wire routed gets
|
|
16
|
+
* the straight line through the middle and everything after it detours, whether or not it was the
|
|
17
|
+
* one that needed it. Negotiation asks each wire how much it wants the space, by seeing which of
|
|
18
|
+
* them finds an alternative when the price goes up, and that question has an answer that does not
|
|
19
|
+
* depend on who was asked first.
|
|
20
|
+
*
|
|
21
|
+
* **History is what makes it settle.** Charging only for what is currently occupied makes two wires
|
|
22
|
+
* swap routes every round for ever, each taking the one the other has just left. A line that has
|
|
23
|
+
* been fought over stays expensive after it is vacated, so the second time round the pair separates
|
|
24
|
+
* instead of trading.
|
|
25
|
+
*
|
|
26
|
+
* **Only the wires in an argument are asked again.** After the first round, a wire whose route
|
|
27
|
+
* shares nothing with anybody has already got what it wanted and is left alone; the rounds after
|
|
28
|
+
* the first cost what the remaining conflicts cost rather than what the whole graph costs. Without
|
|
29
|
+
* this a graph whose wires nearly all fit spends five further rounds re-deriving the same routes,
|
|
30
|
+
* and the work grows as the square of the graph rather than with the trouble in it.
|
|
31
|
+
*
|
|
32
|
+
* **The wires leaving one port are one net, and share lines with each other for nothing.** They
|
|
33
|
+
* are one signal, and they leave the port along one stub whatever anybody does; charging them for
|
|
34
|
+
* running along the same line after it prices up the one thing they cannot help, every round,
|
|
35
|
+
* until they are pushed onto whichever line is left and pulled apart there in an order nobody
|
|
36
|
+
* chose — which is how a fan of six wires came to be drawn crossing itself. Left to share, they
|
|
37
|
+
* run out of the port as one line and fork where each of them leaves, which is a bus, and is what
|
|
38
|
+
* a fan of wires from one port looks like in any drawing done by hand. See
|
|
39
|
+
* {@link RouteGrid#owner_h}.
|
|
40
|
+
*
|
|
41
|
+
* **A long wire is routed through its lanes.** The placement gave every wire that crosses a column
|
|
42
|
+
* a lane in it — a point the ordering stage put where it crosses the fewest other wires and the
|
|
43
|
+
* coordinate stage lined up with the lanes either side of it — and a wire with lanes is routed as
|
|
44
|
+
* a chain of short searches, one per lane, each ending where the lane is and going through it
|
|
45
|
+
* horizontally. That is the placement's crossing-minimised order drawn, rather than left for the
|
|
46
|
+
* router to rediscover one wire at a time; and it is what makes a wire forty columns long cheap to
|
|
47
|
+
* route, where one search across the whole drawing floods the grid and gives up. A wire whose
|
|
48
|
+
* lanes cannot be reached is routed free, as a wire with no lanes always is.
|
|
49
|
+
*
|
|
50
|
+
* **Crossings are not an argument, and are settled afterwards.** Sharing a line is something the
|
|
51
|
+
* negotiation can price up until one wire leaves; crossing is allowed, merely costed, and a wire
|
|
52
|
+
* that crosses six others may have had no way not to. But the order the wires are first routed in
|
|
53
|
+
* hides most of the crossings from the wires that make them: a wire routed early sees an empty
|
|
54
|
+
* grid, takes whichever of its equal routes surfaces first, and is then crossed by everything
|
|
55
|
+
* routed after it — and since it shares nothing it is never asked again. So once nothing is shared,
|
|
56
|
+
* every wire something has been done to is asked once more, with all the others present, and moves
|
|
57
|
+
* only if the route it finds is cheaper than the one it has. That is a descent on the total cost
|
|
58
|
+
* of the drawing — a crossing costs both wires the same, so a wire making itself cheaper makes the
|
|
59
|
+
* whole cheaper — and it stops on its own when a round moves nothing.
|
|
60
|
+
*
|
|
61
|
+
* @see McMurchie, Ebeling — *PathFinder: A Negotiation-Based Performance-Driven Router for FPGAs*
|
|
62
|
+
* (1995)
|
|
63
|
+
*
|
|
64
|
+
* @param {LayoutProblem} problem placement must be finished
|
|
65
|
+
* @param {RouteGrid} grid
|
|
66
|
+
* @param {NodeGraphLayoutOptions} options
|
|
67
|
+
* @returns {RouteSet}
|
|
68
|
+
*
|
|
69
|
+
* @author Alex Goldring
|
|
70
|
+
* @copyright Company Named Limited (c) 2026
|
|
71
|
+
*/
|
|
72
|
+
export function route_connections(problem, grid, options) {
|
|
73
|
+
const count = problem.connection_count;
|
|
74
|
+
|
|
75
|
+
const routes = new RouteSet(count);
|
|
76
|
+
|
|
77
|
+
if (count === 0) {
|
|
78
|
+
return routes;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const search = new RouteSearch(grid);
|
|
82
|
+
|
|
83
|
+
// present cost rises between rounds, and the caller's options are not ours to change
|
|
84
|
+
const working = NodeGraphLayoutOptions.from(options);
|
|
85
|
+
|
|
86
|
+
const port_x = new Float64Array(count * 2);
|
|
87
|
+
const port_y = new Float64Array(count * 2);
|
|
88
|
+
|
|
89
|
+
const escape_x = new Float64Array(count * 2);
|
|
90
|
+
const escape_y = new Float64Array(count * 2);
|
|
91
|
+
|
|
92
|
+
const wires = new WireSet(problem, grid, options, { port_x, port_y, escape_x, escape_y });
|
|
93
|
+
|
|
94
|
+
routes.net = wires.net;
|
|
95
|
+
|
|
96
|
+
// Routes as they currently stand, so that a wire can be taken off the grid before being routed
|
|
97
|
+
// again. Corner points alone are not enough for that — what has to be given back is every
|
|
98
|
+
// line the wire occupies.
|
|
99
|
+
/** @type {(WireRoute|null)[]} */
|
|
100
|
+
const held = [];
|
|
101
|
+
|
|
102
|
+
for (let i = 0; i < count; i++) {
|
|
103
|
+
held.push(null);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Which wires are worth asking again. Everything, to begin with, because nothing is routed yet.
|
|
107
|
+
const contested = new Uint8Array(count).fill(1);
|
|
108
|
+
|
|
109
|
+
for (let round = 0; round < options.congestion_iterations; round++) {
|
|
110
|
+
for (let i = 0; i < count; i++) {
|
|
111
|
+
if (contested[i] === 0) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (held[i] !== null) {
|
|
116
|
+
wires.occupy(i, held[i], -1);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
held[i] = wires.route(search, i, working);
|
|
120
|
+
|
|
121
|
+
if (held[i] !== null) {
|
|
122
|
+
wires.occupy(i, held[i], 1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (mark_contested(grid, held, wires.net, contested) === 0) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
remember(grid, options.history_rate);
|
|
131
|
+
|
|
132
|
+
working.present_cost *= options.present_growth;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Sharing is priced at what the negotiation would have charged had it run out of rounds: an
|
|
136
|
+
// improvement is not allowed to buy a route with a line the negotiation had already priced a
|
|
137
|
+
// wire off, and the wires still sharing something pay the same price for it as everyone else.
|
|
138
|
+
working.present_cost = options.present_cost * options.present_growth ** options.congestion_iterations;
|
|
139
|
+
|
|
140
|
+
for (let round = 0; round < options.improvement_rounds; round++) {
|
|
141
|
+
if (improve(search, wires, held, working) === 0) {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
for (let i = 0; i < count; i++) {
|
|
147
|
+
routes.begin(i);
|
|
148
|
+
|
|
149
|
+
routes.push(port_x[i * 2], port_y[i * 2]);
|
|
150
|
+
|
|
151
|
+
const route = held[i];
|
|
152
|
+
|
|
153
|
+
if (route !== null) {
|
|
154
|
+
const path = route.path;
|
|
155
|
+
|
|
156
|
+
for (let k = 0; k < path.length; k++) {
|
|
157
|
+
routes.push(grid.xs[path[k] % grid.nx], grid.ys[(path[k] / grid.nx) | 0]);
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
// Nothing was found — the wire is boxed in, or the search ran out of room to look. It
|
|
161
|
+
// still has to be drawn, and going out of one port and into the other the way every
|
|
162
|
+
// other wire does is a better failure than a line through the middle of a node.
|
|
163
|
+
routes.push(escape_x[i * 2], escape_y[i * 2]);
|
|
164
|
+
routes.push(escape_x[i * 2 + 1], escape_y[i * 2 + 1]);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
routes.push(port_x[i * 2 + 1], port_y[i * 2 + 1]);
|
|
168
|
+
|
|
169
|
+
routes.end(i);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return routes;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* One wire's route: its vertices, where each leg of it begins, and what it cost when it was chosen.
|
|
177
|
+
*
|
|
178
|
+
* A leg is one search — from the start to the first lane, from lane to lane, from the last lane to
|
|
179
|
+
* the goal — and the legs share their end points, so `leg[k]` is the index into `path` of the
|
|
180
|
+
* vertex leg `k` begins at, which is the vertex leg `k - 1` ended at. A wire with no lanes is one
|
|
181
|
+
* leg.
|
|
182
|
+
*/
|
|
183
|
+
class WireRoute {
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @type {Int32Array}
|
|
187
|
+
*/
|
|
188
|
+
path;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Length `legs + 1`; the last entry is `path.length - 1`.
|
|
192
|
+
* @type {Int32Array}
|
|
193
|
+
*/
|
|
194
|
+
leg;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* What each wire believed its route cost when it chose it. A wire whose route has since come
|
|
198
|
+
* to cost more has had something done to it — crossed, or joined on a line — and is the one
|
|
199
|
+
* worth asking whether it would now rather be elsewhere.
|
|
200
|
+
* @type {number}
|
|
201
|
+
*/
|
|
202
|
+
cost;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @param {Int32Array} path
|
|
206
|
+
* @param {Int32Array} leg
|
|
207
|
+
* @param {number} cost
|
|
208
|
+
*/
|
|
209
|
+
constructor(path, leg, cost) {
|
|
210
|
+
this.path = path;
|
|
211
|
+
this.leg = leg;
|
|
212
|
+
this.cost = cost;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Every wire's terminals and waypoints, on the grid, and the two things done with them: finding a
|
|
218
|
+
* wire a route, and putting one on the grid or taking it off.
|
|
219
|
+
*/
|
|
220
|
+
class WireSet {
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @type {RouteGrid}
|
|
224
|
+
*/
|
|
225
|
+
grid;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @type {Int32Array}
|
|
229
|
+
*/
|
|
230
|
+
start_vertex;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @type {Uint8Array}
|
|
234
|
+
*/
|
|
235
|
+
start_axis;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @type {Int32Array}
|
|
239
|
+
*/
|
|
240
|
+
goal_vertex;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @type {Uint8Array}
|
|
244
|
+
*/
|
|
245
|
+
goal_axis;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Net of each wire: the wires leaving one port share a number. See {@link RouteGrid#owner_h}.
|
|
249
|
+
* @type {Int32Array}
|
|
250
|
+
*/
|
|
251
|
+
net;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Where each wire's waypoints begin in {@link waypoint}. Length `count + 1`.
|
|
255
|
+
* @type {Int32Array}
|
|
256
|
+
*/
|
|
257
|
+
waypoint_start;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Grid vertex of every lane, grouped by wire in the order the wire goes through them.
|
|
261
|
+
* @type {Int32Array}
|
|
262
|
+
*/
|
|
263
|
+
waypoint;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @param {LayoutProblem} problem
|
|
267
|
+
* @param {RouteGrid} grid
|
|
268
|
+
* @param {NodeGraphLayoutOptions} options
|
|
269
|
+
* @param {{port_x: Float64Array, port_y: Float64Array, escape_x: Float64Array, escape_y: Float64Array}} terminal
|
|
270
|
+
* written, two entries per connection
|
|
271
|
+
*/
|
|
272
|
+
constructor(problem, grid, options, terminal) {
|
|
273
|
+
const count = problem.connection_count;
|
|
274
|
+
|
|
275
|
+
this.grid = grid;
|
|
276
|
+
|
|
277
|
+
this.start_vertex = new Int32Array(count);
|
|
278
|
+
this.start_axis = new Uint8Array(count);
|
|
279
|
+
this.goal_vertex = new Int32Array(count);
|
|
280
|
+
this.goal_axis = new Uint8Array(count);
|
|
281
|
+
|
|
282
|
+
for (let i = 0; i < count; i++) {
|
|
283
|
+
write_terminal(problem, grid, options, i, true, this.start_vertex, this.start_axis, terminal);
|
|
284
|
+
write_terminal(problem, grid, options, i, false, this.goal_vertex, this.goal_axis, terminal);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// one net per port wires leave from, numbered in the order the ports are first met
|
|
288
|
+
this.net = new Int32Array(count);
|
|
289
|
+
|
|
290
|
+
const net_of_port = new Map();
|
|
291
|
+
|
|
292
|
+
for (let i = 0; i < count; i++) {
|
|
293
|
+
const key = `${problem.from_box[i]}:${problem.from_dx[i]}:${problem.from_dy[i]}`;
|
|
294
|
+
|
|
295
|
+
let net = net_of_port.get(key);
|
|
296
|
+
|
|
297
|
+
if (net === undefined) {
|
|
298
|
+
net = net_of_port.size;
|
|
299
|
+
|
|
300
|
+
net_of_port.set(key, net);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
this.net[i] = net;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// a problem built by hand, or before placement, has no lanes at all
|
|
307
|
+
const lane_box = problem.lane_box ?? new Int32Array(0);
|
|
308
|
+
|
|
309
|
+
this.waypoint_start = problem.lane_start ?? new Int32Array(count + 1);
|
|
310
|
+
|
|
311
|
+
const lane_count = lane_box.length;
|
|
312
|
+
|
|
313
|
+
this.waypoint = new Int32Array(lane_count);
|
|
314
|
+
|
|
315
|
+
const boxes = problem.boxes;
|
|
316
|
+
|
|
317
|
+
for (let k = 0; k < lane_count; k++) {
|
|
318
|
+
const lane = lane_box[k];
|
|
319
|
+
|
|
320
|
+
this.waypoint[k] = grid.nearest_x(boxes.box_x[lane]) + grid.nearest_y(boxes.box_y[lane]) * grid.nx;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Find a wire its route: through its lanes if it has any and they can be reached, free
|
|
326
|
+
* otherwise.
|
|
327
|
+
*
|
|
328
|
+
* @param {RouteSearch} search
|
|
329
|
+
* @param {number} index wire
|
|
330
|
+
* @param {NodeGraphLayoutOptions} options
|
|
331
|
+
* @returns {WireRoute|null} null when no route was found
|
|
332
|
+
*/
|
|
333
|
+
route(search, index, options) {
|
|
334
|
+
const first = this.waypoint_start[index];
|
|
335
|
+
const last = this.waypoint_start[index + 1];
|
|
336
|
+
|
|
337
|
+
if (last > first) {
|
|
338
|
+
const through = this.__route_legs(search, index, options, first, last);
|
|
339
|
+
|
|
340
|
+
if (through !== null) {
|
|
341
|
+
return through;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return this.__route_legs(search, index, options, 0, 0);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* What a route costs under the grid as it stands, leg by leg. See {@link RouteSearch#cost_of}.
|
|
350
|
+
*
|
|
351
|
+
* @param {RouteSearch} search
|
|
352
|
+
* @param {number} index wire
|
|
353
|
+
* @param {WireRoute} route its own occupancy must be off the grid
|
|
354
|
+
* @param {NodeGraphLayoutOptions} options
|
|
355
|
+
* @returns {number}
|
|
356
|
+
*/
|
|
357
|
+
cost_of(search, index, route, options) {
|
|
358
|
+
const path = route.path;
|
|
359
|
+
const leg = route.leg;
|
|
360
|
+
|
|
361
|
+
const legs = leg.length - 1;
|
|
362
|
+
|
|
363
|
+
let cost = 0;
|
|
364
|
+
|
|
365
|
+
for (let k = 0; k < legs; k++) {
|
|
366
|
+
const from = leg[k];
|
|
367
|
+
const to = leg[k + 1];
|
|
368
|
+
|
|
369
|
+
cost += search.cost_of(
|
|
370
|
+
path.subarray(from, to + 1),
|
|
371
|
+
to + 1 - from,
|
|
372
|
+
k === 0 ? this.start_axis[index] : ROUTE_AXIS_H,
|
|
373
|
+
k === legs - 1 ? this.goal_axis[index] : ROUTE_AXIS_H,
|
|
374
|
+
options,
|
|
375
|
+
k === legs - 1,
|
|
376
|
+
this.net[index]
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return cost;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Claim, or give back, every line a route runs along, and every vertex it goes straight
|
|
385
|
+
* through.
|
|
386
|
+
*
|
|
387
|
+
* Only what is on the grid is claimed. The stub between a port and the grid is not on it and is
|
|
388
|
+
* never charged, which is what lets several wires leave one port: they share that stub whatever
|
|
389
|
+
* it would cost, having no say in where their own port is, and they are only asked to separate
|
|
390
|
+
* once they are somewhere they could have chosen. The stub does say which way the wire arrives
|
|
391
|
+
* at the grid, though, and that is what decides whether it goes straight through the vertex
|
|
392
|
+
* where it meets it — see {@link RouteGrid#through_h}.
|
|
393
|
+
*
|
|
394
|
+
* @param {number} index wire
|
|
395
|
+
* @param {WireRoute} route
|
|
396
|
+
* @param {number} delta 1 to claim, -1 to give back
|
|
397
|
+
* @returns {void}
|
|
398
|
+
*/
|
|
399
|
+
occupy(index, route, delta) {
|
|
400
|
+
const grid = this.grid;
|
|
401
|
+
|
|
402
|
+
const nx = grid.nx;
|
|
403
|
+
|
|
404
|
+
const path = route.path;
|
|
405
|
+
|
|
406
|
+
const last = path.length - 1;
|
|
407
|
+
|
|
408
|
+
const net = this.net[index];
|
|
409
|
+
|
|
410
|
+
// the axis the route is on as it arrives at each vertex, beginning with the stub's
|
|
411
|
+
let arriving = this.start_axis[index];
|
|
412
|
+
|
|
413
|
+
for (let i = 0; i <= last; i++) {
|
|
414
|
+
const a = path[i];
|
|
415
|
+
|
|
416
|
+
let leaving;
|
|
417
|
+
|
|
418
|
+
if (i === last) {
|
|
419
|
+
leaving = this.goal_axis[index];
|
|
420
|
+
} else {
|
|
421
|
+
const b = path[i + 1];
|
|
422
|
+
|
|
423
|
+
if (b === a + 1) {
|
|
424
|
+
leaving = ROUTE_AXIS_H;
|
|
425
|
+
grid.claim_h(a, net, delta);
|
|
426
|
+
} else if (a === b + 1) {
|
|
427
|
+
leaving = ROUTE_AXIS_H;
|
|
428
|
+
grid.claim_h(b, net, delta);
|
|
429
|
+
} else if (b === a + nx) {
|
|
430
|
+
leaving = ROUTE_AXIS_V;
|
|
431
|
+
grid.claim_v(a, net, delta);
|
|
432
|
+
} else {
|
|
433
|
+
leaving = ROUTE_AXIS_V;
|
|
434
|
+
grid.claim_v(b, net, delta);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (leaving === arriving) {
|
|
439
|
+
if (leaving === ROUTE_AXIS_H) {
|
|
440
|
+
grid.through_h[a] += delta;
|
|
441
|
+
} else {
|
|
442
|
+
grid.through_v[a] += delta;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
arriving = leaving;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Route a wire as a chain of searches through the given waypoints, of which there may be none.
|
|
452
|
+
*
|
|
453
|
+
* @param {RouteSearch} search
|
|
454
|
+
* @param {number} index wire
|
|
455
|
+
* @param {NodeGraphLayoutOptions} options
|
|
456
|
+
* @param {number} first index into {@link waypoint}
|
|
457
|
+
* @param {number} last exclusive
|
|
458
|
+
* @returns {WireRoute|null}
|
|
459
|
+
* @private
|
|
460
|
+
*/
|
|
461
|
+
__route_legs(search, index, options, first, last) {
|
|
462
|
+
const legs = last - first + 1;
|
|
463
|
+
|
|
464
|
+
const leg = new Int32Array(legs + 1);
|
|
465
|
+
|
|
466
|
+
let path = null;
|
|
467
|
+
let length = 0;
|
|
468
|
+
let cost = 0;
|
|
469
|
+
|
|
470
|
+
let at = this.start_vertex[index];
|
|
471
|
+
let axis = this.start_axis[index];
|
|
472
|
+
|
|
473
|
+
for (let k = 0; k < legs; k++) {
|
|
474
|
+
const final = k === legs - 1;
|
|
475
|
+
|
|
476
|
+
const goal = final ? this.goal_vertex[index] : this.waypoint[first + k];
|
|
477
|
+
const goal_axis = final ? this.goal_axis[index] : ROUTE_AXIS_H;
|
|
478
|
+
|
|
479
|
+
if (!search.find(at, axis, goal, goal_axis, options, final, this.net[index])) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const found = search.path;
|
|
484
|
+
const found_length = search.path_length;
|
|
485
|
+
|
|
486
|
+
if (path === null) {
|
|
487
|
+
path = found.slice(0, found_length);
|
|
488
|
+
length = found_length;
|
|
489
|
+
} else {
|
|
490
|
+
// the leg begins where the last one ended, and that vertex is already in
|
|
491
|
+
const grown = new Int32Array(length + found_length - 1);
|
|
492
|
+
|
|
493
|
+
grown.set(path.subarray(0, length));
|
|
494
|
+
grown.set(found.subarray(1, found_length), length);
|
|
495
|
+
|
|
496
|
+
path = grown;
|
|
497
|
+
length = grown.length;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
leg[k + 1] = length - 1;
|
|
501
|
+
|
|
502
|
+
cost += search.cost;
|
|
503
|
+
|
|
504
|
+
at = goal;
|
|
505
|
+
axis = ROUTE_AXIS_H;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return new WireRoute(path, leg, cost);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Work out where one end of a wire meets the grid.
|
|
514
|
+
*
|
|
515
|
+
* A wire does not start at its port, it starts a clearance away from the box on the side the port
|
|
516
|
+
* is on — the piece between the two is a straight stub, which is what makes it obvious which port
|
|
517
|
+
* the wire belongs to. That stub is also where the wire's direction comes from: a port on the right
|
|
518
|
+
* of a box is left horizontally, whatever the wire does afterwards.
|
|
519
|
+
*
|
|
520
|
+
* @param {LayoutProblem} problem
|
|
521
|
+
* @param {RouteGrid} grid
|
|
522
|
+
* @param {NodeGraphLayoutOptions} options
|
|
523
|
+
* @param {number} index connection
|
|
524
|
+
* @param {boolean} leaving
|
|
525
|
+
* @param {Int32Array} vertex written
|
|
526
|
+
* @param {Uint8Array} axis written
|
|
527
|
+
* @param {{port_x: Float64Array, port_y: Float64Array, escape_x: Float64Array, escape_y: Float64Array}} terminal
|
|
528
|
+
* written, two entries per connection
|
|
529
|
+
* @returns {void}
|
|
530
|
+
*/
|
|
531
|
+
function write_terminal(problem, grid, options, index, leaving, vertex, axis, terminal) {
|
|
532
|
+
const boxes = problem.boxes;
|
|
533
|
+
|
|
534
|
+
const box = leaving ? problem.from_box[index] : problem.to_box[index];
|
|
535
|
+
const side = leaving ? problem.from_side[index] : problem.to_side[index];
|
|
536
|
+
|
|
537
|
+
const x = boxes.box_x[box] + (leaving ? problem.from_dx[index] : problem.to_dx[index]);
|
|
538
|
+
const y = boxes.box_y[box] + (leaving ? problem.from_dy[index] : problem.to_dy[index]);
|
|
539
|
+
|
|
540
|
+
const at = index * 2 + (leaving ? 0 : 1);
|
|
541
|
+
|
|
542
|
+
terminal.port_x[at] = x;
|
|
543
|
+
terminal.port_y[at] = y;
|
|
544
|
+
|
|
545
|
+
const clearance = options.clearance;
|
|
546
|
+
|
|
547
|
+
let escape_x = x;
|
|
548
|
+
let escape_y = y;
|
|
549
|
+
|
|
550
|
+
switch (side) {
|
|
551
|
+
case LAYOUT_SIDE_LEFT:
|
|
552
|
+
escape_x = boxes.box_x[box] - clearance;
|
|
553
|
+
break;
|
|
554
|
+
case LAYOUT_SIDE_RIGHT:
|
|
555
|
+
escape_x = boxes.box_x[box] + boxes.box_w[box] + clearance;
|
|
556
|
+
break;
|
|
557
|
+
case LAYOUT_SIDE_TOP:
|
|
558
|
+
escape_y = boxes.box_y[box] - clearance;
|
|
559
|
+
break;
|
|
560
|
+
case LAYOUT_SIDE_BOTTOM:
|
|
561
|
+
escape_y = boxes.box_y[box] + boxes.box_h[box] + clearance;
|
|
562
|
+
break;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
terminal.escape_x[at] = escape_x;
|
|
566
|
+
terminal.escape_y[at] = escape_y;
|
|
567
|
+
|
|
568
|
+
vertex[index] = grid.nearest_x(escape_x) + grid.nearest_y(escape_y) * grid.nx;
|
|
569
|
+
|
|
570
|
+
axis[index] = side === LAYOUT_SIDE_TOP || side === LAYOUT_SIDE_BOTTOM ? ROUTE_AXIS_V : ROUTE_AXIS_H;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* One round of asking every wire whether it would rather be somewhere else, now that everything
|
|
575
|
+
* else is routed.
|
|
576
|
+
*
|
|
577
|
+
* Each wire is taken off the grid, asked for its cheapest route through what is left, and put back
|
|
578
|
+
* — on the new route if that is cheaper than the old one under the same grid, on the old one
|
|
579
|
+
* otherwise. The search is exact, so the new route is never dearer; it is refused when it is merely
|
|
580
|
+
* no cheaper, which is what keeps the round from moving wires between routes that tie for ever.
|
|
581
|
+
*
|
|
582
|
+
* Only the wires something has happened to are asked. A wire's route costs what it did when the
|
|
583
|
+
* wire chose it until some other wire comes to cross it or to share a line with it, and a wire
|
|
584
|
+
* whose route still costs what it believed has nothing new to consider: it already took the best
|
|
585
|
+
* route through the grid it was shown, and that grid has not changed along it. What this misses is
|
|
586
|
+
* a wire whose surroundings became *cheaper* — a neighbour that moved away — and the round after a
|
|
587
|
+
* neighbour moves is not the place to chase that; a search is the size of the grid and a wire it
|
|
588
|
+
* would be spent on is one that was already content. Asking everyone once was tried, and moved
|
|
589
|
+
* nothing worth the searches.
|
|
590
|
+
*
|
|
591
|
+
* A wire that has no route at all is asked again too: the grid it failed on is not the one it is
|
|
592
|
+
* being offered now.
|
|
593
|
+
*
|
|
594
|
+
* @param {RouteSearch} search
|
|
595
|
+
* @param {WireSet} wires
|
|
596
|
+
* @param {(WireRoute|null)[]} held current routes, mutated where a wire moves
|
|
597
|
+
* @param {NodeGraphLayoutOptions} options with the present cost to price sharing at
|
|
598
|
+
* @returns {number} how many wires moved
|
|
599
|
+
*/
|
|
600
|
+
function improve(search, wires, held, options) {
|
|
601
|
+
let moved = 0;
|
|
602
|
+
|
|
603
|
+
for (let i = 0; i < held.length; i++) {
|
|
604
|
+
const old = held[i];
|
|
605
|
+
|
|
606
|
+
let old_cost = Infinity;
|
|
607
|
+
|
|
608
|
+
if (old !== null) {
|
|
609
|
+
wires.occupy(i, old, -1);
|
|
610
|
+
|
|
611
|
+
old_cost = wires.cost_of(search, i, old, options);
|
|
612
|
+
|
|
613
|
+
if (old_cost <= old.cost) {
|
|
614
|
+
// nothing has been done to it since it chose this route
|
|
615
|
+
wires.occupy(i, old, 1);
|
|
616
|
+
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
const found = wires.route(search, i, options);
|
|
622
|
+
|
|
623
|
+
if (found !== null && found.cost < old_cost) {
|
|
624
|
+
held[i] = found;
|
|
625
|
+
|
|
626
|
+
moved++;
|
|
627
|
+
} else if (old !== null) {
|
|
628
|
+
// what it has is the best it can do here; remember that, so it is not asked again
|
|
629
|
+
// until something changes
|
|
630
|
+
old.cost = old_cost;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if (held[i] !== null) {
|
|
634
|
+
wires.occupy(i, held[i], 1);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return moved;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Say which wires are still sharing a line with somebody, and how many wires that is.
|
|
643
|
+
*
|
|
644
|
+
* A wire is asked to look again only when some part of its own route is contested — shared with
|
|
645
|
+
* a wire of another net; its own net is welcome. One that is clear of everybody has already found
|
|
646
|
+
* what it wanted, and re-deriving it costs a full search to arrive back where it started.
|
|
647
|
+
*
|
|
648
|
+
* @param {RouteGrid} grid
|
|
649
|
+
* @param {(WireRoute|null)[]} held
|
|
650
|
+
* @param {Int32Array} net of each wire
|
|
651
|
+
* @param {Uint8Array} contested written
|
|
652
|
+
* @returns {number} wires still sharing a line
|
|
653
|
+
*/
|
|
654
|
+
function mark_contested(grid, held, net, contested) {
|
|
655
|
+
const nx = grid.nx;
|
|
656
|
+
|
|
657
|
+
let total = 0;
|
|
658
|
+
|
|
659
|
+
for (let i = 0; i < held.length; i++) {
|
|
660
|
+
const route = held[i];
|
|
661
|
+
|
|
662
|
+
if (route === null) {
|
|
663
|
+
// No route was found for it. Congestion is not what it is waiting for, but the grid it
|
|
664
|
+
// failed on is not the grid the next round presents, so it gets asked again rather than
|
|
665
|
+
// being written off on the strength of one attempt.
|
|
666
|
+
contested[i] = 1;
|
|
667
|
+
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
contested[i] = 0;
|
|
672
|
+
|
|
673
|
+
const path = route.path;
|
|
674
|
+
|
|
675
|
+
for (let k = 0; k + 1 < path.length; k++) {
|
|
676
|
+
const a = path[k];
|
|
677
|
+
const b = path[k + 1];
|
|
678
|
+
|
|
679
|
+
const shared = b === a + 1 ? grid.foreign_h(a, net[i]) > 0
|
|
680
|
+
: a === b + 1 ? grid.foreign_h(b, net[i]) > 0
|
|
681
|
+
: b === a + nx ? grid.foreign_v(a, net[i]) > 0
|
|
682
|
+
: grid.foreign_v(b, net[i]) > 0;
|
|
683
|
+
|
|
684
|
+
if (shared) {
|
|
685
|
+
contested[i] = 1;
|
|
686
|
+
|
|
687
|
+
total++;
|
|
688
|
+
|
|
689
|
+
break;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
return total;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* @param {RouteGrid} grid
|
|
699
|
+
* @param {number} rate
|
|
700
|
+
* @returns {void}
|
|
701
|
+
*/
|
|
702
|
+
function remember(grid, rate) {
|
|
703
|
+
for (let i = 0; i < grid.vertex_count; i++) {
|
|
704
|
+
// a line is fought over when it holds wires beyond those of the net that holds it
|
|
705
|
+
const own_h = Math.max(grid.owned_h[i], 1);
|
|
706
|
+
const own_v = Math.max(grid.owned_v[i], 1);
|
|
707
|
+
|
|
708
|
+
if (grid.use_h[i] > own_h) {
|
|
709
|
+
grid.history_h[i] += rate * (grid.use_h[i] - own_h);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (grid.use_v[i] > own_v) {
|
|
713
|
+
grid.history_v[i] += rate * (grid.use_v[i] - own_v);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|