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

@@ -51,7 +51,6 @@ def expand_smooth(
repeat_output = nodes.new("GeometryNodeRepeatOutput")
repeat_input = nodes.new("GeometryNodeRepeatInput")
repeat_input.pair_with_output(repeat_output)
repeat_output.repeat_items.new("GEOMETRY", "Geometry")
links.new(
iteration_controls.outputs[iterations_name],
repeat_input.inputs["Iterations"],
@@ -109,11 +108,6 @@ def expand_smooth(
links.new(boundary_points.outputs["Value"], choose_boundary.inputs["Switch"])
links.new(smooth_all.outputs["Value"], choose_boundary.inputs["False"])
links.new(sample_boundary.outputs["Value"], choose_boundary.inputs["True"])
boundary_mix = nodes.new("ShaderNodeMix")
boundary_mix.data_type = "VECTOR"
boundary_mix.inputs[0].default_value = 1.0
links.new(smooth_all.outputs["Value"], boundary_mix.inputs[4])
links.new(choose_boundary.outputs["Output"], boundary_mix.inputs[5])
weight = weight_controls.outputs[weight_name]
if pin_sharp:
@@ -126,15 +120,10 @@ def expand_smooth(
normal_coherence = nodes.new("ShaderNodeVectorMath")
normal_coherence.operation = "LENGTH"
links.new(smooth_normal.outputs["Value"], normal_coherence.inputs[0])
sharp_switch = nodes.new("GeometryNodeSwitch")
sharp_switch.input_type = "FLOAT"
sharp_switch.inputs["Switch"].default_value = pin_sharp
sharp_switch.inputs["False"].default_value = 1.0
links.new(normal_coherence.outputs["Value"], sharp_switch.inputs["True"])
smooth_weight = nodes.new("ShaderNodeMath")
smooth_weight.operation = "MULTIPLY"
links.new(weight_controls.outputs[weight_name], smooth_weight.inputs[0])
links.new(sharp_switch.outputs["Output"], smooth_weight.inputs[1])
links.new(normal_coherence.outputs["Value"], smooth_weight.inputs[1])
weight = smooth_weight.outputs[0]
if influence is not None:
masked_weight = nodes.new("ShaderNodeMath")
@@ -143,17 +132,12 @@ def expand_smooth(
links.new(influence, masked_weight.inputs[1])
weight = masked_weight.outputs[0]
target_position = nodes.new("GeometryNodeSwitch")
target_position.input_type = "VECTOR"
target_position.inputs["Switch"].default_value = True
links.new(smooth_all.outputs["Value"], target_position.inputs["False"])
links.new(boundary_mix.outputs["Result"], target_position.inputs["True"])
current_position = nodes.new("GeometryNodeInputPosition")
mix_position = nodes.new("ShaderNodeMix")
mix_position.data_type = "VECTOR"
links.new(weight, mix_position.inputs[0])
links.new(current_position.outputs["Position"], mix_position.inputs[4])
links.new(target_position.outputs["Output"], mix_position.inputs[5])
links.new(choose_boundary.outputs["Output"], mix_position.inputs[5])
set_position = nodes.new("GeometryNodeSetPosition")
links.new(repeat_input.outputs["Geometry"], set_position.inputs["Geometry"])
links.new(mix_position.outputs["Result"], set_position.inputs["Position"])