The Blender API has methods for defining nodes, but unfortunately not a lot of documentation or examples. I’d like to create a simple node that would appear in the Shader Editor/Add/Texture menu capable of generating an image. At the moment though, not even the poll()
method of my Node class is being called. How do I get my node to show up in this menu?
This is my best try to far. I’m getting an error saying
raise KeyError("Node categories list '%s' already registered" % identifier)
KeyError: "Node categories list 'SHADER' already registered"
Error: Python script failed, check the message in the system console
Source:
import bpy
import nodeitems_utils
class SortedNodeCategory(nodeitems_utils .NodeCategory):
def __init__(self, identifier, name, description="", items=None):
# for builtin nodes the convention is to sort by name
if isinstance(items, list):
items = sorted(items, key=lambda item: item.label.lower())
super().__init__(identifier, name, description, items)
class ShaderNewNodeCategory(SortedNodeCategory):
@classmethod
def poll(cls, context):
return (context.space_data.tree_type == 'ShaderNodeTree' and
context.scene.render.use_shading_nodes)
class ImageGenNode(bpy.types.Node):
"""
Tooltip: Generate a simple image
"""
bl_idname = "kitfox.image_gen_node"
bl_label = "Image Gen"
bl_icon = "SPEAKER"
color_out : bpy.props.FloatVectorProperty(
default = [.5, .5, .5, 1.0], size=4, subtype = "COLOR", soft_min = 0.0, soft_max = 1.0
)
def init(self, context):
super().init(context)
self.outputs.new("NodeSocketColor", "Color")
print("ImageGenNode init()")
def execute(self):
print("ImageGenNode execute()")
return {"color_out": self.color_out}
def output(self):
print("ImageGenNode output()")
return self.execute()
# Additional buttons displayed on the node.
def draw_buttons(self, context, layout):
print("ImageGenNode draw_buttons()")
layout.prop(self, "color_out", text="walla")
@classmethod
def poll(cls, ntree):
print("ImageGenNode poll()")
return True
# all categories in a list
shader_node_categories = [
# identifier, label, items list
ShaderNewNodeCategory('SH_NEW_TEXTURE', "Texture", items=[
# our basic node
nodeitems_utils.NodeItem("ImageGenNode"),
])
]
def register():
bpy.utils.register_class(ImageGenNode)
nodeitems_utils.register_node_categories('SHADER', shader_node_categories)
print("Registered ImageGenNode")
def unregister():
bpy.utils.unregister_class(ImageGenNode)
if __name__ == "__main__":
register()