Skip to content

Commit 5cf07a1

Browse files
alphaditocarson-katri
authored andcommitted
rewrite topological sort, avoiding calls to the expensive 'links' property of the NodeSocket class
1 parent 8a1b4c4 commit 5cf07a1

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

api/arrange.py

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
11
import bpy
22
import typing
3+
from collections import deque
34

45
def _arrange(node_tree, padding: typing.Tuple[float, float] = (50, 25)):
56
# Organize the nodes into columns based on their links.
67
columns: typing.List[typing.List[typing.Any]] = []
7-
def contains_link(node, column):
8-
return any(
9-
any(
10-
any(link.from_node == node for link in input.links)
11-
for input in n.inputs
12-
)
13-
for n in column
14-
)
15-
for node in reversed(node_tree.nodes):
16-
if (x := next(
17-
filter(
18-
lambda x: contains_link(node, x[1]),
19-
enumerate(columns)
20-
),
21-
None
22-
)) is not None:
23-
if x[0] > 0:
24-
columns[x[0] - 1].append(node)
25-
else:
26-
columns.insert(x[0], [node])
8+
9+
def topo_sort(graph):
10+
in_degree = {u: 0 for u in graph}
11+
for u in graph:
12+
for v in graph[u]:
13+
in_degree[v] += 1
14+
queue = deque([u for u in in_degree if in_degree[u] == 0])
15+
topo_order = []
16+
while queue:
17+
u = queue.popleft()
18+
topo_order.append(u)
19+
for v in graph[u]:
20+
in_degree[v] -= 1
21+
if in_degree[v] == 0:
22+
queue.append(v)
23+
return topo_order
24+
25+
graph = { node:set() for node in node_tree.nodes }
26+
for link in node_tree.links:
27+
graph[link.from_node].add(link.to_node)
28+
sorted_nodes = topo_sort(graph)
29+
30+
column_index = {}
31+
for node in reversed(sorted_nodes):
32+
column_index[node] = max([ column_index[node] for node in graph[node] ], default=-1) + 1
33+
if column_index[node] == len(columns):
34+
columns.append([node])
2735
else:
28-
if len(columns) == 0:
29-
columns.append([node])
30-
else:
31-
columns[len(columns) - 1].append(node)
36+
columns[column_index[node]].append(node)
37+
columns = reversed(columns)
3238

3339
# Arrange the columns, computing the size of the node manually so arrangement can be done without UI being visible.
3440
UI_SCALE = bpy.context.preferences.view.ui_scale

0 commit comments

Comments
 (0)