2013-03-18 16:34:57 +00:00
|
|
|
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)
|
|
|
|
|
2013-03-22 13:17:16 +00:00
|
|
|
# Socket color
|
|
|
|
def draw_color(self, context, node):
|
|
|
|
return (1.0, 0.4, 0.216, 0.5)
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
# 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()
|
|
|
|
|