Files
nan 198fcbf55b
Some checks failed
Test / test (push) Has been cancelled
Initial public release
2026-09-19 21:31:36 +08:00

43 lines
1.9 KiB
Python

"""Identify paired execution zones and their exclusive input calculations."""
from graphlib import TopologicalSorter
def repeat_regions(node_group, positions, sizes):
"""Bound repeat execution and calculations without peripheral routing corners."""
regions = []
for entry, end, members in node_zones(node_group):
if entry.bl_idname != "GeometryNodeRepeatInput":
continue
nodes = {node for node in members if node.bl_idname not in {"NodeReroute", "NodeFrame"}}
regions.append((members, (positions[entry][0] - 60,
positions[end][0] + sizes[end].width + 60,
max(positions[node][1] for node in nodes) + 60,
min(positions[node][1] - sizes[node].height for node in nodes) - 40)))
return regions
def node_zones(node_group):
"""Return each paired entry, exit, and its data-dependent node membership."""
parents = {node: set() for node in node_group.nodes}
children = {node: set() for node in node_group.nodes}
for link in node_group.links:
parents[link.to_node].add(link.from_node)
children[link.from_node].add(link.to_node)
order = list(TopologicalSorter(parents).static_order())
ancestors = {}
for node in order:
ancestors[node] = parents[node] | set().union(*(ancestors[parent] for parent in parents[node]))
zones = []
for entry in order:
end = getattr(entry, "paired_output", None)
if end is None:
continue
members = {node for node in ancestors[end] if entry in ancestors[node]} | {entry, end}
for node in reversed(order):
if (node not in members and node in ancestors[end] and children[node]
and children[node] <= members and entry not in children[node]):
members.add(node)
zones.append((entry, end, members))
return zones