Just a short recap… The topic is marked as known issue for now.
After testing many things I decided to manually create the related node setup with some Python code. Of course this is not very flexible when the modifier is changed in the future but on the other hand it works nicely and was a nice exercise for me in scripting geometry nodes…
If anyone is looking for an example feel free to grab ideas from here:
import math
import bpy
from bpy.app.translations import pgettext_data as data_
def create_geometry_node_group(object, name, has_initial_link=True):
"""create_geometry_node_group"""
modifier = object.modifiers.new(name, "NODES")
node_group = bpy.data.node_groups.new(name, "GeometryNodeTree")
node_group.interface.new_socket(data_("Geometry"), in_out="INPUT", socket_type="NodeSocketGeometry")
input_node = node_group.nodes.new("NodeGroupInput")
input_node.select = False
input_node.location.x = -200 - input_node.width
node_group.interface.new_socket(data_("Geometry"), in_out="OUTPUT", socket_type="NodeSocketGeometry")
output_node = node_group.nodes.new("NodeGroupOutput")
output_node.is_active_output = True
output_node.select = False
output_node.location.x = 200
if has_initial_link:
node_group.links.new(node_group.nodes[data_("Group Input")].outputs[0], node_group.nodes[data_("Group Output")].inputs[0])
node_group.is_modifier = True
modifier.node_group = node_group
return modifier, node_group
def add_auto_smooth_geometry_nodes(object, name=None):
"""add_auto_smooth_geometry_nodes"""
if name is None:
name = "Smooth by Angle"
# create empty geometry nodes group
modifier, node_group = create_geometry_node_group(object, name=name, has_initial_link=False)
nodes = node_group.nodes
geom_in = nodes.get(data_("Group Input"))
geom_out = nodes.get(data_("Group Output"))
# set some geometrical layout details
dx = geom_in.width
dy = geom_in.height
x0 = -500
x1 = x0 + 7.5 * dx
# location of the input and output nodes
geom_in.location = (x0, 0)
geom_out.location = (x1, 0)
# new Angle socket for input node
angle_socket = node_group.interface.new_socket(data_("Angle"), in_out="INPUT", socket_type="NodeSocketFloat")
angle_socket.subtype = "ANGLE"
angle_socket.default_value = 30.0 / 180.0 * math.pi
angle_socket.min_value = 0.0
angle_socket.max_value = math.pi
modifier[angle_socket.identifier] = 30.0 / 180.0 * math.pi
# new Sharpness socket for input node
sharpness_socket = node_group.interface.new_socket(data_("Ignore Sharpness"), in_out="INPUT", socket_type="NodeSocketBool")
sharpness_socket.force_non_field = True
# Edge Angle node
node_edge_angle = nodes.new(data_("GeometryNodeInputMeshEdgeAngle"))
node_edge_angle.label = "Edge Angle"
node_edge_angle.location = (x0, 0 - 1.5 * dy)
# Is Face smooth node
node_is_face_smooth = nodes.new(data_("GeometryNodeInputShadeSmooth"))
node_is_face_smooth.label = "Is Face Smooth"
node_is_face_smooth.location = (x0, 0 - 2.5 * dy)
# Is Edge smooth node
node_is_edge_smooth = nodes.new(data_("GeometryNodeInputEdgeSmooth"))
node_is_edge_smooth.label = "Is Edge Smooth"
node_is_edge_smooth.location = (x0 + 0 * dx, 0 + 1.0 * dy)
# Compare less or equal node
node_less_than_or_equal = nodes.new(data_("FunctionNodeCompare"))
node_less_than_or_equal.operation = "LESS_EQUAL"
node_less_than_or_equal.location = (x0 + 1.5 * dx, 0 - 0.5 * dy)
# Boolean OR node
node_or_01 = nodes.new(data_("FunctionNodeBooleanMath"))
node_or_01.operation = "OR"
node_or_01.label = "OR_1"
node_or_01.location = (x0 + 1.5 * dx, 0 - 2.5 * dy)
# Boolean OR node
node_or_02 = nodes.new(data_("FunctionNodeBooleanMath"))
node_or_02.operation = "OR"
node_or_02.label = "OR_2"
node_or_02.location = (x0 + 3 * dx, 0 + 1.5 * dy)
# Boolean AND node
node_and = nodes.new(data_("FunctionNodeBooleanMath"))
node_and.operation = "AND"
node_and.label = "AND"
node_and.location = (x0 + 3 * dx, 0)
# Shade Smooth node
node_set_smooth_edge = nodes.new(data_("GeometryNodeSetShadeSmooth"))
node_set_smooth_edge.label = "Set Shade Smooth (Edge)"
node_set_smooth_edge.domain = "EDGE"
node_set_smooth_edge.location = (x0 + 4.5 * dx, 0)
# Shade Smooth node
node_set_smooth_face = nodes.new(data_("GeometryNodeSetShadeSmooth"))
node_set_smooth_face.label = "Set Shade Smooth (Face)"
node_set_smooth_face.domain = "FACE"
node_set_smooth_face.inputs["Shade Smooth"].default_value = True
node_set_smooth_face.location = (x0 + 6 * dx, 0)
# Linking all the nodes
node_group.links.new(node_edge_angle.outputs["Unsigned Angle"], node_less_than_or_equal.inputs["A"])
node_group.links.new(geom_in.outputs["Angle"], node_less_than_or_equal.inputs["B"])
node_group.links.new(geom_in.outputs["Ignore Sharpness"], node_or_01.inputs[0])
node_group.links.new(node_is_face_smooth.outputs["Smooth"], node_or_01.inputs[1])
node_group.links.new(node_less_than_or_equal.outputs["Result"], node_and.inputs[0])
node_group.links.new(node_or_01.outputs["Boolean"], node_and.inputs[1])
node_group.links.new(node_is_edge_smooth.outputs["Smooth"], node_or_02.inputs[0])
node_group.links.new(geom_in.outputs["Ignore Sharpness"], node_or_02.inputs[1])
node_group.links.new(geom_in.outputs["Geometry"], node_set_smooth_edge.inputs["Geometry"])
node_group.links.new(node_or_02.outputs["Boolean"], node_set_smooth_edge.inputs["Selection"])
node_group.links.new(node_and.outputs["Boolean"], node_set_smooth_edge.inputs["Shade Smooth"])
node_group.links.new(node_set_smooth_edge.outputs["Geometry"], node_set_smooth_face.inputs["Geometry"])
node_group.links.new(node_set_smooth_face.outputs["Geometry"], geom_out.inputs["Geometry"])