arrangebpy
Automatic layout of nodes for Blender node trees - A clean, library-focused Python module implementing multiple graph layout algorithms.
Ported from the excellent node-arrange Blender add-on, redesigned as a standalone module for use in other add-ons and tools.
Features
🎨 Multiple Layout Algorithms
- Sugiyama: Hierarchical layout with minimal edge crossings (default)
- Topological: Fast layered layout for quick results
- Grid: Regular grid arrangement, great for organization
- Orthogonal: Clean orthogonal edge routing for presentations
✨ Complete Sugiyama Implementation
- Hierarchical node layout with minimal edge crossings
- Frame-aware layout (respects Blender's node frames)
- Multi-input socket handling
- Reroute node optimization
🎛️ Highly Configurable
- 5 layout directions: Balanced, Left-Up, Right-Down, etc.
- 3 socket alignment modes: None, Moderate, Full
- Node stacking: Automatically stack collapsed math nodes
- Iterative refinement: Better layouts for complex frame hierarchies
- Adjustable spacing: Control horizontal and vertical spacing
🔧 Clean API Design
- Unified
layout()function for all algorithms - Settings-based configuration (no global state)
- Type-safe with full type hints
- Well-documented with examples
- Designed for embedding in other add-ons
Installation
pip install arrangebpy
Or with uv:
uv add arrangebpy
Quick Start
from arrangebpy import layout, LayoutSettings
# Simple usage with defaults (uses Sugiyama)
layout(node_tree)
# Choose a specific algorithm
layout(node_tree, algorithm="topological") # Fast layout
layout(node_tree, algorithm="grid") # Grid layout
layout(node_tree, algorithm="orthogonal") # Orthogonal edges
# Custom settings
from arrangebpy import LayoutSettings
settings = LayoutSettings(
direction="BALANCED",
socket_alignment="MODERATE",
horizontal_spacing=60.0,
vertical_spacing=30.0,
)
layout(node_tree, algorithm="sugiyama", settings=settings)
Legacy API (Still Supported)
from arrangebpy import sugiyama_layout, LayoutSettings
# Direct function calls still work
sugiyama_layout(node_tree)
sugiyama_layout(node_tree, LayoutSettings(horizontal_spacing=60.0))
Layout Algorithms
Sugiyama (Hierarchical)
Best for most node trees. Creates a hierarchical left-to-right layout with minimal edge crossings.
from arrangebpy import layout, LayoutSettings
layout(ntree, algorithm="sugiyama", settings=LayoutSettings(
direction="BALANCED",
socket_alignment="FULL",
stack_collapsed=True, # Stack collapsed math nodes
align_top_layer=True # Align input/output at top
))
Special Feature - Flat Top Layout:
# Align source and sink nodes (input/output) at Y=0, push others below
layout(ntree, algorithm="sugiyama", settings=LayoutSettings(
align_top_layer=True # Clean flat top with I/O aligned
))
Use when: You want the highest quality layout with minimal crossings (shader trees, geometry nodes, etc.)
Topological (Fast Layered)
Quick and simple layered layout without crossing reduction. Much faster than Sugiyama.
from arrangebpy import layout, TopologicalSettings
layout(ntree, algorithm="topological", settings=TopologicalSettings(
horizontal_spacing=60.0,
sort_by_degree=True # Sort nodes by connection count
))
# For perfectly flat horizontal layouts (all nodes at Y=0)
layout(ntree, algorithm="topological", settings=TopologicalSettings(
flatten=True # Perfect for simple linear chains
))
Use when: You need quick layouts during development, have very large graphs, or want a perfectly flat horizontal layout.
Grid
Arranges nodes in a regular grid pattern, optionally grouping by type or cluster.
from arrangebpy import layout, GridSettings
layout(ntree, algorithm="grid", settings=GridSettings(
columns=5,
grouping="TYPE", # Group by node type
cell_width=250.0
))
Use when: You want to organize collections of nodes or create inventory-style layouts.
Orthogonal (Clean Edges)
Uses Sugiyama for node placement but routes edges with only horizontal/vertical segments.
from arrangebpy import layout, OrthogonalSettings
layout(ntree, algorithm="orthogonal", settings=OrthogonalSettings(
horizontal_spacing=80.0, # More space for routing
socket_alignment="FULL"
))
Use when: You need professional-looking layouts for presentations or documentation.
Usage Examples
Default Layout (Sugiyama)
from arrangebpy import layout
# Uses sensible defaults
layout(material.node_tree)
Shader Node Trees (with stacking)
from arrangebpy import LayoutSettings
from arrangebpy.arrange.sugiyama import sugiyama_layout
settings = LayoutSettings(
# Stack collapsed math nodes
stack_collapsed=True,
stack_margin_y_factor=0.4,
# Full socket alignment for cleaner connections
socket_alignment="FULL",
# Balanced direction
direction="BALANCED",
# Tight spacing
horizontal_spacing=50.0,
vertical_spacing=20.0,
)
sugiyama_layout(shader_node_tree, settings)
Geometry Node Trees
settings = LayoutSettings(
# More spacing for larger nodes
horizontal_spacing=70.0,
vertical_spacing=30.0,
# Left-to-right flow
direction="RIGHT_DOWN",
# Moderate socket alignment
socket_alignment="MODERATE",
# High quality layout
iterations=20,
crossing_reduction_sweeps=48,
)
sugiyama_layout(geometry_node_tree, settings)
Configuration
All configuration through the LayoutSettings dataclass:
from arrangebpy import LayoutSettings
settings = LayoutSettings(
# Spacing
horizontal_spacing=50.0, # Horizontal spacing between columns
vertical_spacing=25.0, # Vertical spacing between nodes
# Layout algorithm
direction="BALANCED", # Layout direction
socket_alignment="MODERATE", # Socket alignment mode
iterations=20, # BK algorithm refinement iterations
crossing_reduction_sweeps=24, # Edge crossing minimization passes
# Features
add_reroutes=True, # Add reroute nodes for clean routing
stack_collapsed=False, # Stack collapsed math nodes
stack_margin_y_factor=0.5, # Spacing factor for stacks (0-1)
)
Direction Options
"BALANCED"- Combines all 4 directions (default, best results)"LEFT_DOWN"- Top-left alignment"RIGHT_DOWN"- Bottom-right alignment"LEFT_UP"- Bottom-left alignment"RIGHT_UP"- Top-right alignment
Socket Alignment Options
"NONE"- Only align node tops (fastest)"MODERATE"- Smart alignment based on node heights (default)"FULL"- Always align sockets (cleanest connections)
Use in Blender Add-ons
import bpy
from arrangebpy import LayoutSettings
from arrangebpy.arrange.sugiyama import sugiyama_layout
class MY_OT_ArrangeNodes(bpy.types.Operator):
bl_idname = "node.my_arrange"
bl_label = "Arrange Nodes"
def execute(self, context):
ntree = context.space_data.edit_tree
# Configure based on node tree type
if ntree.bl_idname == 'ShaderNodeTree':
settings = LayoutSettings(
stack_collapsed=True,
socket_alignment="FULL",
)
else:
settings = LayoutSettings()
sugiyama_layout(ntree, settings)
return {'FINISHED'}
How It Works
Implements the Sugiyama hierarchical graph layout framework:
- Graph Construction - Build directed graph from node tree
- Ranking - Assign nodes to horizontal layers
- Crossing Minimization - Reduce edge crossings via median heuristic
- Coordinate Assignment - Place nodes using Brandes-Köpf algorithm
- Edge Routing - Add bend points for clean connections
- Realization - Apply positions back to Blender
Architecture
arrangebpy/
├── settings.py # Configuration
├── arrange/
│ ├── sugiyama.py # Main orchestration
│ ├── graph.py # Graph construction
│ ├── ranking.py # Rank assignment
│ ├── ordering.py # Crossing minimization
│ ├── placement/
│ │ ├── bk.py # Brandes-Köpf algorithm
│ │ └── linear_segments.py
│ ├── coordinates.py # X-coordinate assignment
│ ├── routing.py # Edge routing
│ ├── stacking.py # Node stacking
│ └── ...
└── utils.py
Development
git clone https://github.com/BradyAJohnston/arrangebpy.git
cd arrangebpy
# Install
uv sync
# Run tests
uv run pytest tests/
License
GPL-3.0-or-later
Credits
Based on node-arrange by Leonardo Pike-Excell
Implements algorithms from Sugiyama et al., Brandes & Köpf, and others.
Metadata
Release files for arrangebpy 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| arrangebpy-0.1.0.tar.gz | 63.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| arrangebpy-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 131.1 kB
Release files / arrangebpy-0.1.0.tar.gz
| Download URL | arrangebpy-0.1.0.tar.gz |
|---|---|
| Size | 63.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
230f57781838889aa2a10c71cea2d435eb0b27bf13fdcfe5ec22e093b36bafe6
|
|
BLAKE2b-256 checksum How to use checksums |
d7fdd11c47a133f09e76d252497ee223c22de7ab53f056b78e3cb66774ffa306
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 15, 2026.
Transparency logRelease files / arrangebpy-0.1.0-py3-none-any.whl
| Download URL | arrangebpy-0.1.0-py3-none-any.whl |
|---|---|
| Size | 67.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ce383bb51bf95b8c7c70a2b0b2197f782a8e9ede2bacb18616f87077e5f05bfd
|
|
BLAKE2b-256 checksum How to use checksums |
06183eee56801d93e678c07cdf39aaad81513f4fb8572244e0b0178cc383e3bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 15, 2026.
Transparency log