- Implemented the "O Image Relief Plane" Geometry Nodes group to create a fixed-base image relief using depth images and various parameters. - Created the "O Shadeless" shader node group to display color without scene lighting while preserving shadows and reflections. - Introduced a preview feature for node groups, allowing for interactive visualization of node arrangements in an HTML format. - Added a template HTML file for rendering node previews with customizable views and controls.
107 lines
3.6 KiB
Python
107 lines
3.6 KiB
Python
"""Build interfaces and basic nodes shared by asset definitions."""
|
|
from types import SimpleNamespace
|
|
|
|
|
|
def prepare_node_group(node_group):
|
|
"""Hide unused outputs and discard disconnected interface nodes."""
|
|
for node in list(node_group.nodes):
|
|
for socket in node.outputs:
|
|
socket.hide = not socket.is_linked
|
|
if node.bl_idname == "NodeGroupInput" and not any(socket.is_linked for socket in node.outputs):
|
|
node_group.nodes.remove(node)
|
|
|
|
|
|
def interface_socket(group, name, in_out, socket_type, parent=None):
|
|
socket = group.interface.new_socket(
|
|
name=name,
|
|
in_out=in_out,
|
|
socket_type=socket_type,
|
|
parent=parent,
|
|
)
|
|
if in_out == "INPUT" and hasattr(socket, "structure_type"):
|
|
socket.structure_type = "SINGLE"
|
|
return socket
|
|
|
|
|
|
def group_input(nodes, visible_names):
|
|
node = nodes.new("NodeGroupInput")
|
|
visible = set(visible_names)
|
|
for output in node.outputs:
|
|
output.hide = output.name not in visible
|
|
return node
|
|
|
|
|
|
def float_input(
|
|
group,
|
|
name,
|
|
default,
|
|
minimum=0.0,
|
|
maximum=None,
|
|
subtype=None,
|
|
parent=None,
|
|
):
|
|
socket = interface_socket(group, name, "INPUT", "NodeSocketFloat", parent)
|
|
socket.default_value = default
|
|
socket.min_value = minimum
|
|
if maximum is not None:
|
|
socket.max_value = maximum
|
|
if subtype is not None:
|
|
socket.subtype = subtype
|
|
return socket
|
|
|
|
|
|
def bool_input(group, name, default=False, parent=None):
|
|
socket = interface_socket(group, name, "INPUT", "NodeSocketBool", parent)
|
|
socket.default_value = default
|
|
return socket
|
|
|
|
|
|
def vector_input(group, name, default, subtype=None, parent=None):
|
|
socket = interface_socket(group, name, "INPUT", "NodeSocketVector", parent)
|
|
socket.default_value = default
|
|
if subtype is not None:
|
|
socket.subtype = subtype
|
|
return socket
|
|
|
|
|
|
def math_node(nodes, operation):
|
|
node = nodes.new("ShaderNodeMath")
|
|
node.operation = operation
|
|
return node
|
|
|
|
|
|
def menu_switch(group, control, names, kind):
|
|
selector = next((node for node in group.nodes if node.bl_idname == "GeometryNodeMenuSwitch" and node.inputs["Menu"].is_linked and node.inputs["Menu"].links[0].from_socket.name == control), None)
|
|
if selector is None:
|
|
selector = group.nodes.new("GeometryNodeMenuSwitch")
|
|
selector.data_type = "BOOLEAN"
|
|
for item, name in zip(selector.enum_items, names):
|
|
item.name = name
|
|
selector.inputs[names[0]].default_value = False
|
|
selector.inputs[names[1]].default_value = True
|
|
local = group_input(group.nodes, {control})
|
|
group.links.new(local.outputs[control], selector.inputs["Menu"])
|
|
node = group.nodes.new("GeometryNodeSwitch")
|
|
node.input_type = kind
|
|
group.links.new(selector.outputs[0], node.inputs["Switch"])
|
|
return SimpleNamespace(inputs={names[0]: node.inputs["False"], names[1]: node.inputs["True"]}, outputs=node.outputs)
|
|
|
|
|
|
def read_float_attribute(group, name):
|
|
node = group.nodes.new("GeometryNodeInputNamedAttribute")
|
|
node.data_type = "FLOAT"
|
|
node.inputs["Name"].default_value = name
|
|
return node.outputs["Attribute"]
|
|
|
|
|
|
def store_float_attribute(group, geometry, name, value, domain="POINT"):
|
|
node = group.nodes.new("GeometryNodeStoreNamedAttribute")
|
|
node.domain, node.data_type = domain, "FLOAT"
|
|
node.inputs["Name"].default_value = name
|
|
group.links.new(geometry, node.inputs["Geometry"])
|
|
if isinstance(value, (int, float)):
|
|
node.inputs["Value"].default_value = value
|
|
else:
|
|
group.links.new(value, node.inputs["Value"])
|
|
return node.outputs["Geometry"]
|