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:
2026-09-12 12:19:07 +08:00
parent dd32ccdc44
commit 5b2dc59f79
57 changed files with 2253 additions and 700 deletions

View File

@@ -155,7 +155,7 @@ def test_plane_edge_smoothing_preserves_uvs_and_closes_thickness(source):
from tests.support.planes import create_surface, evaluated as plane_mesh
obj, set_value, _, inputs, image = create_surface(source, "DEPTH")
assert inputs["Boundary Smooth"].default_value == 5
assert inputs["Boundary Smooth"].default_value == 2
assert inputs["Boundary Smooth"].parent.name == "Options"
pixels = np.array(image.pixels[:], np.float32).reshape(8, 16, 4)
yy, xx = np.mgrid[:8, :16]
@@ -216,15 +216,18 @@ def test_every_split_node_enables_boundary_smoothing_by_default(source):
continue
split_groups.append(group.name)
smooth = inputs["Boundary Smooth"]
assert smooth.default_value == 5
assert (smooth.min_value, smooth.max_value) == (0, 20)
assert smooth.default_value == (5 if group.name == "O Image Depth Panorama" else 2)
assert (smooth.min_value, smooth.max_value) == (1 if "Outline Depth Fix" in inputs else 0, 20)
assert smooth.parent.name == "Options"
assert not {"Depth Blur Iterations", "Depth Band Rings", "Depth Blur Strength", "Skip Inactive Geometry"} & inputs.keys()
depth_mix = next(n for n in group.nodes if n.bl_idname == "ShaderNodeMix"
and n.data_type == "FLOAT" and n.inputs[3].is_linked
and origin_socket(n.inputs[3].links[0].from_socket).node.bl_idname == "GeometryNodeBlurAttribute")
depth_blur = origin_socket(depth_mix.inputs[3].links[0].from_socket).node
assert origin_socket(depth_blur.inputs["Iterations"].links[0].from_socket).name == "Boundary Smooth"
depth_blurs = [n for n in group.nodes if n.bl_idname == "GeometryNodeBlurAttribute"
and n.data_type == "FLOAT" and n.inputs["Iterations"].is_linked
and origin_socket(n.inputs["Iterations"].links[0].from_socket).name == "Boundary Smooth"]
assert len(depth_blurs) == 1
if "Outline Depth Fix" in inputs:
assert inputs["Outline Depth Fix"].default_value == 16
assert origin_socket(depth_blurs[0].inputs["Weight"].links[0].from_socket).node.bl_idname == "GeometryNodeSampleIndex"
continue
depth_bypass = [n for n in group.nodes if n.bl_idname == "GeometryNodeSwitch"
and n.input_type == "FLOAT" and n.inputs["Switch"].is_linked
and origin_socket(n.inputs["Switch"].links[0].from_socket).name == "Boundary Smooth"]