[Bf-blender-cvs] [837144b4577] master: Nodes: Use plain menus for geometry nodes add menu

Hans Goudey noreply at git.blender.org
Mon Sep 26 20:20:16 CEST 2022


Commit: 837144b4577f161baf1625f8a5478c83a088ea0f
Author: Hans Goudey
Date:   Mon Sep 26 12:36:13 2022 -0500
Branches: master
https://developer.blender.org/rB837144b4577f161baf1625f8a5478c83a088ea0f

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

===================================================================

M	release/scripts/startup/bl_ui/__init__.py
A	release/scripts/startup/bl_ui/node_add_menu.py
A	release/scripts/startup/bl_ui/node_add_menu_geometry.py
M	release/scripts/startup/bl_ui/space_node.py
M	release/scripts/startup/nodeitems_builtins.py

===================================================================

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_typ

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list