AttributeError: 'module' object has no attribute 'inputs'

76 Views Asked by At

I'm working on one blender project, need to install add-on. When I'm trying to add this add-on in geometry nodes, I get this error. I tried to search for some same errors with inputs, but I didn't found anything... enter image description here Have suggestions how to fix it?

Code:


import bpy
from bpy.props import IntProperty, EnumProperty

bl_info = {
    "name": "Pick Node Generator",
    "author": "Johnny Matthews",
    "location": "Geometry Nodes Editor: Add Node Panel",
    "version": (1, 0),
    "blender": (3, 4, 1),
    "description": "Add a customizable pick node",
    "category": "Nodes"
}


def find_socket(list, type, name):
    for s in list:
        if s.type == type and s.name == name:
            return s


def main(self, context):
    space = context.space_data
    if space.node_tree == None:
        return
    group = space.node_tree


    cases = self.cases
    type_enum = self.type
    type = 'NodeSocket'+type_enum.capitalize()
    if type_enum == "RGBA":
        type = 'NodeSocketColor'
    if type_enum == "BOOLEAN":
        type = 'NodeSocketBool'
    if type_enum == "VALUE":
        type = 'NodeSocketFloat'

    tree = bpy.data.node_groups.new("test", 'GeometryNodeTree')
    tree.name = type_enum.capitalize() + ' Pick x'+str(cases)
    socket_case = tree.inputs.new('NodeSocketInt', 'Switch')
    for i in range(cases):
        socket_case = tree.inputs.new(type, 'Case '+str(i+self.start)+":")
    tree.inputs.new(type, 'Default ')

    socket_output = tree.outputs.new(type, 'Output')

    input = tree.nodes.new("NodeGroupInput")
    input.location = (0, 0)
    output = tree.nodes.new("NodeGroupOutput")
    output.location = (700+(cases*200), 0)

    compares = []
    switches = []
    for i in range(cases):
        compares.append(tree.nodes.new("FunctionNodeCompare"))
        compares[i].data_type = 'INT'
        compares[i].hide = True
        compares[i].name = 'Equals '+str(i+self.start)
        compares[i].operation = 'EQUAL'
        compares[i].inputs[3].default_value = i+self.start
        compares[i].location = (200+((cases-i)*150), -i*250+(cases*250/2)-60)
        tree.links.new(compares[i].inputs[2], input.outputs[0])

        switches.append(tree.nodes.new("GeometryNodeSwitch"))
        switches[i].location = (400+((cases-i)*150), -i*250+(cases*250/2))

        if type_enum == 'VALUE':
            switches[i].input_type = 'FLOAT'
        else:
            switches[i].input_type = type_enum

        switch_type = 0
        if type_enum in ('OBJECT', 'IMAGE', 'GEOMETRY', 'COLLECTION', 'TEXTURE', 'MATERIAL'):
            switch_type = 1

        tree.links.new(switches[i].inputs[switch_type], compares[i].outputs[0])

        sock = find_socket(switches[i].inputs, type_enum, "True")
        if sock != None:
            tree.links.new(sock, input.outputs[i+1])

    for i in range(cases):
        if i == 0:
            sock = find_socket(switches[i].outputs, type_enum, "Output")
            if sock != None:
                tree.links.new(output.inputs[0], sock)
        else:
            sock_o = find_socket(switches[i].outputs, type_enum, "Output")
            sock_i = find_socket(switches[i-1].inputs, type_enum, "False")
            tree.links.new(sock_i, sock_o)

    sock_i = find_socket(switches[cases-1].inputs, type_enum, "False")
    tree.links.new(sock_i, input.outputs[cases+1])

    group = group.nodes.new('GeometryNodeGroup')
    group.name = "Case Statement"
    group.node_tree = tree
    group.width = 150
    return {'FINISHED'}


class PickNodeOperator(bpy.types.Operator):
    """Pick Node Generator"""
    bl_idname = "node.swich_node"
    bl_label = "Pick Node Generator"
    bl_options = {'REGISTER', 'UNDO'}

    cases: bpy.props.IntProperty(min=0, default=6, max=25, name="# of Cases")
    start: bpy.props.IntProperty(default=0, name="Starting Value")
    type: bpy.props.EnumProperty(name="Type", items=[
        ('VALUE', 'Float', "", 0),
        ('INT', 'Int', "", 1),
        ('BOOLEAN', 'Bool', "", 2),
        ('VECTOR', 'Vector', "", 3),
        ('RGBA', 'Color', "", 4),
        ('STRING', 'String', "", 5),
        ('GEOMETRY', 'Geometry', "", 6),
        ('OBJECT', 'Object', "", 7),
        ('COLLECTION', 'Collection', "", 8),
        ('TEXTURE', 'Texture', "", 9),
        ('MATERIAL', 'Material', "", 10),
        ('IMAGE', 'Image', "", 11)
    ], default='GEOMETRY')

    @classmethod
    def poll(cls, context):
        space = context.space_data
        return space.type == 'NODE_EDITOR'

    def execute(self, context):
        main(self, context)
        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(PickNodeOperator.bl_idname,
                         text=PickNodeOperator.bl_label)


def register():
    bpy.utils.register_class(PickNodeOperator)
    bpy.types.NODE_MT_add.append(menu_func)


def unregister():
    bpy.utils.unregister_class(PickNodeOperator)
    bpy.types.NODE_MT_add.remove(menu_func)


if __name__ == "__main__":
    register()

I tried to replace input with Input and somehow try to fix error on line 40, but I'm bad at Blender add-on programming :P

1

There are 1 best solutions below

0
35308 On

I was not able to reproduce this error on Blender 3.4.1 but I was for Blender 4.0.2 indicating a version specific issue. By looking through the Blender change logs for bpy.types.NodeTree we notice that the inputs property was removed between Blender 3.6 and 4.0 hence why you got that error. What was added in it's place is bpy.types.NodeTree.interface which has a new_socket method, thus to "update" this add-on for Blender 4.0+ you'll have to switch all instances of tree.inputs and tree.outputs with

tree.interface.new_socket(name = "the name", in_out='INPUT or OUTPUT',socket_type='socket type')

For the add-on code that would mean replacing lines 40 to 45 (from socket_case = tree.interface.new_socket(name = "Switch"... to socket_output = tree.interface...) with this updated code:

    tree.name = type_enum.capitalize() + ' Pick x'+str(cases)
    socket_case = tree.interface.new_socket(name = "Switch", in_out='INPUT',socket_type='NodeSocketInt')
    for i in range(cases):
        socket_case = tree.interface.new_socket(name = 'Case '+str(i+self.start)+":", in_out='INPUT',socket_type= type)
    tree.interface.new_socket(name = "Default ", in_out='INPUT',socket_type=type)

    socket_output = tree.interface.new_socket(name = "Output", in_out='OUTPUT',socket_type=type)

I was able to confirm this works on my fresh copy of Blender 4.0.2.

It also looks like the BlenderArtists Forum has a very similar question so you might want to check that out.

PS: Generally avoid attaching images of text in your posts as it can introduce complications.