blender-geometry-script/api/arrange.py

61 wiersze
2.4 KiB
Python
Czysty Zwykły widok Historia

import bpy
import typing
def _arrange(node_tree, padding: typing.Tuple[float, float] = (50, 25)):
# Organize the nodes into columns based on their links.
columns: typing.List[typing.List[typing.Any]] = []
def contains_link(node, column):
return any(
any(
any(link.from_node == node for link in input.links)
for input in n.inputs
)
for n in column
)
for node in reversed(node_tree.nodes):
if (x := next(
filter(
lambda x: contains_link(node, x[1]),
enumerate(columns)
),
None
)) is not None:
if x[0] > 0:
columns[x[0] - 1].append(node)
else:
columns.insert(x[0], [node])
else:
if len(columns) == 0:
columns.append([node])
else:
columns[len(columns) - 1].append(node)
# Arrange the columns, computing the size of the node manually so arrangement can be done without UI being visible.
UI_SCALE = bpy.context.preferences.view.ui_scale
NODE_HEADER_HEIGHT = 20
NODE_LINK_HEIGHT = 28
NODE_PROPERTY_HEIGHT = 28
NODE_VECTOR_HEIGHT = 84
x = 0
for col in columns:
largest_width = 0
y = 0
for node in col:
node.update()
input_count = len(list(filter(lambda i: i.enabled, node.inputs)))
output_count = len(list(filter(lambda i: i.enabled, node.outputs)))
parent_props = [prop.identifier for base in type(node).__bases__ for prop in base.bl_rna.properties]
properties_count = len([prop for prop in node.bl_rna.properties if prop.identifier not in parent_props])
unset_vector_count = len(list(filter(lambda i: i.enabled and i.type == 'VECTOR' and len(i.links) == 0, node.inputs)))
node_height = (
NODE_HEADER_HEIGHT \
+ (output_count * NODE_LINK_HEIGHT) \
+ (properties_count * NODE_PROPERTY_HEIGHT) \
+ (input_count * NODE_LINK_HEIGHT) \
+ (unset_vector_count * NODE_VECTOR_HEIGHT)
) * UI_SCALE
if node.width > largest_width:
largest_width = node.width
node.location = (x, y)
y -= node_height + padding[1]
x += largest_width + padding[0]