diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index a57a2cc5a4c..eaf61b58e6d 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -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", diff --git a/release/scripts/startup/bl_ui/node_add_menu.py b/release/scripts/startup/bl_ui/node_add_menu.py new file mode 100644 index 00000000000..17bff9a5087 --- /dev/null +++ b/release/scripts/startup/bl_ui/node_add_menu.py @@ -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) diff --git a/release/scripts/startup/bl_ui/node_add_menu_geometry.py b/release/scripts/startup/bl_ui/node_add_menu_geometry.py new file mode 100644 index 00000000000..d164d0d2c83 --- /dev/null +++ b/release/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -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) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 118928ef9c6..f4070a8289d 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -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 diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 38629c18ca0..798ac9e37a5 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -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__":