/blender/release/scripts/templates_py/custom_nodes.py
Python | 160 lines | 150 code | 4 blank | 6 comment | 0 complexity | c6d5ae1e9a8586b06b1d1e6d76d27a25 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-1.0
- import bpy
- # XXX these don't work yet ...
- #from bpy_types import NodeTree, Node, NodeSocket
- # Implementation of custom nodes from Python
- # Shortcut for node type menu
- def add_nodetype(layout, type):
- layout.operator("node.add_node", text=type.bl_label).type = type.bl_rna.identifier
- # Derived from the NodeTree base type, similar to Menu, Operator, Panel, etc.
- class MyCustomTree(bpy.types.NodeTree):
- # Description string
- '''A custom node tree type that will show up in the node editor header'''
- # Optional identifier string. If not explicitly defined, the python class name is used.
- bl_idname = 'CustomTreeType'
- # Label for nice name display
- bl_label = 'Custom Node Tree'
- # Icon identifier
- # NOTE: If no icon is defined, the node tree will not show up in the editor header!
- # This can be used to make additional tree types for groups and similar nodes (see below)
- # Only one base tree class is needed in the editor for selecting the general category
- bl_icon = 'NODETREE'
- def draw_add_menu(self, context, layout):
- layout.label("Hello World!")
- add_nodetype(layout, bpy.types.CustomNodeType)
- add_nodetype(layout, bpy.types.MyCustomGroup)
- # Custom socket type
- class MyCustomSocket(bpy.types.NodeSocket):
- # Description string
- '''Custom node socket type'''
- # Optional identifier string. If not explicitly defined, the python class name is used.
- bl_idname = 'CustomSocketType'
- # Label for nice name display
- bl_label = 'Custom Node Socket'
- # Enum items list
- my_items = [
- ("DOWN", "Down", "Where your feet are"),
- ("UP", "Up", "Where your head should be"),
- ("LEFT", "Left", "Not right"),
- ("RIGHT", "Right", "Not left")
- ]
- myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
- # Optional function for drawing the socket input value
- def draw(self, context, layout, node):
- layout.prop(self, "myEnumProperty", text=self.name)
- # Socket color
- def draw_color(self, context, node):
- return (1.0, 0.4, 0.216, 0.5)
- # Base class for all custom nodes in this tree type.
- # Defines a poll function to enable instantiation.
- class MyCustomTreeNode :
- @classmethod
- def poll(cls, ntree):
- return ntree.bl_idname == 'CustomTreeType'
- # Derived from the Node base type.
- class MyCustomNode(bpy.types.Node, MyCustomTreeNode):
- # === Basics ===
- # Description string
- '''A custom node'''
- # Optional identifier string. If not explicitly defined, the python class name is used.
- bl_idname = 'CustomNodeType'
- # Label for nice name display
- bl_label = 'Custom Node'
- # Icon identifier
- bl_icon = 'SOUND'
- # === Custom Properties ===
- # These work just like custom properties in ID data blocks
- # Extensive information can be found under
- # http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties
- myStringProperty = bpy.props.StringProperty()
- myFloatProperty = bpy.props.FloatProperty(default=3.1415926)
- # === Optional Functions ===
- # Initialization function, called when a new node is created.
- # This is the most common place to create the sockets for a node, as shown below.
- # NOTE: this is not the same as the standard __init__ function in Python, which is
- # a purely internal Python method and unknown to the node system!
- def init(self, context):
- self.inputs.new('CustomSocketType', "Hello")
- self.inputs.new('NodeSocketFloat', "World")
- self.inputs.new('NodeSocketVector', "!")
- self.outputs.new('NodeSocketColor', "How")
- self.outputs.new('NodeSocketColor', "are")
- self.outputs.new('NodeSocketFloat', "you")
- # Copy function to initialize a copied node from an existing one.
- def copy(self, node):
- print("Copying from node ", node)
- # Free function to clean up on removal.
- def free(self):
- print("Removing node ", self, ", Goodbye!")
- # Additional buttons displayed on the node.
- def draw_buttons(self, context, layout):
- layout.label("Node settings")
- layout.prop(self, "myFloatProperty")
- # Detail buttons in the sidebar.
- # If this function is not defined, the draw_buttons function is used instead
- def draw_buttons_ext(self, context, layout):
- layout.prop(self, "myFloatProperty")
- # myStringProperty button will only be visible in the sidebar
- layout.prop(self, "myStringProperty")
- # A customized group-like node.
- class MyCustomGroup(bpy.types.NodeGroup, MyCustomTreeNode):
- # === Basics ===
- # Description string
- '''A custom group node'''
- # Label for nice name display
- bl_label = 'Custom Group Node'
- bl_group_tree_idname = 'CustomTreeType'
- orks = bpy.props.IntProperty(default=3)
- dwarfs = bpy.props.IntProperty(default=12)
- wizards = bpy.props.IntProperty(default=1)
- # Additional buttons displayed on the node.
- def draw_buttons(self, context, layout):
- col = layout.column(align=True)
- col.prop(self, "orks")
- col.prop(self, "dwarfs")
- col.prop(self, "wizards")
- layout.label("The Node Tree:")
- layout.prop(self, "node_tree", text="")
- def register():
- bpy.utils.register_class(MyCustomTree)
- bpy.utils.register_class(MyCustomSocket)
- bpy.utils.register_class(MyCustomNode)
- bpy.utils.register_class(MyCustomGroup)
- def unregister():
- bpy.utils.unregister_class(MyCustomTree)
- bpy.utils.unregister_class(MyCustomSocket)
- bpy.utils.unregister_class(MyCustomNode)
- bpy.utils.unregister_class(MyCustomGroup)
- if __name__ == "__main__":
- register()