Blender  V3.3
socket_search_link.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_set.hh"
4 
5 #include "BKE_node.h"
6 
7 #include "UI_interface.h"
8 
9 #include "BLT_translation.h"
10 
11 #include "NOD_node_declaration.hh"
13 
14 namespace blender::nodes {
15 
16 void GatherLinkSearchOpParams::add_item(std::string socket_name,
18  const int weight)
19 {
20 
21  std::string name = std::string(IFACE_(node_type_.ui_name)) + " " + UI_MENU_ARROW_SEP +
22  socket_name;
23 
24  items_.append({std::move(name), std::move(fn), weight});
25 }
26 
28 {
29  return other_socket_;
30 }
31 
33 {
34  return node_tree_;
35 }
36 
38 {
39  return node_type_;
40 }
41 
43 {
44  return other_socket_.in_out == SOCK_IN ? SOCK_OUT : SOCK_IN;
45 }
46 
48 {
49  const eNodeSocketInOut in_out = socket.in_out == SOCK_IN ? SOCK_OUT : SOCK_IN;
50  bNodeSocket *new_node_socket = bke::node_find_enabled_socket(new_node, in_out, socket_name);
51  if (new_node_socket == nullptr) {
52  /* If the socket isn't found, some node's search gather functions probably aren't configured
53  * properly. It's likely enough that it's worth avoiding a crash in a release build though. */
55  return;
56  }
57  nodeAddLink(&node_tree, &new_node, new_node_socket, &node, &socket);
58 }
59 
61 {
62  std::string idname_str = idname;
63  bNode *node = nodeAddNode(&C, &node_tree, idname_str.c_str());
64  BLI_assert(node != nullptr);
65  added_nodes_.append(node);
66  return *node;
67 }
68 
70 {
71  return this->add_node(node_type.idname);
72 }
73 
75  StringRef socket_name)
76 {
77  if (new_node.typeinfo->updatefunc) {
78  new_node.typeinfo->updatefunc(&node_tree, &new_node);
79  }
80  this->connect_available_socket(new_node, socket_name);
81 }
82 
84  Span<SocketDeclarationPtr> declarations)
85 {
86  const bNodeType &node_type = params.node_type();
87 
88  const SocketDeclaration *main_socket = nullptr;
89  Vector<const SocketDeclaration *> connectable_sockets;
90 
91  Set<StringRef> socket_names;
92  for (const int i : declarations.index_range()) {
93  const SocketDeclaration &socket = *declarations[i];
94  if (!socket_names.add(socket.name())) {
95  /* Don't add sockets with the same name to the search. Needed to support being called from
96  * #search_link_ops_for_basic_node, which should have "okay" behavior for nodes with
97  * duplicate socket names. */
98  continue;
99  }
100  if (!socket.can_connect(params.other_socket())) {
101  continue;
102  }
103  if (socket.is_default_link_socket() || main_socket == nullptr) {
104  /* Either the first connectable or explicitly tagged socket is the main socket. */
105  main_socket = &socket;
106  }
107  connectable_sockets.append(&socket);
108  }
109  for (const int i : connectable_sockets.index_range()) {
110  const SocketDeclaration &socket = *connectable_sockets[i];
111  /* Give non-main sockets a lower weight so that they don't show up at the top of the search
112  * when they are not explicitly searched for. The -1 is used to make sure that the first socket
113  * has a smaller weight than zero so that it does not have the same weight as the main socket.
114  * Negative weights are used to avoid making the highest weight dependent on the number of
115  * sockets. */
116  const int weight = (&socket == main_socket) ? 0 : -1 - i;
117  params.add_item(
118  IFACE_(socket.name().c_str()),
119  [&node_type, &socket](LinkSearchOpParams &params) {
120  bNode &node = params.add_node(node_type);
121  socket.make_available(node);
122  params.update_and_connect_available_socket(node, socket.name());
123  },
124  weight);
125  }
126 }
127 
129  const bNodeSocketTemplate *templates,
130  const eNodeSocketInOut in_out)
131 {
132  const bNodeType &node_type = params.node_type();
133  const bNodeTreeType &node_tree_type = *params.node_tree().typeinfo;
134 
135  Set<StringRef> socket_names;
136  for (const bNodeSocketTemplate *socket_template = templates; socket_template->type != -1;
137  socket_template++) {
138  eNodeSocketDatatype from = (eNodeSocketDatatype)socket_template->type;
139  eNodeSocketDatatype to = (eNodeSocketDatatype)params.other_socket().type;
140  if (in_out == SOCK_IN) {
141  std::swap(from, to);
142  }
143  if (node_tree_type.validate_link && !node_tree_type.validate_link(from, to)) {
144  continue;
145  }
146  if (!socket_names.add(socket_template->name)) {
147  /* See comment in #search_link_ops_for_declarations. */
148  continue;
149  }
150 
151  params.add_item(
152  socket_template->name, [socket_template, node_type, in_out](LinkSearchOpParams &params) {
153  bNode &node = params.add_node(node_type);
154  bNodeSocket *new_node_socket = bke::node_find_enabled_socket(
155  node, in_out, socket_template->name);
156  if (new_node_socket != nullptr) {
157  /* Rely on the way #nodeAddLink switches in/out if necessary. */
158  nodeAddLink(&params.node_tree, &params.node, &params.socket, &node, new_node_socket);
159  }
160  });
161  }
162 }
163 
165 {
166  const bNodeType &node_type = params.node_type();
167 
168  if (node_type.declare) {
169  if (node_type.declaration_is_dynamic) {
170  /* Dynamic declarations (whatever they end up being) aren't supported
171  * by this function, but still avoid a crash in release builds. */
173  return;
174  }
175 
176  const NodeDeclaration &declaration = *node_type.fixed_declaration;
177 
178  search_link_ops_for_declarations(params, declaration.sockets(params.in_out()));
179  }
180  else if (node_type.inputs && params.in_out() == SOCK_IN) {
182  }
183  else if (node_type.outputs && params.in_out() == SOCK_OUT) {
185  }
186 }
187 
188 } // namespace blender::nodes
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2296
struct bNode * nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname)
Definition: node.cc:2133
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define IFACE_(msgid)
void swap(T &a, T &b)
Definition: Common.h:19
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
eNodeSocketDatatype
bool add(const Key &key)
Definition: BLI_set.hh:253
constexpr IndexRange index_range() const
Definition: BLI_span.hh:401
constexpr const char * c_str() const
void append(const T &value)
Definition: BLI_vector.hh:433
IndexRange index_range() const
Definition: BLI_vector.hh:920
void add_item(std::string socket_name, SocketLinkOperation::LinkSocketFn fn, int weight=0)
const bNodeSocket & other_socket() const
void connect_available_socket(bNode &new_node, StringRef socket_name)
bNode & add_node(StringRef idname)
void update_and_connect_available_socket(bNode &new_node, StringRef socket_name)
Span< SocketDeclarationPtr > sockets(eNodeSocketInOut in_out) const
virtual bool can_connect(const bNodeSocket &socket) const =0
OperationNode * node
StackEntry * from
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
bNodeSocket * node_find_enabled_socket(bNode &node, const eNodeSocketInOut in_out, const StringRef name)
Definition: node.cc:1464
void search_link_ops_for_basic_node(GatherLinkSearchOpParams &params)
static void search_link_ops_for_socket_templates(GatherLinkSearchOpParams &params, const bNodeSocketTemplate *templates, const eNodeSocketInOut in_out)
void search_link_ops_for_declarations(GatherLinkSearchOpParams &params, Span< SocketDeclarationPtr > declarations)
#define UI_MENU_ARROW_SEP
Compact definition of a node socket.
Definition: BKE_node.h:84
bool(* validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to)
Definition: BKE_node.h:402
Defines a node type.
Definition: BKE_node.h:226
char ui_name[64]
Definition: BKE_node.h:230
void(* updatefunc)(struct bNodeTree *ntree, struct bNode *node)
Definition: BKE_node.h:265
bNodeSocketTemplate * outputs
Definition: BKE_node.h:239
bool declaration_is_dynamic
Definition: BKE_node.h:326
NodeDeclareFunction declare
Definition: BKE_node.h:324
bNodeSocketTemplate * inputs
Definition: BKE_node.h:239
char idname[64]
Definition: BKE_node.h:227
NodeDeclarationHandle * fixed_declaration
Definition: BKE_node.h:328
struct bNodeType * typeinfo
std::function< void(LinkSearchOpParams &link_params)> LinkSocketFn