Automatic layout of Blender node trees
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arrangebpy-0.1.0.tar.gz.
File metadata
- Download URL: arrangebpy-0.1.0.tar.gz
- Upload date:
- Size: 63.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
230f57781838889aa2a10c71cea2d435eb0b27bf13fdcfe5ec22e093b36bafe6
|
|
| MD5 |
b118f8fb0f54f101eeda9f749d02efee
|
|
| BLAKE2b-256 |
d7fdd11c47a133f09e76d252497ee223c22de7ab53f056b78e3cb66774ffa306
|
Provenance
The following attestation bundles were made for arrangebpy-0.1.0.tar.gz:
Publisher:
pypi.yml on BradyAJohnston/arrangebpy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arrangebpy-0.1.0.tar.gz -
Subject digest:
230f57781838889aa2a10c71cea2d435eb0b27bf13fdcfe5ec22e093b36bafe6 - Sigstore transparency entry: 828910643
- Sigstore integration time:
-
Permalink:
BradyAJohnston/arrangebpy@9facd9704040065ecf349c8c83a1b29653b3ee5c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/BradyAJohnston
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@9facd9704040065ecf349c8c83a1b29653b3ee5c -
Trigger Event:
push
-
Statement type:
File details
Details for the file arrangebpy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: arrangebpy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 67.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce383bb51bf95b8c7c70a2b0b2197f782a8e9ede2bacb18616f87077e5f05bfd
|
|
| MD5 |
a44d5a026ea670312bbfb3f81d1f5c39
|
|
| BLAKE2b-256 |
06183eee56801d93e678c07cdf39aaad81513f4fb8572244e0b0178cc383e3bf
|
Provenance
The following attestation bundles were made for arrangebpy-0.1.0-py3-none-any.whl:
Publisher:
pypi.yml on BradyAJohnston/arrangebpy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arrangebpy-0.1.0-py3-none-any.whl -
Subject digest:
ce383bb51bf95b8c7c70a2b0b2197f782a8e9ede2bacb18616f87077e5f05bfd - Sigstore transparency entry: 828910673
- Sigstore integration time:
-
Permalink:
BradyAJohnston/arrangebpy@9facd9704040065ecf349c8c83a1b29653b3ee5c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/BradyAJohnston
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@9facd9704040065ecf349c8c83a1b29653b3ee5c -
Trigger Event:
push
-
Statement type: