Files
AnyImage/tools/node_assets/cutout_layout.py
nan 196b964efc Add cutout shell and volume node assets for depth volume processing
- Implemented `cutout_shell.py` to build front normals and shell positions for balloon geometry.
- Created `cutout_volume.py` to establish smooth center fields and manage balloon surface attributes.
- Introduced `pisa_sr_export.py` for exporting PiSA-SR components with dependencies and asset finalization.
2026-09-08 17:18:03 +08:00

54 lines
2.4 KiB
Python

"""Place independent Cutout stages using authored local layouts."""
from collections import Counter
def route_geometry(group, source, positions):
"""Guide a shared forward geometry reference through authored waypoints."""
for position in positions:
reroute = group.nodes.new("NodeReroute")
reroute.location = position
group.links.new(source, reroute.inputs[0])
source = reroute.outputs[0]
return source
def layout_stage(group, previous, positions, input_regions, offset=(0, 0)):
"""Map stage-local default names without renaming Blender nodes."""
counts, stage = Counter(), {}
for node in group.nodes:
if node in previous or node.bl_idname == "NodeGroupInput":
continue
base, dot, suffix = node.name.rpartition(".")
base = base if dot and suffix.isdigit() else node.name
index = counts[base]
counts[base] += 1
stage[base if index == 0 else f"{base}.{index:03d}"] = node
assert set(stage) == set(positions) - {"Set Shade Smooth", "Group Output"}, (group.name, set(stage) ^ set(positions))
for name, node in stage.items():
x, y = positions[name]
node.location = (x + offset[0], y + offset[1])
inputs = [(link.to_socket, link.from_socket.name) for link in group.links if link.to_node in stage.values() and link.from_node.bl_idname == "NodeGroupInput"]
for targets, (x, y) in input_regions:
sockets = [(socket, name) for socket, name in inputs if socket.node in [stage[key] for key in targets if key in stage]]
if not sockets:
continue
control = group.nodes.new("NodeGroupInput")
control.location = (x + offset[0], y + offset[1])
for socket, name in sockets:
group.links.new(control.outputs[name], socket)
return stage
def finish_layout(group):
"""Expose linked fields and retain readable constants."""
for node in group.nodes:
node.select = False
node.width = 200 if "Attribute" in node.bl_idname else 160
if node.bl_idname in {"ShaderNodeMath", "ShaderNodeVectorMath"}:
node.hide = all(socket.is_linked for socket in node.inputs if socket.enabled and not socket.hide)
for socket in node.outputs:
socket.hide = not socket.is_linked
for node in list(group.nodes):
if node.bl_idname == "NodeGroupInput" and not any(socket.is_linked for socket in node.outputs):
group.nodes.remove(node)