PageRenderTime 37ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/blender/release/scripts/templates_py/custom_nodes.py

https://bitbucket.org/DeanGiberson/blender
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
  1. import bpy
  2. # XXX these don't work yet ...
  3. #from bpy_types import NodeTree, Node, NodeSocket
  4. # Implementation of custom nodes from Python
  5. # Shortcut for node type menu
  6. def add_nodetype(layout, type):
  7. layout.operator("node.add_node", text=type.bl_label).type = type.bl_rna.identifier
  8. # Derived from the NodeTree base type, similar to Menu, Operator, Panel, etc.
  9. class MyCustomTree(bpy.types.NodeTree):
  10. # Description string
  11. '''A custom node tree type that will show up in the node editor header'''
  12. # Optional identifier string. If not explicitly defined, the python class name is used.
  13. bl_idname = 'CustomTreeType'
  14. # Label for nice name display
  15. bl_label = 'Custom Node Tree'
  16. # Icon identifier
  17. # NOTE: If no icon is defined, the node tree will not show up in the editor header!
  18. # This can be used to make additional tree types for groups and similar nodes (see below)
  19. # Only one base tree class is needed in the editor for selecting the general category
  20. bl_icon = 'NODETREE'
  21. def draw_add_menu(self, context, layout):
  22. layout.label("Hello World!")
  23. add_nodetype(layout, bpy.types.CustomNodeType)
  24. add_nodetype(layout, bpy.types.MyCustomGroup)
  25. # Custom socket type
  26. class MyCustomSocket(bpy.types.NodeSocket):
  27. # Description string
  28. '''Custom node socket type'''
  29. # Optional identifier string. If not explicitly defined, the python class name is used.
  30. bl_idname = 'CustomSocketType'
  31. # Label for nice name display
  32. bl_label = 'Custom Node Socket'
  33. # Enum items list
  34. my_items = [
  35. ("DOWN", "Down", "Where your feet are"),
  36. ("UP", "Up", "Where your head should be"),
  37. ("LEFT", "Left", "Not right"),
  38. ("RIGHT", "Right", "Not left")
  39. ]
  40. myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
  41. # Optional function for drawing the socket input value
  42. def draw(self, context, layout, node):
  43. layout.prop(self, "myEnumProperty", text=self.name)
  44. # Socket color
  45. def draw_color(self, context, node):
  46. return (1.0, 0.4, 0.216, 0.5)
  47. # Base class for all custom nodes in this tree type.
  48. # Defines a poll function to enable instantiation.
  49. class MyCustomTreeNode :
  50. @classmethod
  51. def poll(cls, ntree):
  52. return ntree.bl_idname == 'CustomTreeType'
  53. # Derived from the Node base type.
  54. class MyCustomNode(bpy.types.Node, MyCustomTreeNode):
  55. # === Basics ===
  56. # Description string
  57. '''A custom node'''
  58. # Optional identifier string. If not explicitly defined, the python class name is used.
  59. bl_idname = 'CustomNodeType'
  60. # Label for nice name display
  61. bl_label = 'Custom Node'
  62. # Icon identifier
  63. bl_icon = 'SOUND'
  64. # === Custom Properties ===
  65. # These work just like custom properties in ID data blocks
  66. # Extensive information can be found under
  67. # http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties
  68. myStringProperty = bpy.props.StringProperty()
  69. myFloatProperty = bpy.props.FloatProperty(default=3.1415926)
  70. # === Optional Functions ===
  71. # Initialization function, called when a new node is created.
  72. # This is the most common place to create the sockets for a node, as shown below.
  73. # NOTE: this is not the same as the standard __init__ function in Python, which is
  74. # a purely internal Python method and unknown to the node system!
  75. def init(self, context):
  76. self.inputs.new('CustomSocketType', "Hello")
  77. self.inputs.new('NodeSocketFloat', "World")
  78. self.inputs.new('NodeSocketVector', "!")
  79. self.outputs.new('NodeSocketColor', "How")
  80. self.outputs.new('NodeSocketColor', "are")
  81. self.outputs.new('NodeSocketFloat', "you")
  82. # Copy function to initialize a copied node from an existing one.
  83. def copy(self, node):
  84. print("Copying from node ", node)
  85. # Free function to clean up on removal.
  86. def free(self):
  87. print("Removing node ", self, ", Goodbye!")
  88. # Additional buttons displayed on the node.
  89. def draw_buttons(self, context, layout):
  90. layout.label("Node settings")
  91. layout.prop(self, "myFloatProperty")
  92. # Detail buttons in the sidebar.
  93. # If this function is not defined, the draw_buttons function is used instead
  94. def draw_buttons_ext(self, context, layout):
  95. layout.prop(self, "myFloatProperty")
  96. # myStringProperty button will only be visible in the sidebar
  97. layout.prop(self, "myStringProperty")
  98. # A customized group-like node.
  99. class MyCustomGroup(bpy.types.NodeGroup, MyCustomTreeNode):
  100. # === Basics ===
  101. # Description string
  102. '''A custom group node'''
  103. # Label for nice name display
  104. bl_label = 'Custom Group Node'
  105. bl_group_tree_idname = 'CustomTreeType'
  106. orks = bpy.props.IntProperty(default=3)
  107. dwarfs = bpy.props.IntProperty(default=12)
  108. wizards = bpy.props.IntProperty(default=1)
  109. # Additional buttons displayed on the node.
  110. def draw_buttons(self, context, layout):
  111. col = layout.column(align=True)
  112. col.prop(self, "orks")
  113. col.prop(self, "dwarfs")
  114. col.prop(self, "wizards")
  115. layout.label("The Node Tree:")
  116. layout.prop(self, "node_tree", text="")
  117. def register():
  118. bpy.utils.register_class(MyCustomTree)
  119. bpy.utils.register_class(MyCustomSocket)
  120. bpy.utils.register_class(MyCustomNode)
  121. bpy.utils.register_class(MyCustomGroup)
  122. def unregister():
  123. bpy.utils.unregister_class(MyCustomTree)
  124. bpy.utils.unregister_class(MyCustomSocket)
  125. bpy.utils.unregister_class(MyCustomNode)
  126. bpy.utils.unregister_class(MyCustomGroup)
  127. if __name__ == "__main__":
  128. register()