[Bf-blender-cvs] [11be151d58e] master: Node Editor: Link Drag Search Menu

Hans Goudey noreply at git.blender.org
Wed Dec 15 16:52:07 CET 2021


Commit: 11be151d58ec0ca955f019b0eed738e3245110b8
Author: Hans Goudey
Date:   Wed Dec 15 09:51:57 2021 -0600
Branches: master
https://developer.blender.org/rB11be151d58ec0ca955f019b0eed738e3245110b8

Node Editor: Link Drag Search Menu

This commit adds a search menu when links are dragged above empty
space. When releasing the drag, a menu displays all compatible
sockets with the source link. The "main" sockets (usually the first)
are weighted above other sockets in the search, so they appear first
when you type the name of the node.

A few special operators for creating a reroute or a group input node
are also added to the search.

Translation is started after choosing a node so it can be placed
quickly, since users would likely adjust the position after anyway.

A small "+" is displayed next to the cursor to give a hint about this.

Further improvements are possible after this first iteration:
 - Support custom node trees.
 - Better drawing of items in the search menu.
 - Potential tweaks to filtering of items, depending on user feedback.

Thanks to Juanfran Matheu for developing an initial patch.

Differential Revision: https://developer.blender.org/D8286

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

M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.cc
M	source/blender/editors/space_node/CMakeLists.txt
A	source/blender/editors/space_node/link_drag_search.cc
M	source/blender/editors/space_node/node_intern.hh
M	source/blender/editors/space_node/node_relationships.cc
M	source/blender/nodes/CMakeLists.txt
M	source/blender/nodes/NOD_geometry.h
M	source/blender/nodes/NOD_node_declaration.hh
M	source/blender/nodes/NOD_socket_declarations.hh
M	source/blender/nodes/NOD_socket_declarations_geometry.hh
A	source/blender/nodes/NOD_socket_search_link.hh
M	source/blender/nodes/composite/node_composite_util.cc
M	source/blender/nodes/function/node_function_util.cc
M	source/blender/nodes/function/nodes/node_fn_random_value.cc
M	source/blender/nodes/geometry/node_geometry_tree.cc
M	source/blender/nodes/geometry/node_geometry_util.cc
M	source/blender/nodes/geometry/node_geometry_util.hh
M	source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
M	source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
M	source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
M	source/blender/nodes/geometry/nodes/node_geo_raycast.cc
M	source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
M	source/blender/nodes/geometry/nodes/node_geo_switch.cc
M	source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
M	source/blender/nodes/geometry/nodes/node_geo_viewer.cc
M	source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
M	source/blender/nodes/intern/node_declaration.cc
M	source/blender/nodes/intern/node_socket.cc
M	source/blender/nodes/intern/node_socket_declarations.cc
A	source/blender/nodes/intern/socket_search_link.cc
M	source/blender/nodes/shader/node_shader_tree.c
M	source/blender/nodes/shader/node_shader_util.cc
M	source/blender/nodes/shader/nodes/node_shader_math.cc
M	source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc
M	source/blender/nodes/shader/nodes/node_shader_tex_noise.cc
M	source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc
M	source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc
M	source/blender/nodes/shader/nodes/node_shader_vector_math.cc

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

diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 2038842ee59..a2959556810 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -33,6 +33,10 @@
 
 #include "RNA_types.h"
 
+#ifdef __cplusplus
+#  include "BLI_string_ref.hh"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -114,6 +118,7 @@ namespace nodes {
 class NodeMultiFunctionBuilder;
 class GeoNodeExecParams;
 class NodeDeclarationBuilder;
+class GatherLinkSearchOpParams;
 }  // namespace nodes
 namespace fn {
 class CPPType;
@@ -129,10 +134,15 @@ using SocketGetCPPValueFunction = void (*)(const struct bNodeSocket &socket, voi
 using SocketGetGeometryNodesCPPValueFunction = void (*)(const struct bNodeSocket &socket,
                                                         void *r_value);
 
+/* Adds socket link operations that are specific to this node type. */
+using NodeGatherSocketLinkOperationsFunction =
+    void (*)(blender::nodes::GatherLinkSearchOpParams &params);
+
 #else
 typedef void *NodeMultiFunctionBuildFunction;
 typedef void *NodeGeometryExecFunction;
 typedef void *NodeDeclareFunction;
+typedef void *NodeGatherSocketLinkOperationsFunction;
 typedef void *SocketGetCPPTypeFunction;
 typedef void *SocketGetGeometryNodesCPPTypeFunction;
 typedef void *SocketGetGeometryNodesCPPValueFunction;
@@ -284,7 +294,7 @@ typedef struct bNodeType {
 
   /**
    * Can this node type be added to a node tree?
-   * \param r_disabled_hint: Optional hint to display in the UI when the poll fails.
+   * \param r_disabled_hint: Hint to display in the UI when the poll fails.
    *                         The callback can set this to a static string without having to
    *                         null-check it (or without setting it to null if it's not used).
    *                         The caller must pass a valid `const char **` and null-initialize it
@@ -325,6 +335,13 @@ typedef struct bNodeType {
   /* Declaration to be used when it is not dynamic. */
   NodeDeclarationHandle *fixed_declaration;
 
+  /**
+   * Add to the list of search names and operations gathered by node link drag searching.
+   * Usually it isn't necessary to override the default behavior here, but a node type can have
+   * custom behavior here like adding custom search items.
+   */
+  NodeGatherSocketLinkOperationsFunction gather_link_search_ops;
+
   /** True when the node cannot be muted. */
   bool no_muting;
 
@@ -402,7 +419,7 @@ typedef struct bNodeTreeType {
   /* Tree update. Overrides `nodetype->updatetreefunc` ! */
   void (*update)(struct bNodeTree *ntree);
 
-  bool (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link);
+  bool (*validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to);
 
   void (*node_add_init)(struct bNodeTree *ntree, struct bNode *bnode);
 
@@ -1768,6 +1785,18 @@ extern struct bNodeSocketType NodeSocketTypeUndefined;
 }
 #endif
 
+#ifdef __cplusplus
+
+namespace blender::bke {
+
+bNodeSocket *node_find_enabled_socket(bNode &node, eNodeSocketInOut in_out, StringRef name);
+bNodeSocket *node_find_enabled_input_socket(bNode &node, StringRef name);
+bNodeSocket *node_find_enabled_output_socket(bNode &node, StringRef name);
+
+}  // namespace blender::bke
+
+#endif
+
 #define NODE_STORAGE_FUNCS(StorageT) \
   [[maybe_unused]] static StorageT &node_storage(bNode &node) \
   { \
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index a4de6730f8f..be458ed036e 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -102,6 +102,7 @@ using blender::MutableSpan;
 using blender::Set;
 using blender::Span;
 using blender::Stack;
+using blender::StringRef;
 using blender::Vector;
 using blender::VectorSet;
 using blender::nodes::FieldInferencingInterface;
@@ -1522,6 +1523,33 @@ struct bNodeSocket *nodeFindSocket(const bNode *node,
   return nullptr;
 }
 
+namespace blender::bke {
+
+bNodeSocket *node_find_enabled_socket(bNode &node,
+                                      const eNodeSocketInOut in_out,
+                                      const StringRef name)
+{
+  ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs;
+  LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
+    if (!(socket->flag & SOCK_UNAVAIL) && socket->name == name) {
+      return socket;
+    }
+  }
+  return nullptr;
+}
+
+bNodeSocket *node_find_enabled_input_socket(bNode &node, StringRef name)
+{
+  return node_find_enabled_socket(node, SOCK_IN, name);
+}
+
+bNodeSocket *node_find_enabled_output_socket(bNode &node, StringRef name)
+{
+  return node_find_enabled_socket(node, SOCK_OUT, name);
+}
+
+}  // namespace blender::bke
+
 /* find unique socket identifier */
 static bool unique_identifier_check(void *arg, const char *identifier)
 {
@@ -4459,7 +4487,8 @@ static void ntree_validate_links(bNodeTree *ntree)
       link->flag &= ~NODE_LINK_VALID;
     }
     else if (ntree->typeinfo->validate_link) {
-      if (!ntree->typeinfo->validate_link(ntree, link)) {
+      if (!ntree->typeinfo->validate_link((eNodeSocketDatatype)link->fromsock->type,
+                                          (eNodeSocketDatatype)link->tosock->type)) {
         link->flag &= ~NODE_LINK_VALID;
       }
     }
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index e88d61fe880..94b67e43651 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -39,6 +39,7 @@ set(INC
 
 set(SRC
   drawnode.cc
+  link_drag_search.cc
   node_add.cc
   node_context_path.cc
   node_draw.cc
diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc
new file mode 100644
index 00000000000..e1ba36e81c0
--- /dev/null
+++ b/source/blender/editors/space_node/link_drag_search.cc
@@ -0,0 +1,291 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_string_search.h"
+
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+
+#include "NOD_socket_search_link.hh"
+
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+
+#include "node_intern.hh"
+
+using blender::nodes::SocketLinkOperation;
+
+namespace blender::ed::space_node {
+
+struct LinkDragSearchStorage {
+  bNode &from_node;
+  bNodeSocket &from_socket;
+  float2 cursor;
+  Vector<SocketLinkOperation> search_link_ops;
+  char search[256];
+
+  eNodeSocketInOut in_out() const
+  {
+    return static_cast<eNodeSocketInOut>(from_socket.in_out);
+  }
+};
+
+static void add_reroute_node_fn(nodes::LinkSearchOpParams &params)
+{
+  bNode &reroute = params.add_node("NodeReroute");
+  if (params.socket.in_out == SOCK_IN) {
+    nodeAddLink(&params.node_tree,
+                &reroute,
+                static_cast<bNodeSocket *>(reroute.outputs.first),
+                &params.node,
+                &params.socket);
+  }
+  else {
+    nodeAddLink(&params.node_tree,
+                &params.node,
+                &params.socket,
+                &reroute,
+                static_cast<bNodeSocket *>(reroute.inputs.first));
+  }
+}
+
+static void add_group_input_node_fn(nodes::LinkSearchOpParams &params)
+{
+  /* Add a group input based on the connected socket, and add a new group input node. */
+  bNodeSocket *interface_socket = ntreeAddSocketInterfaceFromSocket(
+      &params.node_tree, &params.node, &params.socket);
+  const int group_input_index = BLI_findindex(&params.node_tree.inputs, interface_socket);
+
+  bNode &group_input = params.add_node("NodeGroupInput");
+
+  /* This is necessary to create the new sockets in the other input nodes. */
+  ntreeUpdateTree(CTX_data_main(&params.C), &params.node_tree);
+
+  /* Hide the new input in all other group input nodes, to avoid making them taller. */
+  LISTBASE_FOREACH (bNode *, node, &params.node_tree.nodes) {
+    if (node->type == NODE_GROUP_INPUT) {
+      bNodeSocket *new_group_input_socket = (bNodeSocket *)BLI_findlink(&node->outputs,
+                                                                        group_input_index);
+      new_group_input_socket->flag |= SOCK_HIDDEN;
+    }
+  }
+
+  /* Hide all existing inputs in the new group input node, to only display the new one. */
+  LISTBASE_FOREACH (bNodeSocket *, socket, &group_input.outputs) {
+    socket->flag |= SOCK_HIDDEN;
+  }
+
+  bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&group_input.outputs, group_input_index);
+  if (socket == nullptr) {
+    /* Adding sockets can fail in some cases. There's no good reason not to be safe here. */
+    return;
+  }
+  /* Unhide the socket for the new input in the new node and make a connection to it. */
+  socket->flag &= ~SOCK_HIDDEN;
+  nodeAddLink(&params.node_tree, &group_input, socket, &params.node, &params.socket);
+}
+
+/**
+ * Call the callback to gather compatible socket connections for all node types, and the operations
+ * that will actually make the connections. Also add some custom operations like connecting a group
+ * output node.
+ */
+static void gather_socket_link_operations(bNodeTree &node_tree,
+                                          const bNodeSocket &socket,
+                                          Vector<SocketLinkOperation> &search_link_ops)
+{
+  NODE_TYPES_BEGIN (node_type) {
+    if (StringRef(node_type->idname).find("Legacy") != StringRef::not_found) {
+      continue;
+    }
+    const cha

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list