Files
AnyImage/tools/nodes/arrangement/sources.py
nan 5b2dc59f79 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.
2026-09-12 12:19:07 +08:00

39 lines
2.0 KiB
Python

"""Place shared calculation sources beside their peripheral distribution channels."""
def place_shared_sources(bodies, peripheral_nodes, positions, sizes, *, gap):
"""Place consumer regions first, then keep their producers outside and to the left."""
ordinary = [box for members, box in bodies if not members & peripheral_nodes]
if not ordinary:
ordinary = [(x, x + sizes[node].width, y, y - sizes[node].height)
for node, (x, y) in positions.items() if node not in peripheral_nodes]
ceiling = max(box[2] for box in ordinary)
floor = min(box[3] for box in ordinary)
for index, (members, (left, right, top, bottom)) in enumerate(bodies):
if not members & peripheral_nodes:
continue
links = [link for node in members for socket in node.outputs for link in socket.links
if link.to_node not in members and link.to_node in positions]
if not links:
continue
height = top - bottom
candidates = (ceiling + gap * 2 + height, floor - gap * 2)
new_top = min(candidates, key=lambda level: (sum(
abs(positions[link.to_node][1] - level + height / 2) for link in links), -level))
dy = new_top - top
new_left = float("inf")
for link in links:
source, target = link.from_node, link.to_node
source_y = positions[source][1] + dy - sizes[source].sockets[link.from_socket]
target_y = positions[target][1] - sizes[target].sockets[link.to_socket]
runway = (abs(source_y - target_y) + height * 2) * 0.8 + gap * 3
new_left = min(new_left, positions[target][0] - runway
- (positions[source][0] - left) - sizes[source].width)
dx = new_left - left
for node in members:
x, y = positions[node]
positions[node] = (x + dx, y + dy)
bodies[index] = (members, (left + dx, right + dx, top + dy, bottom + dy))
ceiling = max(ceiling, top + dy)
floor = min(floor, bottom + dy)