diff options
Diffstat (limited to 'release/scripts/templates_py/custom_nodes.py')
-rw-r--r-- | release/scripts/templates_py/custom_nodes.py | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py new file mode 100644 index 00000000000..485ee0ebe05 --- /dev/null +++ b/release/scripts/templates_py/custom_nodes.py @@ -0,0 +1,159 @@ +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' + # Socket color + bl_color = (1.0, 0.4, 0.216, 0.5) + + # 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) + + +# 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() + |