From 39a3b44a72a3860bd98d271c166b44fa18363ef3 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 28 May 2025 05:41:37 +0200 Subject: [PATCH] Nodes: support searching for outputs of various input nodes directly Previously, one had to search for the name of an input node (Geometry, Light Path, etc.) instead of for the actual desired values. This patch makes it possible to search for the output names of various input nodes directly. All other outputs of the input node are hidden automatically. This was partially support for the Scene Time before. Supported nodes: * Compositor: Scene Time * Geometry Nodes: Camera Info, Mouse Position, Scene Time, Viewport Transform * Shader Nodes: Camera Data, Curves Info, Geometry, Volume Info, Light Path, Object Info, Particle Info Right now, the output names are hardcoded in the menu. We don't have a great way to access those without an actual node instance currently. For that we'll need to make the node declarations available in Python, which is a good project but out of scope for this this feature. It also does not seem too bad to have more explicit control over what's shown in the search. Pull Request: https://projects.blender.org/blender/blender/pulls/139477 --- scripts/startup/bl_operators/node.py | 12 ++++- scripts/startup/bl_ui/node_add_menu.py | 6 ++- .../startup/bl_ui/node_add_menu_compositor.py | 2 +- .../startup/bl_ui/node_add_menu_geometry.py | 23 +++++++-- scripts/startup/bl_ui/node_add_menu_shader.py | 50 ++++++++++++++++--- 5 files changed, 78 insertions(+), 15 deletions(-) diff --git a/scripts/startup/bl_operators/node.py b/scripts/startup/bl_operators/node.py index 1a7a04855ac..1ed3e731ceb 100644 --- a/scripts/startup/bl_operators/node.py +++ b/scripts/startup/bl_operators/node.py @@ -139,11 +139,21 @@ class NODE_OT_add_node(NodeAddOperator, Operator): description="Node type", ) + visible_output: StringProperty( + name="Output Name", + description="If provided, all outputs that are named differently will be hidden", + options={'SKIP_SAVE'}, + ) + # Default execute simply adds a node. def execute(self, context): if self.properties.is_property_set("type"): self.deselect_nodes(context) - self.create_node(context, self.type) + if node := self.create_node(context, self.type): + if self.visible_output: + for socket in node.outputs: + if socket.name != self.visible_output: + socket.hide = True return {'FINISHED'} else: return {'CANCELLED'} diff --git a/scripts/startup/bl_ui/node_add_menu.py b/scripts/startup/bl_ui/node_add_menu.py index 30a0676afad..98b59989bf8 100644 --- a/scripts/startup/bl_ui/node_add_menu.py +++ b/scripts/startup/bl_ui/node_add_menu.py @@ -25,7 +25,7 @@ def add_node_type(layout, node_type, *, label=None, poll=None, search_weight=0.0 return props -def add_node_type_with_subnames(context, layout, node_type, subnames, *, label=None, search_weight=0.0): +def add_node_type_with_outputs(context, layout, node_type, subnames, *, label=None, search_weight=0.0): bl_rna = bpy.types.Node.bl_rna_get_subclass(node_type) if not label: label = bl_rna.name if bl_rna else "Unknown" @@ -35,7 +35,9 @@ def add_node_type_with_subnames(context, layout, node_type, subnames, *, label=N if getattr(context, "is_menu_search", False): for subname in subnames: sublabel = "{} ▸ {}".format(iface_(label), iface_(subname)) - props.append(add_node_type(layout, node_type, label=sublabel, search_weight=search_weight)) + item_props = add_node_type(layout, node_type, label=sublabel, search_weight=search_weight) + item_props.visible_output = subname + props.append(item_props) return props diff --git a/scripts/startup/bl_ui/node_add_menu_compositor.py b/scripts/startup/bl_ui/node_add_menu_compositor.py index 269597f4936..378a780be63 100644 --- a/scripts/startup/bl_ui/node_add_menu_compositor.py +++ b/scripts/startup/bl_ui/node_add_menu_compositor.py @@ -57,7 +57,7 @@ class NODE_MT_category_compositor_input_scene(Menu): def draw(self, context): layout = self.layout node_add_menu.add_node_type(layout, "CompositorNodeRLayers") - node_add_menu.add_node_type_with_subnames(context, layout, "CompositorNodeSceneTime", ["Frame", "Seconds"]) + node_add_menu.add_node_type_with_outputs(context, layout, "CompositorNodeSceneTime", ["Frame", "Seconds"]) node_add_menu.add_node_type(layout, "CompositorNodeTime") node_add_menu.draw_assets_for_catalog(layout, "Input/Scene") diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index 3f3a687f7b9..40d4572f71c 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -339,17 +339,32 @@ class NODE_MT_geometry_node_GEO_INPUT_SCENE(Menu): if context.space_data.geometry_nodes_type == 'TOOL': node_add_menu.add_node_type(layout, "GeometryNodeTool3DCursor") node_add_menu.add_node_type(layout, "GeometryNodeInputActiveCamera") - node_add_menu.add_node_type(layout, "GeometryNodeCameraInfo") + node_add_menu.add_node_type_with_outputs(context, + layout, + "GeometryNodeCameraInfo", + ["Projection Matrix", + "Focal Length", + "Sensor", + "Shift", + "Clip Start", + "Clip End", + "Focus Distance", + "Is Orthographic", + "Orthographic Scale"]) node_add_menu.add_node_type(layout, "GeometryNodeCollectionInfo") node_add_menu.add_node_type(layout, "GeometryNodeImageInfo") node_add_menu.add_node_type(layout, "GeometryNodeIsViewport") if context.space_data.geometry_nodes_type == 'TOOL': - node_add_menu.add_node_type(layout, "GeometryNodeToolMousePosition") + node_add_menu.add_node_type_with_outputs( + context, layout, "GeometryNodeToolMousePosition", [ + "Mouse X", "Mouse Y", "Region Width", "Region Height"]) node_add_menu.add_node_type(layout, "GeometryNodeObjectInfo") - node_add_menu.add_node_type_with_subnames(context, layout, "GeometryNodeInputSceneTime", ["Frame", "Seconds"]) + node_add_menu.add_node_type_with_outputs(context, layout, "GeometryNodeInputSceneTime", ["Frame", "Seconds"]) node_add_menu.add_node_type(layout, "GeometryNodeSelfObject") if context.space_data.geometry_nodes_type == 'TOOL': - node_add_menu.add_node_type(layout, "GeometryNodeViewportTransform") + node_add_menu.add_node_type_with_outputs( + context, layout, "GeometryNodeViewportTransform", [ + "Projection", "View", "Is Orthographic"]) node_add_menu.draw_assets_for_catalog(layout, "Input/Scene") diff --git a/scripts/startup/bl_ui/node_add_menu_shader.py b/scripts/startup/bl_ui/node_add_menu_shader.py index 4289326d200..118299c73f6 100644 --- a/scripts/startup/bl_ui/node_add_menu_shader.py +++ b/scripts/startup/bl_ui/node_add_menu_shader.py @@ -58,15 +58,50 @@ class NODE_MT_category_shader_input(Menu): node_add_menu.add_node_type(layout, "ShaderNodeAmbientOcclusion") node_add_menu.add_node_type(layout, "ShaderNodeAttribute") node_add_menu.add_node_type(layout, "ShaderNodeBevel") - node_add_menu.add_node_type(layout, "ShaderNodeCameraData") + node_add_menu.add_node_type_with_outputs( + context, layout, "ShaderNodeCameraData", [ + "View Vector", "View Z Depth", "View Distance"]) node_add_menu.add_node_type(layout, "ShaderNodeVertexColor") - node_add_menu.add_node_type(layout, "ShaderNodeHairInfo") + node_add_menu.add_node_type_with_outputs( + context, layout, "ShaderNodeHairInfo", [ + "Is Strand", "Intercept", "Length", "Thickness", "Tangent Normal", "Random"]) node_add_menu.add_node_type(layout, "ShaderNodeFresnel") - node_add_menu.add_node_type(layout, "ShaderNodeNewGeometry") + node_add_menu.add_node_type_with_outputs(context, + layout, + "ShaderNodeNewGeometry", + ["Position", + "Normal", + "Tangent", + "True Normal", + "Incoming", + "Parametric", + "Backfacing", + "Pointiness", + "Random Per Island"]) node_add_menu.add_node_type(layout, "ShaderNodeLayerWeight") - node_add_menu.add_node_type(layout, "ShaderNodeLightPath") - node_add_menu.add_node_type(layout, "ShaderNodeObjectInfo") - node_add_menu.add_node_type(layout, "ShaderNodeParticleInfo") + node_add_menu.add_node_type_with_outputs(context, + layout, + "ShaderNodeLightPath", + ["Is Camera Ray", + "Is Shadow Ray", + "Is Diffuse Ray", + "Is Glossy Ray", + "Is Singular Ray", + "Is Reflection Ray", + "Is Transmission Ray", + "Is Volume Scatter Ray", + "Ray Length", + "Ray Depth", + "Diffuse Depth", + "Glossy Depth", + "Transparent Depth", + "Transmission Depth"]) + node_add_menu.add_node_type_with_outputs( + context, layout, "ShaderNodeObjectInfo", [ + "Location", "Color", "Alpha", "Object Index", "Material Index", "Random"]) + node_add_menu.add_node_type_with_outputs( + context, layout, "ShaderNodeParticleInfo", [ + "Index", "Random", "Age", "Lifetime", "Location", "Size", "Velocity", "Angular Velocity"]) node_add_menu.add_node_type(layout, "ShaderNodePointInfo") node_add_menu.add_node_type(layout, "ShaderNodeRGB") node_add_menu.add_node_type(layout, "ShaderNodeTangent") @@ -74,7 +109,8 @@ class NODE_MT_category_shader_input(Menu): node_add_menu.add_node_type(layout, "ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll(context)) node_add_menu.add_node_type(layout, "ShaderNodeUVMap") node_add_menu.add_node_type(layout, "ShaderNodeValue") - node_add_menu.add_node_type(layout, "ShaderNodeVolumeInfo") + node_add_menu.add_node_type_with_outputs(context, layout, "ShaderNodeVolumeInfo", + ["Color", "Density", "Flame", "Temperature"]) node_add_menu.add_node_type(layout, "ShaderNodeWireframe") node_add_menu.draw_assets_for_catalog(layout, self.bl_label)