Blender V5.0
socket_search_link.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <fmt/format.h>
6
7#include "BLI_listbase.h"
8#include "BLI_set.hh"
9
10#include "BKE_context.hh"
11#include "BKE_node.hh"
12
13#include "UI_interface.hh"
14
15#include "BLT_translation.hh"
16
18#include "NOD_socket.hh"
20
21namespace blender::nodes {
22
23void GatherLinkSearchOpParams::add_item(std::string socket_name,
25 const int weight)
26{
27 std::string name = fmt::format("{}{} " UI_MENU_ARROW_SEP " {}",
28 IFACE_(node_type_.ui_name),
29 node_type_.deprecation_notice ? IFACE_(" (Deprecated)") : "",
30 socket_name);
31 this->add_item_full_name(std::move(name), std::move(fn), weight);
32}
33
36 int weight)
37{
38 items_.append({std::move(name), std::move(fn), weight});
39}
40
42{
43 return other_socket_;
44}
45
47{
48 return snode_;
49}
50
52{
53 return node_tree_;
54}
55
57{
58 return node_type_;
59}
60
62{
63 return other_socket_.in_out == SOCK_IN ? SOCK_OUT : SOCK_IN;
64}
65
67{
68 const eNodeSocketInOut in_out = socket.in_out == SOCK_IN ? SOCK_OUT : SOCK_IN;
69 bNodeSocket *new_node_socket = bke::node_find_enabled_socket(new_node, in_out, socket_name);
70 if (new_node_socket == nullptr) {
71 /* If the socket isn't found, some node's search gather functions probably aren't configured
72 * properly. It's likely enough that it's worth avoiding a crash in a release build though. */
74 return;
75 }
76 this->connect_socket(new_node, *new_node_socket);
77}
78
80 const StringRef socket_identifier)
81{
82 const eNodeSocketInOut in_out = this->socket.in_out == SOCK_IN ? SOCK_OUT : SOCK_IN;
83 bNodeSocket *new_node_socket = bke::node_find_socket(new_node, in_out, socket_identifier);
84 BLI_assert(new_node_socket);
85 this->connect_socket(new_node, *new_node_socket);
86}
87
89{
90 bke::node_add_link(this->node_tree, new_node, new_socket, this->node, this->socket);
91 if (new_socket.in_out == SOCK_OUT) {
92 /* If the old socket already contained a value, then transfer it to a new one, from
93 * which this value will get there. */
95 *CTX_data_main(&C), this->node_tree, this->socket, new_socket);
96 }
97}
98
100{
102 BLI_assert(node != nullptr);
103 added_nodes_.append(node);
104 return *node;
105}
106
108{
109 return this->add_node(node_type.idname);
110}
111
113 StringRef socket_name)
114{
116 if (new_node.typeinfo->updatefunc) {
117 new_node.typeinfo->updatefunc(&node_tree, &new_node);
118 }
119 this->connect_available_socket(new_node, socket_name);
120}
121
123 Span<SocketDeclaration *> declarations)
124{
125 const bke::bNodeType &node_type = params.node_type();
126
127 const SocketDeclaration *main_socket = nullptr;
128 Vector<const SocketDeclaration *> connectable_sockets;
129
130 Set<StringRef> socket_names;
131 for (const int i : declarations.index_range()) {
132 const SocketDeclaration &socket = *declarations[i];
133 if (!socket_names.add(socket.name)) {
134 /* Don't add sockets with the same name to the search. Needed to support being called from
135 * #search_link_ops_for_basic_node, which should have "okay" behavior for nodes with
136 * duplicate socket names. */
137 continue;
138 }
139 if (!socket.can_connect(params.other_socket())) {
140 continue;
141 }
142 if (socket.is_default_link_socket || main_socket == nullptr) {
143 /* Either the first connectable or explicitly tagged socket is the main socket. */
144 main_socket = &socket;
145 }
146 connectable_sockets.append(&socket);
147 }
148 for (const int i : connectable_sockets.index_range()) {
149 const SocketDeclaration &socket = *connectable_sockets[i];
150 /* Give non-main sockets a lower weight so that they don't show up at the top of the search
151 * when they are not explicitly searched for. The -1 is used to make sure that the first socket
152 * has a smaller weight than zero so that it does not have the same weight as the main socket.
153 * Negative weights are used to avoid making the highest weight dependent on the number of
154 * sockets. */
155 const int weight = (&socket == main_socket) ? 0 : -1 - i;
156 params.add_item(
157 IFACE_(socket.name),
158 [&node_type, &socket](LinkSearchOpParams &params) {
159 bNode &node = params.add_node(node_type);
160 socket.make_available(node);
161 params.update_and_connect_available_socket(node, socket.name);
162 },
163 weight);
164 }
165}
166
168{
169 const bke::bNodeType &node_type = params.node_type();
170 if (!node_type.static_declaration) {
171 return;
172 }
173 const NodeDeclaration &declaration = *node_type.static_declaration;
175}
176
177} // namespace blender::nodes
Main * CTX_data_main(const bContext *C)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define IFACE_(msgid)
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void append(const T &value)
IndexRange index_range() const
const bke::bNodeType & node_type() const
void add_item(std::string socket_name, SocketLinkOperation::LinkSocketFn fn, int weight=0)
void add_item_full_name(std::string name, SocketLinkOperation::LinkSocketFn fn, int weight=0)
void connect_available_socket(bNode &new_node, StringRef socket_name)
void connect_available_socket_by_identifier(bNode &new_node, StringRef socket_identifier)
void connect_socket(bNode &new_node, bNodeSocket &new_socket)
void update_and_connect_available_socket(bNode &new_node, StringRef socket_name)
Span< SocketDeclaration * > sockets(eNodeSocketInOut in_out) const
virtual bool can_connect(const bNodeSocket &socket) const =0
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2532
bNode * node_add_node(const bContext *C, bNodeTree &ntree, StringRef idname, std::optional< int > unique_identifier=std::nullopt)
Definition node.cc:3477
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:3810
bNodeSocket * node_find_enabled_socket(bNode &node, eNodeSocketInOut in_out, StringRef name)
Definition node.cc:2553
void node_socket_move_default_value(Main &bmain, bNodeTree &tree, bNodeSocket &src, bNodeSocket &dst)
Definition node.cc:3724
void search_link_ops_for_basic_node(GatherLinkSearchOpParams &params)
void search_link_ops_for_declarations(GatherLinkSearchOpParams &params, Span< SocketDeclaration * > declarations)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
const char * name
#define UI_MENU_ARROW_SEP
bNodeTypeHandle * typeinfo
Defines a node type.
Definition BKE_node.hh:238
blender::nodes::NodeDeclaration * static_declaration
Definition BKE_node.hh:371
std::function< void(LinkSearchOpParams &link_params)> LinkSocketFn
i
Definition text_draw.cc:230