Files
EVEngine/modelconverter/scripts/build_nodegroup_blend.py
T

105 lines
4.0 KiB
Python

"""Build the demo geometry-node converter's .blend inside Blender.
Run once with your Blender:
blender --background --python modelconverter/scripts/build_nodegroup_blend.py
Creates `modelconverter/converters/gn_displace/gn_displace.blend` containing a
Geometry Node group named `EVE_Displace` (displaces a mesh along its normals by
a seeded noise field). The `gn_displace` converter appends and applies it.
"""
from __future__ import annotations
import os
import sys
import bpy
def make_displace_group(name: str = "EVE_Displace") -> None:
if name in bpy.data.node_groups:
bpy.data.node_groups.remove(bpy.data.node_groups[name])
group = bpy.data.node_groups.new(name=name, type="GeometryNodeTree")
group.is_modifier = True
# Keep the group in the saved file even though no object references it yet.
group.use_fake_user = True
# --- node group interface (Blender 4.x) ---
try:
group.interface.new_socket(name="Geometry", in_out="INPUT",
socket_type="NodeSocketGeometry")
group.interface.new_socket(name="Strength", in_out="INPUT",
socket_type="NodeSocketFloat")
group.interface.new_socket(name="Seed", in_out="INPUT",
socket_type="NodeSocketInt")
group.interface.new_socket(name="Geometry", in_out="OUTPUT",
socket_type="NodeSocketGeometry")
except AttributeError:
# Fallback for older Blender node-tree interface.
in_geom = group.inputs.new("NodeSocketGeometry", "Geometry")
in_strength = group.inputs.new("NodeSocketFloat", "Strength")
in_seed = group.inputs.new("NodeSocketInt", "Seed")
group.outputs.new("NodeSocketGeometry", "Geometry")
in_strength.default_value = 0.4
in_seed.default_value = 1
nodes = group.nodes
group_input = nodes.new("NodeGroupInput")
group_output = nodes.new("NodeGroupOutput")
group_input.location = (-800, 0)
group_output.location = (600, 0)
position = nodes.new("GeometryNodeInputPosition")
position.location = (-500, 200)
noise = nodes.new("ShaderNodeTexNoise")
noise.location = (-500, -40)
noise.inputs["Scale"].default_value = 3.0
try:
noise.seed = 1
except AttributeError:
pass
# strength scalar = Strength * noise Fac
mult = nodes.new("ShaderNodeMath")
mult.operation = "MULTIPLY"
mult.location = (-120, 20)
# offset = position vector scaled by strength scalar
scale_vec = nodes.new("ShaderNodeVectorMath")
scale_vec.operation = "SCALE"
scale_vec.location = (140, 0)
set_pos = nodes.new("GeometryNodeSetPosition")
set_pos.location = (380, 0)
links = group.links
# Use index-based sockets: group_input.outputs order follows the interface
# (Geometry, Strength, Seed); node socket orders are stable in Blender 4.x/5.x.
links.new(group_input.outputs[0], set_pos.inputs[0]) # Geometry
links.new(position.outputs[0], scale_vec.inputs[0]) # Position -> Vector
links.new(noise.outputs[0], mult.inputs[0]) # noise Fac -> value
links.new(group_input.outputs[1], mult.inputs[1]) # Strength -> value
links.new(mult.outputs[0], scale_vec.inputs[1]) # value -> Scale
links.new(scale_vec.outputs[0], set_pos.inputs[3]) # Vector -> Offset
links.new(group_input.outputs[2], noise.inputs[1]) # Seed -> W
links.new(set_pos.outputs[0], group_output.inputs[0]) # Geometry
def main() -> int:
make_displace_group("EVE_Displace")
here = os.path.dirname(os.path.abspath(__file__))
converter_dir = os.path.abspath(
os.path.join(here, os.pardir, "converters", "gn_displace"))
os.makedirs(converter_dir, exist_ok=True)
out = os.path.join(converter_dir, "gn_displace.blend")
bpy.ops.wm.save_as_mainfile(filepath=out)
print(f"wrote {out}")
return 0
if __name__ == "__main__":
sys.exit(main())