Blender V4.3
node_common.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstddef>
10#include <cstring>
11
12#include "DNA_asset_types.h"
13#include "DNA_node_types.h"
14
15#include "BLI_listbase.h"
16#include "BLI_map.hh"
18#include "BLI_set.hh"
19#include "BLI_stack.hh"
20#include "BLI_string.h"
21#include "BLI_string_ref.hh"
22#include "BLI_utildefines.h"
23
24#include "BLT_translation.hh"
25
26#include "BKE_node.hh"
27#include "BKE_node_runtime.hh"
29
30#include "MEM_guardedalloc.h"
31
32#include "NOD_common.h"
34#include "NOD_register.hh"
35#include "NOD_socket.hh"
38#include "node_common.h"
39#include "node_util.hh"
40
41using blender::Map;
43using blender::Set;
44using blender::Stack;
46using blender::Vector;
47
49
50/* -------------------------------------------------------------------- */
55{
56 LISTBASE_FOREACH (bNodeSocket *, socket, &sockets) {
57 if (socket->identifier == identifier) {
58 return socket;
59 }
60 }
61 return nullptr;
62}
63
64bNodeSocket *node_group_find_input_socket(bNode *groupnode, const char *identifier)
65{
66 return find_matching_socket(groupnode->inputs, identifier);
67}
68
69bNodeSocket *node_group_find_output_socket(bNode *groupnode, const char *identifier)
70{
71 return find_matching_socket(groupnode->outputs, identifier);
72}
73
74void node_group_label(const bNodeTree * /*ntree*/,
75 const bNode *node,
76 char *label,
77 int label_maxncpy)
78{
80 label, (node->id) ? node->id->name + 2 : IFACE_("Missing Data-Block"), label_maxncpy);
81}
82
121
123 const bNodeTree *nodetree,
124 const char **r_disabled_hint)
125{
126 if (!node->typeinfo->poll(node->typeinfo, nodetree, r_disabled_hint)) {
127 return false;
128 }
129 const bNodeTree *grouptree = reinterpret_cast<const bNodeTree *>(node->id);
130 if (!grouptree) {
131 return true;
132 }
133 return blender::bke::node_group_poll(nodetree, grouptree, r_disabled_hint);
134}
135
136std::string node_group_ui_description(const bNode &node)
137{
138 if (!node.id) {
139 return "";
140 }
141 const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node.id);
142 if (group->id.asset_data) {
143 if (group->id.asset_data->description) {
144 return group->id.asset_data->description;
145 }
146 }
147 if (!group->description) {
148 return "";
149 }
150 return group->description;
151}
152
154 const bNodeTree *grouptree,
155 const char **r_disabled_hint)
156{
157 /* unspecified node group, generally allowed
158 * (if anything, should be avoided on operator level)
159 */
160 if (grouptree == nullptr) {
161 return true;
162 }
163
164 if (nodetree == grouptree) {
165 if (r_disabled_hint) {
166 *r_disabled_hint = RPT_("Nesting a node group inside of itself is not allowed");
167 }
168 return false;
169 }
170 if (nodetree->type != grouptree->type) {
171 if (r_disabled_hint) {
172 *r_disabled_hint = RPT_("Node group has different type");
173 }
174 return false;
175 }
176
177 for (const bNode *node : grouptree->all_nodes()) {
178 if (node->typeinfo->poll_instance &&
179 !node->typeinfo->poll_instance(node, nodetree, r_disabled_hint))
180 {
181 return false;
182 }
183 }
184 return true;
185}
186
187namespace blender::nodes {
188
189static std::function<ID *(const bNode &node)> get_default_id_getter(
190 const bNodeTreeInterface &tree_interface, const bNodeTreeInterfaceSocket &io_socket)
191{
192 const int item_index = tree_interface.find_item_index(io_socket.item);
193 BLI_assert(item_index >= 0);
194
195 /* Avoid capturing pointers that can become dangling. */
196 return [item_index](const bNode &node) -> ID * {
197 if (node.id == nullptr) {
198 return nullptr;
199 }
200 if (GS(node.id->name) != ID_NT) {
201 return nullptr;
202 }
203 const bNodeTree &ntree = *reinterpret_cast<const bNodeTree *>(node.id);
204 const bNodeTreeInterfaceItem *io_item = ntree.tree_interface.get_item_at_index(item_index);
205 if (io_item == nullptr || io_item->item_type != NODE_INTERFACE_SOCKET) {
206 return nullptr;
207 }
208 const bNodeTreeInterfaceSocket &io_socket =
210 return *static_cast<ID **>(io_socket.socket_data);
211 };
212}
213
214static std::function<void(bNode &node, bNodeSocket &socket, const char *data_path)>
216{
217 const int item_index = interface.find_item_index(io_socket.item);
218 BLI_assert(item_index >= 0);
219
220 /* Avoid capturing pointers that can become dangling. */
221 return [item_index](bNode &node, bNodeSocket &socket, const char *data_path) {
222 if (node.id == nullptr) {
223 return;
224 }
225 if (GS(node.id->name) != ID_NT) {
226 return;
227 }
228 bNodeTree &ntree = *reinterpret_cast<bNodeTree *>(node.id);
229 const bNodeTreeInterfaceItem *io_item = ntree.tree_interface.get_item_at_index(item_index);
230 if (io_item == nullptr || io_item->item_type != NODE_INTERFACE_SOCKET) {
231 return;
232 }
233 const bNodeTreeInterfaceSocket &io_socket =
235 blender::bke::bNodeSocketType *typeinfo = io_socket.socket_typeinfo();
236 if (typeinfo && typeinfo->interface_init_socket) {
237 typeinfo->interface_init_socket(&ntree.id, &io_socket, &node, &socket, data_path);
238 }
239 };
240}
241
242/* in_out overrides the socket declaration in/out type (bNodeTreeInterfaceSocket::flag)
243 * because a node group input is turned into an output socket for group input nodes. */
245 const bNodeTree &ntree,
246 const bNodeTreeInterfaceSocket &io_socket,
247 const eNodeSocketInOut in_out)
248{
250
252 io_socket.socket_type);
254 if (base_typeinfo) {
255 datatype = eNodeSocketDatatype(base_typeinfo->type);
256 switch (datatype) {
257 case SOCK_FLOAT: {
259 std::unique_ptr<decl::Float> decl = std::make_unique<decl::Float>();
260 decl->subtype = PropertySubType(value.subtype);
261 decl->default_value = value.value;
262 decl->soft_min_value = value.min;
263 decl->soft_max_value = value.max;
264 dst = std::move(decl);
265 break;
266 }
267 case SOCK_VECTOR: {
269 std::unique_ptr<decl::Vector> decl = std::make_unique<decl::Vector>();
270 decl->subtype = PropertySubType(value.subtype);
271 decl->default_value = value.value;
272 decl->soft_min_value = value.min;
273 decl->soft_max_value = value.max;
274 dst = std::move(decl);
275 break;
276 }
277 case SOCK_RGBA: {
279 std::unique_ptr<decl::Color> decl = std::make_unique<decl::Color>();
280 decl->default_value = value.value;
281 dst = std::move(decl);
282 break;
283 }
284 case SOCK_SHADER: {
285 std::unique_ptr<decl::Shader> decl = std::make_unique<decl::Shader>();
286 dst = std::move(decl);
287 break;
288 }
289 case SOCK_BOOLEAN: {
291 std::unique_ptr<decl::Bool> decl = std::make_unique<decl::Bool>();
292 decl->default_value = value.value;
293 dst = std::move(decl);
294 break;
295 }
296 case SOCK_ROTATION: {
298 io_socket);
299 std::unique_ptr<decl::Rotation> decl = std::make_unique<decl::Rotation>();
300 decl->default_value = math::EulerXYZ(float3(value.value_euler));
301 dst = std::move(decl);
302 break;
303 }
304 case SOCK_MATRIX: {
305 std::unique_ptr<decl::Matrix> decl = std::make_unique<decl::Matrix>();
306 dst = std::move(decl);
307 break;
308 }
309 case SOCK_INT: {
310 const auto &value = node_interface::get_socket_data_as<bNodeSocketValueInt>(io_socket);
311 std::unique_ptr<decl::Int> decl = std::make_unique<decl::Int>();
312 decl->subtype = PropertySubType(value.subtype);
313 decl->default_value = value.value;
314 decl->soft_min_value = value.min;
315 decl->soft_max_value = value.max;
316 dst = std::move(decl);
317 break;
318 }
319 case SOCK_STRING: {
321 std::unique_ptr<decl::String> decl = std::make_unique<decl::String>();
322 decl->default_value = value.value;
323 decl->subtype = PropertySubType(value.subtype);
324 dst = std::move(decl);
325 break;
326 }
327 case SOCK_MENU: {
329 std::unique_ptr<decl::Menu> decl = std::make_unique<decl::Menu>();
330 decl->default_value = value.value;
331 dst = std::move(decl);
332 break;
333 }
334 case SOCK_OBJECT: {
335 auto value = std::make_unique<decl::Object>();
336 value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
337 dst = std::move(value);
338 break;
339 }
340 case SOCK_IMAGE: {
341 auto value = std::make_unique<decl::Image>();
342 value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
343 dst = std::move(value);
344 break;
345 }
346 case SOCK_GEOMETRY:
347 dst = std::make_unique<decl::Geometry>();
348 break;
349 case SOCK_COLLECTION: {
350 auto value = std::make_unique<decl::Collection>();
351 value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
352 dst = std::move(value);
353 break;
354 }
355 case SOCK_TEXTURE: {
356 auto value = std::make_unique<decl::Texture>();
357 value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
358 dst = std::move(value);
359 break;
360 }
361 case SOCK_MATERIAL: {
362 auto value = std::make_unique<decl::Material>();
363 value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
364 dst = std::move(value);
365 break;
366 }
367 case SOCK_CUSTOM: {
368 auto value = std::make_unique<decl::Custom>();
369 value->init_socket_fn = get_init_socket_fn(ntree.tree_interface, io_socket);
370 value->idname_ = io_socket.socket_type;
371 dst = std::move(value);
372 break;
373 }
374 }
375 }
376 else {
377 auto value = std::make_unique<decl::Custom>();
378 value->init_socket_fn = get_init_socket_fn(ntree.tree_interface, io_socket);
379 value->idname_ = io_socket.socket_type;
380 dst = std::move(value);
381 }
382 dst->name = io_socket.name ? io_socket.name : "";
383 dst->identifier = io_socket.identifier;
384 dst->in_out = in_out;
385 dst->socket_type = datatype;
386 dst->description = io_socket.description ? io_socket.description : "";
387 dst->hide_value = io_socket.flag & NODE_INTERFACE_SOCKET_HIDE_VALUE;
388 dst->compact = io_socket.flag & NODE_INTERFACE_SOCKET_COMPACT;
389 return dst;
390}
391
392/* Socket items can be both input and output, generating 2 declarations for 1 item. Count the
393 * actual declarations generated by panel content to get the true size for UI drawing. */
395{
396 int num_child_decls = 0;
397 io_panel.foreach_item([&](const bNodeTreeInterfaceItem &item) {
398 switch (item.item_type) {
399 case NODE_INTERFACE_PANEL:
400 num_child_decls++;
401 break;
402 case NODE_INTERFACE_SOCKET:
403 const bNodeTreeInterfaceSocket &socket =
404 reinterpret_cast<const bNodeTreeInterfaceSocket &>(item);
405 if (socket.flag & NODE_INTERFACE_SOCKET_INPUT) {
406 num_child_decls++;
407 }
408 if (socket.flag & NODE_INTERFACE_SOCKET_OUTPUT) {
409 num_child_decls++;
410 }
411 break;
412 }
413 return true;
414 });
415 return num_child_decls;
416}
417
419 const bNodeTreeInterfacePanel &io_panel)
420{
421 if (io_panel.items_num == 0) {
422 return nullptr;
423 }
424
425 PanelDeclarationPtr dst = std::make_unique<PanelDeclaration>();
426 dst->identifier = io_panel.identifier;
427 dst->name = io_panel.name ? io_panel.name : "";
428 dst->description = io_panel.description ? io_panel.description : "";
429 dst->default_collapsed = (io_panel.flag & NODE_INTERFACE_PANEL_DEFAULT_CLOSED);
430 dst->num_child_decls = count_panel_declaration_children(io_panel);
431 return dst;
432}
433
435{
436 if (decl.socket_type == SOCK_VECTOR) {
437 if (input.default_input == GEO_NODE_DEFAULT_FIELD_INPUT_NORMAL_FIELD) {
438 decl.implicit_input_fn = std::make_unique<ImplicitInputValueFn>(
439 implicit_field_inputs::normal);
440 decl.hide_value = true;
441 }
442 else if (input.default_input == GEO_NODE_DEFAULT_FIELD_INPUT_POSITION_FIELD) {
443 decl.implicit_input_fn = std::make_unique<ImplicitInputValueFn>(
444 implicit_field_inputs::position);
445 decl.hide_value = true;
446 }
447 }
448 else if (decl.socket_type == SOCK_INT) {
449 if (input.default_input == GEO_NODE_DEFAULT_FIELD_INPUT_INDEX_FIELD) {
450 decl.implicit_input_fn = std::make_unique<ImplicitInputValueFn>(
451 implicit_field_inputs::index);
452 decl.hide_value = true;
453 }
454 else if (input.default_input == GEO_NODE_DEFAULT_FIELD_INPUT_ID_INDEX_FIELD) {
455 decl.implicit_input_fn = std::make_unique<ImplicitInputValueFn>(
456 implicit_field_inputs::id_or_index);
457 decl.hide_value = true;
458 }
459 }
460 else if (decl.socket_type == SOCK_MATRIX) {
461 decl.implicit_input_fn = std::make_unique<ImplicitInputValueFn>(
462 implicit_field_inputs::instance_transform);
463 decl.hide_value = true;
464 }
465}
466
468{
469 const bNode *node = b.node_or_null();
470 if (node == nullptr) {
471 return;
472 }
473 NodeDeclaration &r_declaration = b.declaration();
474 const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node->id);
475 if (!group) {
476 return;
477 }
478 if (ID_IS_LINKED(&group->id) && (group->id.tag & ID_TAG_MISSING)) {
479 r_declaration.skip_updating_sockets = true;
480 return;
481 }
482 r_declaration.skip_updating_sockets = false;
483
484 /* Allow the node group interface to define the socket order. */
485 r_declaration.use_custom_socket_order = true;
486
487 group->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) {
488 switch (item.item_type) {
490 const bNodeTreeInterfaceSocket &socket =
492
495 *group, socket, SOCK_IN) :
496 nullptr;
499 *group, socket, SOCK_OUT) :
500 nullptr;
501 if (output_decl) {
502 r_declaration.outputs.append(output_decl.get());
503 r_declaration.items.append(std::move(output_decl));
504 }
505 if (input_decl) {
506 r_declaration.inputs.append(input_decl.get());
507 r_declaration.items.append(std::move(input_decl));
508 }
509 break;
510 }
512 const bNodeTreeInterfacePanel &panel =
514 if (PanelDeclarationPtr panel_decl = declaration_for_interface_panel(*group, panel)) {
515 r_declaration.items.append(std::move(panel_decl));
516 }
517 break;
518 }
519 }
520 return true;
521 });
522
523 if (group->type == NTREE_GEOMETRY) {
524 group->ensure_interface_cache();
525 const Span<const bNodeTreeInterfaceSocket *> inputs = group->interface_inputs();
526 const FieldInferencingInterface &field_interface =
527 *group->runtime->field_inferencing_interface;
528 for (const int i : inputs.index_range()) {
529 SocketDeclaration &decl = *r_declaration.inputs[i];
530 decl.input_field_type = field_interface.inputs[i];
531 set_default_input_field(*inputs[i], decl);
532 }
533
534 for (const int i : r_declaration.outputs.index_range()) {
535 r_declaration.outputs[i]->output_field_dependency = field_interface.outputs[i];
536 }
537 }
538}
539
540} // namespace blender::nodes
541
544/* -------------------------------------------------------------------- */
548static void node_frame_init(bNodeTree * /*ntree*/, bNode *node)
549{
550 NodeFrame *data = MEM_cnew<NodeFrame>("frame node storage");
551 node->storage = data;
552
553 data->flag |= NODE_FRAME_SHRINK;
554
555 data->label_size = 20;
556}
557
559{
560 /* frame type is used for all tree types, needs dynamic allocation */
561 blender::bke::bNodeType *ntype = MEM_cnew<blender::bke::bNodeType>("frame node type");
562 ntype->free_self = (void (*)(blender::bke::bNodeType *))MEM_freeN;
563
565 ntype->initfunc = node_frame_init;
568 blender::bke::node_type_size(ntype, 150, 100, 0);
569 ntype->flag |= NODE_BACKGROUND;
570
572}
573
576/* -------------------------------------------------------------------- */
581{
582 const bNode *node = b.node_or_null();
583 if (node == nullptr) {
584 return;
585 }
586
587 const blender::StringRefNull socket_idname(
588 static_cast<const NodeReroute *>(node->storage)->type_idname);
589 b.add_input<blender::nodes::decl::Custom>("Input").idname(socket_idname.c_str());
590 b.add_output<blender::nodes::decl::Custom>("Output").idname(socket_idname.c_str());
591}
592
593static void node_reroute_init(bNodeTree * /*ntree*/, bNode *node)
594{
595 NodeReroute *data = MEM_cnew<NodeReroute>(__func__);
596 STRNCPY(data->type_idname, "NodeSocketColor");
597 node->storage = data;
598}
599
601{
602 /* frame type is used for all tree types, needs dynamic allocation */
603 blender::bke::bNodeType *ntype = MEM_cnew<blender::bke::bNodeType>("frame node type");
604 ntype->free_self = (void (*)(blender::bke::bNodeType *))MEM_freeN;
605
609 node_type_storage(ntype, "NodeReroute", node_free_standard_storage, node_copy_standard_storage);
610
612}
613
615 bNodeSocket *start_socket,
618{
619 Stack<bNode *> nodes_to_check;
620 for (bNodeLink *link : links_map.lookup(start_socket)) {
621 if (link->tonode->type == NODE_REROUTE) {
622 nodes_to_check.push(link->tonode);
623 }
624 if (link->fromnode->type == NODE_REROUTE) {
625 nodes_to_check.push(link->fromnode);
626 }
627 }
628 const blender::bke::bNodeSocketType *current_type = start_socket->typeinfo;
629 while (!nodes_to_check.is_empty()) {
630 bNode *reroute_node = nodes_to_check.pop();
631 BLI_assert(reroute_node->type == NODE_REROUTE);
632 if (r_reroute_types.add(reroute_node, current_type)) {
633 for (bNodeLink *link : links_map.lookup((bNodeSocket *)reroute_node->inputs.first)) {
634 if (link->fromnode->type == NODE_REROUTE) {
635 nodes_to_check.push(link->fromnode);
636 }
637 }
638 for (bNodeLink *link : links_map.lookup((bNodeSocket *)reroute_node->outputs.first)) {
639 if (link->tonode->type == NODE_REROUTE) {
640 nodes_to_check.push(link->tonode);
641 }
642 }
643 }
644 }
645}
646
648{
649 /* Contains nodes that are linked to at least one reroute node. */
650 Set<bNode *> nodes_linked_with_reroutes;
651 /* Contains all links that are linked to at least one reroute node. */
653 /* Build acceleration data structures for the algorithm below. */
654 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
655 if (link->fromsock == nullptr || link->tosock == nullptr) {
656 continue;
657 }
658 if (link->fromnode->type != NODE_REROUTE && link->tonode->type != NODE_REROUTE) {
659 continue;
660 }
661 if (link->fromnode->type != NODE_REROUTE) {
662 nodes_linked_with_reroutes.add(link->fromnode);
663 }
664 if (link->tonode->type != NODE_REROUTE) {
665 nodes_linked_with_reroutes.add(link->tonode);
666 }
667 links_map.add(link->fromsock, link);
668 links_map.add(link->tosock, link);
669 }
670
671 /* Will contain the socket type for every linked reroute node. */
673
674 /* Propagate socket types from left to right. */
675 for (bNode *start_node : nodes_linked_with_reroutes) {
676 LISTBASE_FOREACH (bNodeSocket *, output_socket, &start_node->outputs) {
677 propagate_reroute_type_from_start_socket(output_socket, links_map, reroute_types);
678 }
679 }
680
681 /* Propagate socket types from right to left. This affects reroute nodes that haven't been
682 * changed in the loop above. */
683 for (bNode *start_node : nodes_linked_with_reroutes) {
684 LISTBASE_FOREACH (bNodeSocket *, input_socket, &start_node->inputs) {
685 propagate_reroute_type_from_start_socket(input_socket, links_map, reroute_types);
686 }
687 }
688
689 /* Actually update reroute nodes with changed types. */
690 for (const auto item : reroute_types.items()) {
691 bNode *reroute_node = item.key;
692 const blender::bke::bNodeSocketType *socket_type = item.value;
693 NodeReroute *storage = static_cast<NodeReroute *>(reroute_node->storage);
694 STRNCPY(storage->type_idname, socket_type->idname);
696 }
697}
698
700{
701 ntree->ensure_topology_cache();
702 Stack<const bNode *> nodes_to_check;
703 for (const bNodeSocket *socket : node->output_sockets()) {
704 for (const bNodeLink *link : socket->directly_linked_links()) {
705 nodes_to_check.push(link->tonode);
706 }
707 }
708 while (!nodes_to_check.is_empty()) {
709 const bNode *next_node = nodes_to_check.pop();
710 for (const bNodeSocket *socket : next_node->output_sockets()) {
711 for (const bNodeLink *link : socket->directly_linked_links()) {
712 if (link->tonode->typeinfo->nclass == NODE_CLASS_OUTPUT &&
713 link->tonode->flag & NODE_DO_OUTPUT)
714 {
715 return true;
716 }
717 nodes_to_check.push(link->tonode);
718 }
719 }
720 }
721
722 return false;
723}
724
727/* -------------------------------------------------------------------- */
731bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
732{
733 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
734 if (STREQ(sock->identifier, identifier)) {
735 return sock;
736 }
737 }
738 return nullptr;
739}
740
741namespace blender::nodes {
742
744{
745 const bNodeTree *node_tree = b.tree_or_null();
746 if (node_tree == nullptr) {
747 return;
748 }
749 NodeDeclaration &r_declaration = b.declaration();
750 node_tree->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) {
751 switch (item.item_type) {
752 case NODE_INTERFACE_SOCKET: {
753 const bNodeTreeInterfaceSocket &socket =
754 node_interface::get_item_as<bNodeTreeInterfaceSocket>(item);
755 if (socket.flag & NODE_INTERFACE_SOCKET_INPUT) {
756 SocketDeclarationPtr socket_decl = declaration_for_interface_socket(
757 *node_tree, socket, SOCK_OUT);
758 r_declaration.outputs.append(socket_decl.get());
759 r_declaration.items.append(std::move(socket_decl));
760 }
761 break;
762 }
763 }
764 return true;
765 });
766 SocketDeclarationPtr extend_decl = decl::create_extend_declaration(SOCK_OUT);
767 r_declaration.outputs.append(extend_decl.get());
768 r_declaration.items.append(std::move(extend_decl));
769}
770
772{
773 const bNodeTree *node_tree = b.tree_or_null();
774 if (node_tree == nullptr) {
775 return;
776 }
777 NodeDeclaration &r_declaration = b.declaration();
778 node_tree->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) {
779 switch (item.item_type) {
780 case NODE_INTERFACE_SOCKET: {
781 const bNodeTreeInterfaceSocket &socket =
782 node_interface::get_item_as<bNodeTreeInterfaceSocket>(item);
783 if (socket.flag & NODE_INTERFACE_SOCKET_OUTPUT) {
784 SocketDeclarationPtr socket_decl = declaration_for_interface_socket(
785 *node_tree, socket, SOCK_IN);
786 r_declaration.inputs.append(socket_decl.get());
787 r_declaration.items.append(std::move(socket_decl));
788 }
789 break;
790 }
791 }
792 return true;
793 });
794 SocketDeclarationPtr extend_decl = decl::create_extend_declaration(SOCK_IN);
795 r_declaration.inputs.append(extend_decl.get());
796 r_declaration.items.append(std::move(extend_decl));
797}
798
799static bool group_input_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
800{
801 BLI_assert(link->tonode != node);
802 BLI_assert(link->tosock->in_out == SOCK_IN);
803 if (!StringRef(link->fromsock->identifier).startswith("__extend__")) {
804 return true;
805 }
806 if (StringRef(link->tosock->identifier).startswith("__extend__")) {
807 /* Don't connect to other "extend" sockets. */
808 return false;
809 }
811 *ntree, *link->tonode, *link->tosock);
812 if (!io_socket) {
813 return false;
814 }
816 link->fromsock = node_group_input_find_socket(node, io_socket->identifier);
817 return true;
818}
819
820static bool group_output_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
821{
822 BLI_assert(link->fromnode != node);
824 if (!StringRef(link->tosock->identifier).startswith("__extend__")) {
825 return true;
826 }
827 if (StringRef(link->fromsock->identifier).startswith("__extend__")) {
828 /* Don't connect to other "extend" sockets. */
829 return false;
830 }
832 *ntree, *link->fromnode, *link->fromsock);
833 if (!io_socket) {
834 return false;
835 }
837 link->tosock = node_group_output_find_socket(node, io_socket->identifier);
838 return true;
839}
840
841} // namespace blender::nodes
842
844{
845 /* used for all tree types, needs dynamic allocation */
846 blender::bke::bNodeType *ntype = MEM_cnew<blender::bke::bNodeType>("node type");
847 ntype->free_self = (void (*)(blender::bke::bNodeType *))MEM_freeN;
848
850 blender::bke::node_type_size(ntype, 140, 80, 400);
853
855}
856
857bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
858{
859 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
860 if (STREQ(sock->identifier, identifier)) {
861 return sock;
862 }
863 }
864 return nullptr;
865}
866
868{
869 /* used for all tree types, needs dynamic allocation */
870 blender::bke::bNodeType *ntype = MEM_cnew<blender::bke::bNodeType>("node type");
871 ntype->free_self = (void (*)(blender::bke::bNodeType *))MEM_freeN;
872
874 blender::bke::node_type_size(ntype, 140, 80, 400);
877
878 ntype->no_muting = true;
879
881}
882
#define NODE_CLASS_OUTPUT
Definition BKE_node.hh:405
#define NODE_REROUTE
Definition BKE_node.hh:804
#define NODE_CLASS_INTERFACE
Definition BKE_node.hh:416
#define NODE_CLASS_MATTE
Definition BKE_node.hh:411
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:410
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:418
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define NODE_CLASS_DISTORT
Definition BKE_node.hh:412
#define NODE_CLASS_OP_VECTOR
Definition BKE_node.hh:407
#define NODE_CLASS_LAYOUT
Definition BKE_node.hh:420
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:406
#define NODE_CLASS_INPUT
Definition BKE_node.hh:404
#define NODE_CLASS_OP_FILTER
Definition BKE_node.hh:408
#define NODE_FRAME
Definition BKE_node.hh:803
#define NODE_CLASS_GROUP
Definition BKE_node.hh:409
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#define NODE_CLASS_ATTRIBUTE
Definition BKE_node.hh:419
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:414
#define NODE_CLASS_SHADER
Definition BKE_node.hh:417
#define NODE_CLASS_SCRIPT
Definition BKE_node.hh:415
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STREQ(a, b)
#define RPT_(msgid)
#define IFACE_(msgid)
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
@ ID_TAG_MISSING
Definition DNA_ID.h:813
@ ID_NT
@ NODE_INTERFACE_PANEL_DEFAULT_CLOSED
@ NODE_INTERFACE_SOCKET_COMPACT
@ NODE_INTERFACE_SOCKET_HIDE_VALUE
@ GEO_NODE_DEFAULT_FIELD_INPUT_POSITION_FIELD
@ GEO_NODE_DEFAULT_FIELD_INPUT_NORMAL_FIELD
@ GEO_NODE_DEFAULT_FIELD_INPUT_ID_INDEX_FIELD
@ GEO_NODE_DEFAULT_FIELD_INPUT_INDEX_FIELD
@ NTREE_GEOMETRY
@ NODE_DO_OUTPUT
@ NODE_BACKGROUND
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_TEXTURE
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_SHADER
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_CUSTOM
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_OBJECT
@ SOCK_STRING
@ SOCK_RGBA
@ SOCK_MENU
@ NODE_FRAME_SHRINK
Read Guarded memory(de)allocation.
PropertySubType
Definition RNA_types.hh:135
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
ItemIterator items() const
Definition BLI_map.hh:864
Span< Value > lookup(const Key &key) const
void add(const Key &key, const Value &value)
bool add(const Key &key)
Definition BLI_set.hh:248
bool is_empty() const
Definition BLI_stack.hh:308
void push(const T &value)
Definition BLI_stack.hh:213
constexpr bool startswith(StringRef prefix) const
constexpr const char * c_str() const
void append(const T &value)
Vector< ItemDeclarationPtr > items
Vector< SocketDeclaration * > inputs
Vector< SocketDeclaration * > outputs
std::unique_ptr< ImplicitInputValueFn > implicit_input_fn
local_group_size(16, 16) .push_constant(Type b
OperationNode * node
const char * label
#define GS(x)
Definition iris.cc:202
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
T & get_item_as(bNodeTreeInterfaceItem &item)
T & get_socket_data_as(bNodeTreeInterfaceSocket &item)
bNodeTreeInterfaceSocket * add_interface_socket_from_node(bNodeTree &ntree, const bNode &from_node, const bNodeSocket &from_sock, const StringRef socket_type, const StringRef name)
bool node_is_connected_to_output(const bNodeTree *ntree, const bNode *node)
bool node_group_poll(const bNodeTree *nodetree, const bNodeTree *grouptree, const char **r_disabled_hint)
bNodeSocketType * node_socket_type_find(const char *idname)
Definition node.cc:1763
void node_type_size(bNodeType *ntype, int width, int minwidth, int maxwidth)
Definition node.cc:4602
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
void node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
Definition node.cc:4325
EulerXYZBase< float > EulerXYZ
SocketDeclarationPtr create_extend_declaration(const eNodeSocketInOut in_out)
static void group_input_declare(NodeDeclarationBuilder &b)
static std::function< ID *(const bNode &node)> get_default_id_getter(const bNodeTreeInterface &tree_interface, const bNodeTreeInterfaceSocket &io_socket)
std::unique_ptr< SocketDeclaration > SocketDeclarationPtr
static bool group_input_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
static int count_panel_declaration_children(const bNodeTreeInterfacePanel &io_panel)
static SocketDeclarationPtr declaration_for_interface_socket(const bNodeTree &ntree, const bNodeTreeInterfaceSocket &io_socket, const eNodeSocketInOut in_out)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
static std::function< void(bNode &node, bNodeSocket &socket, const char *data_path)> get_init_socket_fn(const bNodeTreeInterface &interface, const bNodeTreeInterfaceSocket &io_socket)
void node_group_declare(NodeDeclarationBuilder &b)
std::unique_ptr< PanelDeclaration > PanelDeclarationPtr
static void group_output_declare(NodeDeclarationBuilder &b)
static PanelDeclarationPtr declaration_for_interface_panel(const bNodeTree &, const bNodeTreeInterfacePanel &io_panel)
static bool group_output_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
static void set_default_input_field(const bNodeTreeInterfaceSocket &input, SocketDeclaration &decl)
VecBase< float, 3 > float3
bNodeSocket * node_group_input_find_socket(bNode *node, const char *identifier)
static bNodeSocket * find_matching_socket(ListBase &sockets, StringRef identifier)
int node_group_ui_class(const bNode *node)
static void propagate_reroute_type_from_start_socket(bNodeSocket *start_socket, const MultiValueMap< bNodeSocket *, bNodeLink * > &links_map, Map< bNode *, const blender::bke::bNodeSocketType * > &r_reroute_types)
void register_node_type_group_output()
void node_group_label(const bNodeTree *, const bNode *node, char *label, int label_maxncpy)
void register_node_type_group_input()
void ntree_update_reroute_nodes(bNodeTree *ntree)
static void node_frame_init(bNodeTree *, bNode *node)
bool node_group_poll_instance(const bNode *node, const bNodeTree *nodetree, const char **r_disabled_hint)
static void node_reroute_init(bNodeTree *, bNode *node)
void register_node_type_frame()
bNodeSocket * node_group_find_output_socket(bNode *groupnode, const char *identifier)
bNodeSocket * node_group_output_find_socket(bNode *node, const char *identifier)
static void node_reroute_declare(blender::nodes::NodeDeclarationBuilder &b)
std::string node_group_ui_description(const bNode &node)
bNodeSocket * node_group_find_input_socket(bNode *groupnode, const char *identifier)
void register_node_type_reroute()
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
Definition DNA_ID.h:413
struct AssetMetaData * asset_data
Definition DNA_ID.h:422
void * first
char type_idname[64]
bNodeSocketTypeHandle * typeinfo
char identifier[64]
bNodeTreeInterface tree_interface
ListBase links
ListBase inputs
void * storage
ListBase outputs
int16_t type
Defines a socket type.
Definition BKE_node.hh:151
void(* interface_init_socket)(ID *id, const bNodeTreeInterfaceSocket *interface_socket, bNode *node, bNodeSocket *socket, const char *data_path)
Definition BKE_node.hh:165
Defines a node type.
Definition BKE_node.hh:218
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
bool(* insert_link)(bNodeTree *ntree, bNode *node, bNodeLink *link)
Definition BKE_node.hh:309
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* free_self)(bNodeType *ntype)
Definition BKE_node.hh:311