- 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.
54 lines
2.4 KiB
Python
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)
|