1
$\begingroup$

I am trying to draw the inputs of the Geometry Nodes modifier to a panel, and I tried doing this

import bpy
from bpy.types import (Panel)

class DRAW_PT_ModInputs(Panel):
    bl_label = "Draw Modifier Inputs"
    bl_idname = "DRAW_PT_ModInputs"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.label(text = "Geometry Node inputs here")
        row = layout.row()
        GeoNodesModifier = context.active_object.modifiers.get("GeometryNodes")
        if GeoNodesModifier:
            row.prop(GeoNodesModifier.Input_5, "Density Max", text="Density")
        
        
 

classes = [DRAW_PT_ModInputs]   

def register():
    for cls in classes:
        bpy.utils.register_class(cls)



def unregister():
    for cls in classes:
        bpy.utils.register_class(cls)

if __name__ == "__main__":
    register()

       

and that gave me error AttributeError: 'NodesModifier', object has no attribute 'Input_5' and in another attempt I tried this row.prop(GeoNodesModifier['Input_5'], "Density Max", text="Density") but this is also not working and it gives error -

TypeError: UILayout.prop(): error with argument 1, "data" -  Function.data expected a AnyType type, not float

and this is how my Geometry Nodes Modifier looks like -

Modifier screenshot

and this is my Geometry Node tree -

Geometry Nodetree screenshot

I needed help regarding drawing the inputs from the Geometry Nodes modifier in my customized panel.

Thanks in advance!

$\endgroup$
1
  • 2
    $\begingroup$ Check out the style guide under which the modifier instance variable would be named akin to geom_modifier (I like using gm to reduce the verbosity) Camel case is used for class names. A variable named GeoNodesModifier will consistently be a type in any official blender UI code. $\endgroup$
    – batFINGER
    May 15 at 4:45
4
$\begingroup$

The modifier input value is treated like a custom property.

If you right click over the data field in the modifier and select "copy datapath", pasting will reveal

modifiers["GeometryNodes"]["Input_5"]

Indicating it is a custom propoerty of the modifier named "Input_5". A custom property named "prop" on object ob is shown in UI as

UILayout.prop(ob, '["prop"]')

Hence in this case.

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.label(text = "Geometry Node inputs here")
        row = layout.row()
        gm = context.active_object.modifiers.get("GeometryNodes")
        if gm:
            row.prop(gm, '["Input_5"]',  text="Density")
        

Note

Check out the style guide under which the modifier instance variable would be named akin to geom_modifier (I like using gm to reduce the verbosity) Camel case is used for class names. A variable named GeoNodesModifier will consistently be a type in any official blender UI code

$\endgroup$
4
  • 1
    $\begingroup$ That was fast :) Oh right, add commas around the list ! Clever. I don't know about the use of custom properties though. It would seem better to me if they were categorised in an inputs container and accessed like in node groups for instance. Using custom properties might clash with addons and so on. Idk $\endgroup$
    – Gorgious
    May 15 at 8:10
  • 2
    $\begingroup$ Agreed, fuddles the py console too. Teething problem perhaps? $\endgroup$
    – batFINGER
    May 15 at 8:14
  • $\begingroup$ Yeah, I'm not too worried, it's still a very young tool and they have time to improve the API and UI :) But unfortunately that will render this kind of answers outdated at every breaking update... $\endgroup$
    – Gorgious
    May 15 at 8:18
  • 2
    $\begingroup$ Also agreed. Will notice that like UI defined custom properties the _RNA_UIdata is set. Changing the input / output node default_value sets the default of custom prop. C.object.modifiers["GeometryNodes"]['_RNA_UI'].to_dict() $\endgroup$
    – batFINGER
    May 15 at 8:25
2
$\begingroup$

From what I understood from the GeoNodes modifier API, you access the node group (or tree, since every node tree is a group and every node group is a tree there) with modifier.node_group. This will give you access to the inputs and outputs, very much like all other node groups in Blender (Shader, Compositor, etc.)

You can then access the input by its Name, or its integer position in the inputs hierarchy. The former will break if you change the input name, while the latter will break if you reorder your inputs.

Replace your row.prop line with

row.prop(geom_modifier.node_group.inputs["Density Max"], "default_value", text="Density")
 

OR

row.prop(geom_modifier.node_group.inputs[1], "default_value", text="Density")
 

Result :

enter image description here

If you want more information from the API, check Python tooltips and developer extras in the preferences, and hover over fields to get more information about their relative path.

$\endgroup$
2
  • $\begingroup$ Hi, this is working fine with the default value of the input node, but it is not updating in the inputs of the modifier $\endgroup$ May 15 at 5:30
  • $\begingroup$ Right, my mistake ! See the other answer :) $\endgroup$
    – Gorgious
    May 15 at 8:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.