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:
38
tools/nodes/arrangement/sources.py
Normal file
38
tools/nodes/arrangement/sources.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user