Nodes: Use plain menus for geometry nodes add menu
At the cost of slightly more boilerplate code, we can avoid the `NodeItem` and `NodeCategory` abstractions used to build the node add menu. This makes the menus more flexible and more obvious, which will make them easier to extend with assets. The identifiers for the new menu types are inconsistent with regular class naming for backwards compatibility with the old "category" menu naming. Also adds an item for the "Self Object" node missed in dd5131bd700c. Differential Revision: https://developer.blender.org/D15973
This commit is contained in:
parent
8a6dc0fac7
commit
837144b457
@ -9,6 +9,8 @@ if "bpy" in locals():
|
||||
del reload
|
||||
|
||||
_modules = [
|
||||
"node_add_menu",
|
||||
"node_add_menu_geometry",
|
||||
"properties_animviz",
|
||||
"properties_constraint",
|
||||
"properties_data_armature",
|
||||
|
63
release/scripts/startup/bl_ui/node_add_menu.py
Normal file
63
release/scripts/startup/bl_ui/node_add_menu.py
Normal file
@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
import bpy
|
||||
from bpy.types import Menu
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
contexts as i18n_contexts,
|
||||
)
|
||||
|
||||
def add_node_type(layout, node_type, *, label=None):
|
||||
"""Add a node type to a menu."""
|
||||
bl_rna = bpy.types.Node.bl_rna_get_subclass(node_type)
|
||||
if not label:
|
||||
label = bl_rna.name if bl_rna else iface_("Unknown")
|
||||
translation_context = bl_rna.translation_context if bl_rna else i18n_contexts.default
|
||||
props = layout.operator("node.add_node", text=label, text_ctxt=translation_context)
|
||||
props.type = node_type
|
||||
props.use_transform = True
|
||||
return props
|
||||
|
||||
|
||||
def draw_node_group_add_menu(context, layout):
|
||||
"""Add items to the layout used for interacting with node groups."""
|
||||
space_node = context.space_data
|
||||
node_tree = space_node.edit_tree
|
||||
all_node_groups = context.blend_data.node_groups
|
||||
|
||||
layout.operator("node.group_make")
|
||||
layout.operator("node.group_ungroup")
|
||||
if node_tree in all_node_groups.values():
|
||||
layout.separator()
|
||||
add_node_type(layout, "NodeGroupInput")
|
||||
add_node_type(layout, "NodeGroupOutput")
|
||||
|
||||
if node_tree:
|
||||
from nodeitems_builtins import node_tree_group_type
|
||||
def contains_group(nodetree, group):
|
||||
if nodetree == group:
|
||||
return True
|
||||
for node in nodetree.nodes:
|
||||
if node.bl_idname in node_tree_group_type.values() and node.node_tree is not None:
|
||||
if contains_group(node.node_tree, group):
|
||||
return True
|
||||
return False
|
||||
|
||||
groups = [group for group in context.blend_data.node_groups if group.bl_idname == node_tree.bl_idname and
|
||||
not contains_group(group, node_tree) and
|
||||
not group.name.startswith('.')]
|
||||
if groups:
|
||||
layout.separator()
|
||||
for group in groups:
|
||||
props = add_node_type(layout, node_tree_group_type[group.bl_idname], label=group.name)
|
||||
ops = props.settings.add()
|
||||
ops.name = "node_tree"
|
||||
ops.value = "bpy.data.node_groups[%r]" % group.name
|
||||
|
||||
|
||||
classes = (
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
395
release/scripts/startup/bl_ui/node_add_menu_geometry.py
Normal file
395
release/scripts/startup/bl_ui/node_add_menu_geometry.py
Normal file
@ -0,0 +1,395 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
import bpy
|
||||
from bpy.types import Menu
|
||||
from bl_ui import node_add_menu
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
class NODE_MT_geometry_node_GEO_ATTRIBUTE(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_ATTRIBUTE"
|
||||
bl_label = "Attribute"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCaptureAttribute")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeAttributeDomainSize")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeAttributeStatistic")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeAttributeTransfer")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeRemoveAttribute")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeStoreNamedAttribute")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_COLOR(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_COLOR"
|
||||
bl_label = "Color"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
props = node_add_menu.add_node_type(layout, "ShaderNodeMix", label=iface_("Mix Color"))
|
||||
ops = props.settings.add()
|
||||
ops.name = "data_type"
|
||||
ops.value = "'RGBA'"
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeValToRGB")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeSeparateColor")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeCombineColor")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_CURVE(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_CURVE"
|
||||
bl_label = "Curve"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveLength")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveToMesh")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveToPoints")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDeformCurvesOnSurface")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeFillCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeFilletCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeResampleCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeReverseCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSubdivideCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeTrimCurve")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputControlPointNeighbors")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputCurveHandlePositions")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputTangent")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputCurveTilt")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveEndpointSelection")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveHandleTypeSelection")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputSplineCyclic")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSplineLength")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSplineParameter")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputSplineResolution")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveRadius")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveTilt")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetCurveHandlePositions")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveSetHandles")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineCyclic")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineResolution")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveSplineType")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE"
|
||||
bl_label = "Curve Primitives"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveLine")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveCircle")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveStar")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveSpiral")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveArc")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurveQuadraticBezier")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveQuadrilateral")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveBezierSegment")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_GEOMETRY(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_GEOMETRY"
|
||||
bl_label = "Geometry"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeBoundBox")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeConvexHull")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDeleteGeometry")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDuplicateElements")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeProximity")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeGeometryToInstance")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeJoinGeometry")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMergeByDistance")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeRaycast")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleIndex")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleNearest")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSeparateComponents")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSeparateGeometry")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeTransform")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetID")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetPosition")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_INPUT(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_INPUT"
|
||||
bl_label = "Input"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputBool")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeCollectionInfo")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputColor")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputInt")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeIsViewport")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterial")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeObjectInfo")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSelfObject")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputString")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeValue")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputVector")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputID")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputIndex")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputNamedAttribute")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputNormal")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputPosition")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputRadius")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputSceneTime")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_INSTANCE(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_INSTANCE"
|
||||
bl_label = "Instances"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInstanceOnPoints")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInstancesToPoints")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeRealizeInstances")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeRotateInstances")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeScaleInstances")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeTranslateInstances")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceRotation")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceScale")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_MATERIAL(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_MATERIAL"
|
||||
bl_label = "Material"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeReplaceMaterial")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterialIndex")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMaterialSelection")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterial")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterialIndex")
|
||||
|
||||
class NODE_MT_geometry_node_GEO_MESH(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_GEO_MESH"
|
||||
bl_label = "Mesh"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDualMesh")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgePathsToCurves")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgePathsToSelection")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeExtrudeMesh")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeFlipFaces")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleNearestSurface")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeScaleElements")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSubdivideMesh")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSubdivisionSurface")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeTriangulate")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeAngle")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeNeighbors")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeVertices")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceArea")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceNeighbors")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshFaceSetBoundaries")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceIsPlanar")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputShadeSmooth")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshIsland")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputShortestEdgePaths")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshVertexNeighbors")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetShadeSmooth")
|
||||
|
||||
class NODE_MT_category_PRIMITIVES_MESH(Menu):
|
||||
bl_idname = "NODE_MT_category_PRIMITIVES_MESH"
|
||||
bl_label = "Mesh Primitives"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCircle")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCone")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCube")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshCylinder")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshGrid")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshIcoSphere")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshLine")
|
||||
|
||||
class NODE_MT_category_GEO_OUTPUT(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_OUTPUT"
|
||||
bl_label = "Output"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeViewer")
|
||||
|
||||
class NODE_MT_category_GEO_POINT(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_POINT"
|
||||
bl_label = "Point"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsInVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsOnFaces")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePoints")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius")
|
||||
|
||||
class NODE_MT_category_GEO_TEXT(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_TEXT"
|
||||
bl_label = "Text"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeSliceString")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeStringJoin")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeStringLength")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeReplaceString")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeValueToString")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeStringToCurves")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInputSpecialCharacters")
|
||||
|
||||
class NODE_MT_category_GEO_TEXTURE(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_TEXTURE"
|
||||
bl_label = "Texture"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexBrick")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexChecker")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexGradient")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeImageTexture")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexMusgrave")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise")
|
||||
|
||||
class NODE_MT_category_GEO_UTILITIES(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_UTILITIES"
|
||||
bl_label = "Utilities"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeAccumulateField")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeFieldAtIndex")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeFieldOnDomain")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMapRange")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeFloatCurve")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeClamp")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMath")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeBooleanMath")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeCompare")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeMix")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeFloatToInt")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSwitch")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRandomValue")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeAlignEulerToVector")
|
||||
|
||||
class NODE_MT_category_GEO_UV(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_UV"
|
||||
bl_label = "UV"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeUVPackIslands")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeUVUnwrap")
|
||||
|
||||
class NODE_MT_category_GEO_VECTOR(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_VECTOR"
|
||||
bl_label = "Vector"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeCombineXYZ")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSeparateXYZ")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorMath")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate")
|
||||
|
||||
class NODE_MT_category_GEO_VOLUME(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_VOLUME"
|
||||
bl_label = "Volume"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
|
||||
|
||||
class NODE_MT_category_GEO_GROUP(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_GROUP"
|
||||
bl_label = "Group"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
node_add_menu.draw_node_group_add_menu(context, layout)
|
||||
|
||||
class NODE_MT_category_GEO_LAYOUT(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_LAYOUT"
|
||||
bl_label = "Layout"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "NodeFrame")
|
||||
node_add_menu.add_node_type(layout, "NodeReroute")
|
||||
|
||||
class NODE_MT_geometry_node_add_all(Menu):
|
||||
bl_idname = "NODE_MT_geometry_node_add_all"
|
||||
bl_label = ""
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.menu("NODE_MT_geometry_node_GEO_ATTRIBUTE")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_COLOR")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_CURVE")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_GEOMETRY")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_INPUT")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_INSTANCE")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_MATERIAL")
|
||||
layout.menu("NODE_MT_geometry_node_GEO_MESH")
|
||||
layout.menu("NODE_MT_category_PRIMITIVES_MESH")
|
||||
layout.menu("NODE_MT_category_GEO_OUTPUT")
|
||||
layout.menu("NODE_MT_category_GEO_POINT")
|
||||
layout.menu("NODE_MT_category_GEO_TEXT")
|
||||
layout.menu("NODE_MT_category_GEO_TEXTURE")
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES")
|
||||
layout.menu("NODE_MT_category_GEO_UV")
|
||||
layout.menu("NODE_MT_category_GEO_VECTOR")
|
||||
layout.menu("NODE_MT_category_GEO_VOLUME")
|
||||
layout.menu("NODE_MT_category_GEO_GROUP")
|
||||
layout.menu("NODE_MT_category_GEO_LAYOUT")
|
||||
|
||||
|
||||
classes = (
|
||||
NODE_MT_geometry_node_add_all,
|
||||
NODE_MT_geometry_node_GEO_ATTRIBUTE,
|
||||
NODE_MT_geometry_node_GEO_COLOR,
|
||||
NODE_MT_geometry_node_GEO_CURVE,
|
||||
NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE,
|
||||
NODE_MT_geometry_node_GEO_GEOMETRY,
|
||||
NODE_MT_geometry_node_GEO_INPUT,
|
||||
NODE_MT_geometry_node_GEO_INSTANCE,
|
||||
NODE_MT_geometry_node_GEO_MATERIAL,
|
||||
NODE_MT_geometry_node_GEO_MESH,
|
||||
NODE_MT_category_PRIMITIVES_MESH,
|
||||
NODE_MT_category_GEO_OUTPUT,
|
||||
NODE_MT_category_GEO_POINT,
|
||||
NODE_MT_category_GEO_TEXT,
|
||||
NODE_MT_category_GEO_TEXTURE,
|
||||
NODE_MT_category_GEO_UTILITIES,
|
||||
NODE_MT_category_GEO_UV,
|
||||
NODE_MT_category_GEO_VECTOR,
|
||||
NODE_MT_category_GEO_VOLUME,
|
||||
NODE_MT_category_GEO_GROUP,
|
||||
NODE_MT_category_GEO_LAYOUT,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
@ -219,10 +219,14 @@ class NODE_MT_add(bpy.types.Menu):
|
||||
import nodeitems_utils
|
||||
|
||||
layout = self.layout
|
||||
|
||||
layout.operator_context = 'INVOKE_DEFAULT'
|
||||
|
||||
if nodeitems_utils.has_node_categories(context):
|
||||
snode = context.space_data
|
||||
if snode.tree_type == 'GeometryNodeTree':
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
layout.separator()
|
||||
layout.menu_contents("NODE_MT_geometry_node_add_all")
|
||||
elif nodeitems_utils.has_node_categories(context):
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
props.use_transform = True
|
||||
|
||||
|
@ -39,14 +39,6 @@ class TextureNodeCategory(SortedNodeCategory):
|
||||
return (context.space_data.type == 'NODE_EDITOR' and
|
||||
context.space_data.tree_type == 'TextureNodeTree')
|
||||
|
||||
|
||||
class GeometryNodeCategory(SortedNodeCategory):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.space_data.type == 'NODE_EDITOR' and
|
||||
context.space_data.tree_type == 'GeometryNodeTree')
|
||||
|
||||
|
||||
# menu entry for node group tools
|
||||
def group_tools_draw(_self, layout, _context):
|
||||
layout.operator("node.group_make")
|
||||
@ -63,198 +55,6 @@ node_tree_group_type = {
|
||||
}
|
||||
|
||||
|
||||
# Custom Menu for Geometry Node Curves.
|
||||
def curve_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("GeometryNodeCurveLength")
|
||||
yield NodeItem("GeometryNodeCurveToMesh")
|
||||
yield NodeItem("GeometryNodeCurveToPoints")
|
||||
yield NodeItem("GeometryNodeDeformCurvesOnSurface")
|
||||
yield NodeItem("GeometryNodeFillCurve")
|
||||
yield NodeItem("GeometryNodeFilletCurve")
|
||||
yield NodeItem("GeometryNodeResampleCurve")
|
||||
yield NodeItem("GeometryNodeReverseCurve")
|
||||
yield NodeItem("GeometryNodeSampleCurve")
|
||||
yield NodeItem("GeometryNodeSubdivideCurve")
|
||||
yield NodeItem("GeometryNodeTrimCurve")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeInputControlPointNeighbors")
|
||||
yield NodeItem("GeometryNodeInputCurveHandlePositions")
|
||||
yield NodeItem("GeometryNodeInputTangent")
|
||||
yield NodeItem("GeometryNodeInputCurveTilt")
|
||||
yield NodeItem("GeometryNodeCurveEndpointSelection")
|
||||
yield NodeItem("GeometryNodeCurveHandleTypeSelection")
|
||||
yield NodeItem("GeometryNodeInputSplineCyclic")
|
||||
yield NodeItem("GeometryNodeSplineLength")
|
||||
yield NodeItem("GeometryNodeSplineParameter")
|
||||
yield NodeItem("GeometryNodeInputSplineResolution")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeSetCurveRadius")
|
||||
yield NodeItem("GeometryNodeSetCurveTilt")
|
||||
yield NodeItem("GeometryNodeSetCurveHandlePositions")
|
||||
yield NodeItem("GeometryNodeCurveSetHandles")
|
||||
yield NodeItem("GeometryNodeSetSplineCyclic")
|
||||
yield NodeItem("GeometryNodeSetSplineResolution")
|
||||
yield NodeItem("GeometryNodeCurveSplineType")
|
||||
|
||||
|
||||
# Custom Menu for Geometry Node Mesh.
|
||||
def mesh_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("GeometryNodeDualMesh")
|
||||
yield NodeItem("GeometryNodeEdgePathsToCurves")
|
||||
yield NodeItem("GeometryNodeEdgePathsToSelection")
|
||||
yield NodeItem("GeometryNodeExtrudeMesh")
|
||||
yield NodeItem("GeometryNodeFlipFaces")
|
||||
yield NodeItem("GeometryNodeMeshBoolean")
|
||||
yield NodeItem("GeometryNodeMeshToCurve")
|
||||
yield NodeItem("GeometryNodeMeshToPoints")
|
||||
yield NodeItem("GeometryNodeMeshToVolume")
|
||||
yield NodeItem("GeometryNodeSampleNearestSurface")
|
||||
yield NodeItem("GeometryNodeScaleElements")
|
||||
yield NodeItem("GeometryNodeSplitEdges")
|
||||
yield NodeItem("GeometryNodeSubdivideMesh")
|
||||
yield NodeItem("GeometryNodeSubdivisionSurface")
|
||||
yield NodeItem("GeometryNodeTriangulate")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeInputMeshEdgeAngle")
|
||||
yield NodeItem("GeometryNodeInputMeshEdgeNeighbors")
|
||||
yield NodeItem("GeometryNodeInputMeshEdgeVertices")
|
||||
yield NodeItem("GeometryNodeInputMeshFaceArea")
|
||||
yield NodeItem("GeometryNodeInputMeshFaceNeighbors")
|
||||
yield NodeItem("GeometryNodeMeshFaceSetBoundaries")
|
||||
yield NodeItem("GeometryNodeInputMeshFaceIsPlanar")
|
||||
yield NodeItem("GeometryNodeInputShadeSmooth")
|
||||
yield NodeItem("GeometryNodeInputMeshIsland")
|
||||
yield NodeItem("GeometryNodeInputShortestEdgePaths")
|
||||
yield NodeItem("GeometryNodeInputMeshVertexNeighbors")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeSetShadeSmooth")
|
||||
|
||||
|
||||
# Custom Menu for Geometry Nodes "Geometry" category.
|
||||
def geometry_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("GeometryNodeBoundBox")
|
||||
yield NodeItem("GeometryNodeConvexHull")
|
||||
yield NodeItem("GeometryNodeDeleteGeometry")
|
||||
yield NodeItem("GeometryNodeDuplicateElements")
|
||||
yield NodeItem("GeometryNodeProximity")
|
||||
yield NodeItem("GeometryNodeGeometryToInstance")
|
||||
yield NodeItem("GeometryNodeJoinGeometry")
|
||||
yield NodeItem("GeometryNodeMergeByDistance")
|
||||
yield NodeItem("GeometryNodeRaycast")
|
||||
yield NodeItem("GeometryNodeSampleIndex")
|
||||
yield NodeItem("GeometryNodeSampleNearest")
|
||||
yield NodeItem("GeometryNodeSeparateComponents")
|
||||
yield NodeItem("GeometryNodeSeparateGeometry")
|
||||
yield NodeItem("GeometryNodeTransform")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeSetID")
|
||||
yield NodeItem("GeometryNodeSetPosition")
|
||||
|
||||
|
||||
# Custom Menu for UV Nodes.
|
||||
def uv_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("GeometryNodeUVPackIslands")
|
||||
yield NodeItem("GeometryNodeUVUnwrap")
|
||||
|
||||
|
||||
# Custom Menu for Geometry Node Input Nodes.
|
||||
def geometry_input_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("FunctionNodeInputBool")
|
||||
yield NodeItem("GeometryNodeCollectionInfo")
|
||||
yield NodeItem("FunctionNodeInputColor")
|
||||
yield NodeItem("FunctionNodeInputInt")
|
||||
yield NodeItem("GeometryNodeIsViewport")
|
||||
yield NodeItem("GeometryNodeInputMaterial")
|
||||
yield NodeItem("GeometryNodeObjectInfo")
|
||||
yield NodeItem("FunctionNodeInputString")
|
||||
yield NodeItem("ShaderNodeValue")
|
||||
yield NodeItem("FunctionNodeInputVector")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeInputID")
|
||||
yield NodeItem("GeometryNodeInputIndex")
|
||||
yield NodeItem("GeometryNodeInputNamedAttribute")
|
||||
yield NodeItem("GeometryNodeInputNormal")
|
||||
yield NodeItem("GeometryNodeInputPosition")
|
||||
yield NodeItem("GeometryNodeInputRadius")
|
||||
yield NodeItem("GeometryNodeInputSceneTime")
|
||||
|
||||
|
||||
# Custom Menu for Geometry Node Instance Nodes.
|
||||
def geometry_instance_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("GeometryNodeInstanceOnPoints")
|
||||
yield NodeItem("GeometryNodeInstancesToPoints")
|
||||
yield NodeItem("GeometryNodeRealizeInstances")
|
||||
yield NodeItem("GeometryNodeRotateInstances")
|
||||
yield NodeItem("GeometryNodeScaleInstances")
|
||||
yield NodeItem("GeometryNodeTranslateInstances")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeInputInstanceRotation")
|
||||
yield NodeItem("GeometryNodeInputInstanceScale")
|
||||
|
||||
|
||||
# Custom Menu for Material Nodes.
|
||||
def geometry_material_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("GeometryNodeReplaceMaterial")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeInputMaterialIndex")
|
||||
yield NodeItem("GeometryNodeMaterialSelection")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeSetMaterial")
|
||||
yield NodeItem("GeometryNodeSetMaterialIndex")
|
||||
|
||||
|
||||
# Custom Menu for Geometry Node Points.
|
||||
def point_node_items(context):
|
||||
if context is None:
|
||||
return
|
||||
space = context.space_data
|
||||
if not space:
|
||||
return
|
||||
yield NodeItem("GeometryNodeDistributePointsInVolume")
|
||||
yield NodeItem("GeometryNodeDistributePointsOnFaces")
|
||||
yield NodeItem("GeometryNodePoints")
|
||||
yield NodeItem("GeometryNodePointsToVertices")
|
||||
yield NodeItem("GeometryNodePointsToVolume")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
yield NodeItem("GeometryNodeSetPointRadius")
|
||||
|
||||
|
||||
# Generic node group items generator for shader, compositor, geometry and texture node groups.
|
||||
def node_group_items(context):
|
||||
if context is None:
|
||||
@ -648,122 +448,17 @@ texture_node_categories = [
|
||||
]),
|
||||
]
|
||||
|
||||
geometry_node_categories = [
|
||||
# Geometry Nodes
|
||||
GeometryNodeCategory("GEO_ATTRIBUTE", "Attribute", items=[
|
||||
NodeItem("GeometryNodeCaptureAttribute"),
|
||||
NodeItem("GeometryNodeAttributeDomainSize"),
|
||||
NodeItem("GeometryNodeAttributeStatistic"),
|
||||
NodeItem("GeometryNodeRemoveAttribute"),
|
||||
NodeItem("GeometryNodeStoreNamedAttribute"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_COLOR", "Color", items=[
|
||||
NodeItem("ShaderNodeMix", label="Mix Color", settings={"data_type": "'RGBA'"}),
|
||||
NodeItem("ShaderNodeRGBCurve"),
|
||||
NodeItem("ShaderNodeValToRGB"),
|
||||
NodeItem("FunctionNodeSeparateColor"),
|
||||
NodeItem("FunctionNodeCombineColor"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_CURVE", "Curve", items=curve_node_items),
|
||||
GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[
|
||||
NodeItem("GeometryNodeCurvePrimitiveLine"),
|
||||
NodeItem("GeometryNodeCurvePrimitiveCircle"),
|
||||
NodeItem("GeometryNodeCurveStar"),
|
||||
NodeItem("GeometryNodeCurveSpiral"),
|
||||
NodeItem("GeometryNodeCurveArc"),
|
||||
NodeItem("GeometryNodeCurveQuadraticBezier"),
|
||||
NodeItem("GeometryNodeCurvePrimitiveQuadrilateral"),
|
||||
NodeItem("GeometryNodeCurvePrimitiveBezierSegment"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=geometry_node_items),
|
||||
GeometryNodeCategory("GEO_INPUT", "Input", items=geometry_input_node_items),
|
||||
GeometryNodeCategory("GEO_INSTANCE", "Instances", items=geometry_instance_node_items),
|
||||
GeometryNodeCategory("GEO_MATERIAL", "Material", items=geometry_material_node_items),
|
||||
GeometryNodeCategory("GEO_MESH", "Mesh", items=mesh_node_items),
|
||||
GeometryNodeCategory("GEO_PRIMITIVES_MESH", "Mesh Primitives", items=[
|
||||
NodeItem("GeometryNodeMeshCircle"),
|
||||
NodeItem("GeometryNodeMeshCone"),
|
||||
NodeItem("GeometryNodeMeshCube"),
|
||||
NodeItem("GeometryNodeMeshCylinder"),
|
||||
NodeItem("GeometryNodeMeshGrid"),
|
||||
NodeItem("GeometryNodeMeshIcoSphere"),
|
||||
NodeItem("GeometryNodeMeshLine"),
|
||||
NodeItem("GeometryNodeMeshUVSphere"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_OUTPUT", "Output", items=[
|
||||
NodeItem("GeometryNodeViewer"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_POINT", "Point", items=point_node_items),
|
||||
GeometryNodeCategory("GEO_TEXT", "Text", items=[
|
||||
NodeItem("FunctionNodeStringLength"),
|
||||
NodeItem("FunctionNodeSliceString"),
|
||||
NodeItem("FunctionNodeValueToString"),
|
||||
NodeItem("GeometryNodeStringJoin"),
|
||||
NodeItem("FunctionNodeInputSpecialCharacters"),
|
||||
NodeItem("GeometryNodeStringToCurves"),
|
||||
NodeItem("FunctionNodeReplaceString"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_TEXTURE", "Texture", items=[
|
||||
NodeItem("ShaderNodeTexBrick"),
|
||||
NodeItem("ShaderNodeTexChecker"),
|
||||
NodeItem("ShaderNodeTexGradient"),
|
||||
NodeItem("ShaderNodeTexMagic"),
|
||||
NodeItem("ShaderNodeTexMusgrave"),
|
||||
NodeItem("ShaderNodeTexNoise"),
|
||||
NodeItem("ShaderNodeTexVoronoi"),
|
||||
NodeItem("ShaderNodeTexWave"),
|
||||
NodeItem("ShaderNodeTexWhiteNoise"),
|
||||
NodeItem("GeometryNodeImageTexture"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
|
||||
NodeItem("GeometryNodeAccumulateField"),
|
||||
NodeItem("GeometryNodeFieldAtIndex"),
|
||||
NodeItem("GeometryNodeFieldOnDomain"),
|
||||
NodeItem("ShaderNodeMapRange"),
|
||||
NodeItem("ShaderNodeFloatCurve"),
|
||||
NodeItem("ShaderNodeClamp"),
|
||||
NodeItem("ShaderNodeMath"),
|
||||
NodeItem("FunctionNodeBooleanMath"),
|
||||
NodeItem("FunctionNodeRotateEuler"),
|
||||
NodeItem("FunctionNodeCompare"),
|
||||
NodeItem("ShaderNodeMix"),
|
||||
NodeItem("FunctionNodeFloatToInt"),
|
||||
NodeItem("GeometryNodeSwitch"),
|
||||
NodeItem("FunctionNodeRandomValue"),
|
||||
NodeItem("FunctionNodeAlignEulerToVector"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_UV", "UV", items=uv_node_items),
|
||||
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
|
||||
NodeItem("ShaderNodeVectorCurve"),
|
||||
NodeItem("ShaderNodeSeparateXYZ"),
|
||||
NodeItem("ShaderNodeCombineXYZ"),
|
||||
NodeItem("ShaderNodeVectorMath"),
|
||||
NodeItem("ShaderNodeVectorRotate"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
|
||||
NodeItem("GeometryNodeVolumeCube"),
|
||||
NodeItem("GeometryNodeVolumeToMesh"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_GROUP", "Group", items=node_group_items),
|
||||
GeometryNodeCategory("GEO_LAYOUT", "Layout", items=[
|
||||
NodeItem("NodeFrame"),
|
||||
NodeItem("NodeReroute"),
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def register():
|
||||
nodeitems_utils.register_node_categories('SHADER', shader_node_categories)
|
||||
nodeitems_utils.register_node_categories('COMPOSITING', compositor_node_categories)
|
||||
nodeitems_utils.register_node_categories('TEXTURE', texture_node_categories)
|
||||
nodeitems_utils.register_node_categories('GEOMETRY', geometry_node_categories)
|
||||
|
||||
|
||||
def unregister():
|
||||
nodeitems_utils.unregister_node_categories('SHADER')
|
||||
nodeitems_utils.unregister_node_categories('COMPOSITING')
|
||||
nodeitems_utils.unregister_node_categories('TEXTURE')
|
||||
nodeitems_utils.unregister_node_categories('GEOMETRY')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
Reference in New Issue
Block a user