- 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.
39 lines
2.0 KiB
Python
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)
|