Implement arrangement framework for node groups
- Introduced `frames.py` to manage field complex calculations and their arrangement within node groups. - Added functionality to create and remove field frames based on node arrangements. - Developed `passages.py` to find unobstructed paths for connections around calculation frames. - Implemented `references.py` to route shared results on peripheral tracks, ensuring efficient distribution of outputs. - Created `sections.py` to reserve space for field calculations adjacent to geometry consumers. - Added `sources.py` to position shared calculation sources effectively beside their distribution channels. - Enhanced outline smoothing with `outline_smoothing.py` to adapt camera depth along original outlines.
This commit is contained in:
@@ -9,7 +9,7 @@ import bpy
|
||||
from ..arrangement.dimensions import estimate_node_dimensions
|
||||
from ..arrangement.flow import node_roles
|
||||
from ..arrangement.connections import link_endpoints
|
||||
from ..arrangement.zones import node_zones
|
||||
from ..arrangement.zones import node_zones, repeat_regions
|
||||
|
||||
|
||||
def _display_value(value):
|
||||
@@ -30,7 +30,7 @@ def _display_value(value):
|
||||
|
||||
|
||||
def _node_group_data(node_group):
|
||||
nodes = list(node_group.nodes)
|
||||
nodes = [node for node in node_group.nodes if node.bl_idname != "NodeFrame"]
|
||||
ids = {node: index for index, node in enumerate(nodes)}
|
||||
dimensions = {node: estimate_node_dimensions(node) for node in nodes}
|
||||
roles = node_roles(node_group)
|
||||
@@ -56,28 +56,39 @@ def _node_group_data(node_group):
|
||||
sockets.append([socket.name, round(offset, 2), int(socket.is_output), socket.type, default])
|
||||
records.append({"id": ids[node], "name": node.name, "title": title,
|
||||
"type": node.bl_idname, "role": roles[node],
|
||||
"x": round(node.location.x, 2), "y": round(-node.location.y, 2),
|
||||
"x": round(node.location_absolute.x, 2), "y": round(-node.location_absolute.y, 2),
|
||||
"w": size.width, "h": size.height, "folded": bool(node.hide),
|
||||
"settings": settings, "sockets": sockets})
|
||||
links = []
|
||||
positions = {node: tuple(node.location) for node in nodes}
|
||||
positions = {node: tuple(node.location_absolute) for node in nodes}
|
||||
for link in node_group.links:
|
||||
source, target = link.from_node, link.to_node
|
||||
(x1, y1), (x2, y2) = link_endpoints(link, positions, dimensions)
|
||||
links.append([ids[source], ids[target], *[round(v, 2) for v in (x1, -y1, x2, -y2)], link.from_socket.type])
|
||||
zones = []
|
||||
repeats = {frozenset(members): box for members, box in repeat_regions(node_group, positions, dimensions)}
|
||||
for entry, end, members in node_zones(node_group):
|
||||
if entry.bl_idname != "GeometryNodeRepeatInput":
|
||||
members = {node for node in members if roles[node] == "geometry"} | {entry, end}
|
||||
boxes = [records[ids[node]] for node in members]
|
||||
left = min(node["x"] for node in boxes) - 40
|
||||
padding = 60 if entry.bl_idname == "GeometryNodeRepeatInput" else 40
|
||||
left = min(node["x"] for node in boxes) - padding
|
||||
top = min(node["y"] for node in boxes) - 60
|
||||
right = max(node["x"] + node["w"] for node in boxes) + 40
|
||||
right = max(node["x"] + node["w"] for node in boxes) + padding
|
||||
bottom = max(node["y"] + node["h"] for node in boxes) + 40
|
||||
if entry.bl_idname == "GeometryNodeRepeatInput":
|
||||
left, right, upper, lower = repeats[frozenset(members)]
|
||||
top, bottom = -upper, -lower
|
||||
zones.append({"title": entry.bl_label.removesuffix(" Input"),
|
||||
"type": entry.bl_idname, "entry": ids[entry], "exit": ids[end],
|
||||
"nodes": sorted(ids[node] for node in members),
|
||||
"x": left, "y": top, "w": right - left, "h": bottom - top})
|
||||
zones.sort(key=lambda zone: zone["w"] * zone["h"], reverse=True)
|
||||
return {"name": node_group.name, "nodes": records, "links": links, "zones": zones}
|
||||
frames = [{"title": node.label or node.name, "x": node.location_absolute.x,
|
||||
"y": -node.location_absolute.y, "w": node.width, "h": node.height,
|
||||
"nodes": [ids[child] for child in nodes if child.parent == node]}
|
||||
for node in node_group.nodes if node.bl_idname == "NodeFrame"]
|
||||
return {"name": node_group.name, "nodes": records, "links": links, "zones": zones, "frames": frames}
|
||||
|
||||
|
||||
def write_node_preview(node_groups, output_path, *, fragment=False):
|
||||
|
||||
Reference in New Issue
Block a user