Xinyu_ZHU
(Xinyu ZHU)
December 4, 2024, 8:44am
1
Similiar to question [SOLVED] How can i add a new socket with python to GeometryNodeSimulationOutput? , but I did not see same tricks work for GeometryNodeForeachGeometryElementInput/Output in Blender4.3
I tried
with bpy.context.temp_override(active_node=node, selected_nodes=[node]):
bpy.ops.node.foreach_geometry_element_zone_input_item_add()
No luck
node.inputs.new("BOOL", "new input")
Also not working: RuntimeError: Error: Cannot add socket to built-in node
Any idea how could this be done in Python?
Andrej
(Andrej)
December 4, 2024, 3:20pm
2
It’s interesting. There should some kind of way to access NodeTreeInterface
kind of thing for GeometryNodeForeachGeometryElementInput
to solve it like this https://projects.blender.org/blender/blender/issues/103150#issuecomment-1356203 but there isn’t.
I think your best shot right now is to make the operator work.
The chances are you’re running script either from console or from scripting tab and it could be a reason why it’s not working - in that case try to override area
with the node editor area
. If that won’t work also try to override region
and then space_data
.
Andrej
(Andrej)
December 24, 2024, 4:25pm
3
Okay, I’ve figured it.
It’s not intuitive but ForEach Input node’s inputs located… on the Output node attributes.
See .input_items
on https://docs.blender.org/api/current/bpy.types.GeometryNodeForeachGeometryElementOutput.html , .main_items
is used for Output node inputs. Below is a full example on how they’re used.hasattr
The cool thing is that I’ve found it using https://extensions.blender.org/approval-queue/node-to-python/ .
It’s an addon that converts nodes setup to Python code, so it can be very useful for exploring the API to learn how to recreate some type of node. And it’s generated the code below.
import bpy, mathutils
#initialize geometry_nodes node group
def geometry_nodes_node_group():
geometry_nodes = bpy.data.node_groups.new(type = 'GeometryNodeTree', name = "Geometry Nodes")
geometry_nodes.color_tag = 'NONE'
geometry_nodes.description = ""
geometry_nodes.default_group_node_width = 140
geometry_nodes.is_modifier = True
#geometry_nodes interface
#Socket Geometry
geometry_socket = geometry_nodes.interface.new_socket(name = "Geometry", in_out='OUTPUT', socket_type = 'NodeSocketGeometry')
geometry_socket.attribute_domain = 'POINT'
#Socket Geometry
geometry_socket_1 = geometry_nodes.interface.new_socket(name = "Geometry", in_out='INPUT', socket_type = 'NodeSocketGeometry')
geometry_socket_1.attribute_domain = 'POINT'
#initialize geometry_nodes nodes
#node Group Input
group_input = geometry_nodes.nodes.new("NodeGroupInput")
group_input.name = "Group Input"
#node Group Output
group_output = geometry_nodes.nodes.new("NodeGroupOutput")
group_output.name = "Group Output"
group_output.is_active_output = True
#node For Each Geometry Element Input
for_each_geometry_element_input = geometry_nodes.nodes.new("GeometryNodeForeachGeometryElementInput")
for_each_geometry_element_input.name = "For Each Geometry Element Input"
#node For Each Geometry Element Output
for_each_geometry_element_output = geometry_nodes.nodes.new("GeometryNodeForeachGeometryElementOutput")
for_each_geometry_element_output.name = "For Each Geometry Element Output"
for_each_geometry_element_output.active_generation_index = 0
for_each_geometry_element_output.active_input_index = 0
for_each_geometry_element_output.active_main_index = 0
for_each_geometry_element_output.domain = 'POINT'
for_each_geometry_element_output.generation_items.clear()
for_each_geometry_element_output.generation_items.new('GEOMETRY', "Geometry")
for_each_geometry_element_output.generation_items[0].domain = 'POINT'
for_each_geometry_element_output.input_items.clear()
for_each_geometry_element_output.input_items.new('FLOAT', "test float")
for_each_geometry_element_output.inspection_index = 0
for_each_geometry_element_output.main_items.clear()
for_each_geometry_element_output.main_items.new('FLOAT', "xxxx")
#Main_5
for_each_geometry_element_output.inputs[0].default_value = 0.0
#Process zone input For Each Geometry Element Input
for_each_geometry_element_input.pair_with_output(for_each_geometry_element_output)
#Selection
for_each_geometry_element_input.inputs[1].default_value = True
#Input_4
for_each_geometry_element_input.inputs[2].default_value = 0.0
#Main_5
for_each_geometry_element_output.inputs[0].default_value = 0.0
#Set locations
group_input.location = (-437.2269287109375, -7.660833358764648)
group_output.location = (200.0, 0.0)
for_each_geometry_element_input.location = (-219.3697509765625, 285.320068359375)
for_each_geometry_element_output.location = (80.6302490234375, 285.320068359375)
#Set dimensions
group_input.width, group_input.height = 140.0, 100.0
group_output.width, group_output.height = 140.0, 100.0
for_each_geometry_element_input.width, for_each_geometry_element_input.height = 140.0, 100.0
for_each_geometry_element_output.width, for_each_geometry_element_output.height = 140.0, 100.0
#initialize geometry_nodes links
#group_input.Geometry -> group_output.Geometry
geometry_nodes.links.new(group_input.outputs[0], group_output.inputs[0])
return geometry_nodes
geometry_nodes = geometry_nodes_node_group()
1 Like
Xinyu_ZHU
(Xinyu ZHU)
December 25, 2024, 2:30am
4
Awesome! This is great finding, and the node_to_python addon is a nice tool! Thanks for sharing