Blender V4.5
node_socket.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
8
9#include <climits>
10
11#include "DNA_node_types.h"
12
13#include "BLI_color.hh"
14#include "BLI_listbase.h"
15#include "BLI_math_euler.hh"
17#include "BLI_math_vector.h"
19#include "BLI_string.h"
20#include "BLI_utildefines.h"
21
22#include "BKE_geometry_set.hh"
23#include "BKE_lib_id.hh"
24#include "BKE_node.hh"
26#include "BKE_node_runtime.hh"
29
31#include "DNA_material_types.h"
32
33#include "RNA_access.hh"
34
35#include "MEM_guardedalloc.h"
36
40#include "NOD_socket.hh"
41
42using namespace blender;
45
47 bNode *node,
49 eNodeSocketInOut in_out)
50{
52 *ntree, *node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
53
54 sock->flag |= stemp->flag;
55
56 /* initialize default_value */
57 switch (stemp->type) {
58 case SOCK_FLOAT: {
60 dval->value = stemp->val1;
61 dval->min = stemp->min;
62 dval->max = stemp->max;
63 break;
64 }
65 case SOCK_INT: {
67 dval->value = int(stemp->val1);
68 dval->min = int(stemp->min);
69 dval->max = int(stemp->max);
70 break;
71 }
72 case SOCK_BOOLEAN: {
74 dval->value = int(stemp->val1);
75 break;
76 }
77 case SOCK_VECTOR: {
79 dval->value[0] = stemp->val1;
80 dval->value[1] = stemp->val2;
81 dval->value[2] = stemp->val3;
82 dval->dimensions = 3;
83 dval->min = stemp->min;
84 dval->max = stemp->max;
85 break;
86 }
87 case SOCK_RGBA: {
89 dval->value[0] = stemp->val1;
90 dval->value[1] = stemp->val2;
91 dval->value[2] = stemp->val3;
92 dval->value[3] = stemp->val4;
93 break;
94 }
95 }
96
97 return sock;
98}
99
101 bNode *node,
102 eNodeSocketInOut in_out,
103 ListBase *socklist,
105{
106 bNodeSocket *sock;
107
108 for (sock = (bNodeSocket *)socklist->first; sock; sock = sock->next) {
109 if (STREQLEN(sock->name, stemp->name, NODE_MAXSTR)) {
110 break;
111 }
112 }
113 if (sock) {
114 if (sock->type != stemp->type) {
115 bke::node_modify_socket_type_static(ntree, node, sock, stemp->type, stemp->subtype);
116 }
117 sock->flag |= stemp->flag;
118 }
119 else {
120 /* no socket for this template found, make a new one */
121 sock = node_add_socket_from_template(ntree, node, stemp, in_out);
122 }
123
124 /* remove the new socket from the node socket list first,
125 * will be added back after verification. */
126 BLI_remlink(socklist, sock);
127
128 return sock;
129}
130
132 bNode *node,
133 eNodeSocketInOut in_out,
134 ListBase *socklist,
135 bke::bNodeSocketTemplate *stemp_first)
136{
137 bNodeSocket *sock, *nextsock;
139
140 /* no inputs anymore? */
141 if (stemp_first == nullptr) {
142 for (sock = (bNodeSocket *)socklist->first; sock; sock = nextsock) {
143 nextsock = sock->next;
144 bke::node_remove_socket(*ntree, *node, *sock);
145 }
146 }
147 else {
148 /* step by step compare */
149 stemp = stemp_first;
150 while (stemp->type != -1) {
151 stemp->sock = verify_socket_template(ntree, node, in_out, socklist, stemp);
152 stemp++;
153 }
154 /* leftovers are removed */
155 for (sock = (bNodeSocket *)socklist->first; sock; sock = nextsock) {
156 nextsock = sock->next;
157 bke::node_remove_socket(*ntree, *node, *sock);
158 }
159
160 /* and we put back the verified sockets */
161 stemp = stemp_first;
162 if (socklist->first) {
163 /* Some dynamic sockets left, store the list start
164 * so we can add static sockets in front of it. */
165 sock = (bNodeSocket *)socklist->first;
166 while (stemp->type != -1) {
167 /* Put static sockets in front of dynamic. */
168 BLI_insertlinkbefore(socklist, sock, stemp->sock);
169 stemp++;
170 }
171 }
172 else {
173 while (stemp->type != -1) {
174 BLI_addtail(socklist, stemp->sock);
175 stemp++;
176 }
177 }
178 }
179}
180
181namespace blender::nodes {
182
184 bNode &node,
185 const SocketDeclaration &socket_decl,
186 Vector<bNodeSocket *> &old_sockets,
187 VectorSet<bNodeSocket *> &new_sockets,
188 const bool hide_new_sockets)
189{
190 /* Try to find a socket that corresponds to the declaration. */
191 bNodeSocket *old_socket_with_same_identifier = nullptr;
192 for (const int i : old_sockets.index_range()) {
193 bNodeSocket &old_socket = *old_sockets[i];
194 if (old_socket.identifier == socket_decl.identifier) {
195 old_sockets.remove_and_reorder(i);
196 old_socket_with_same_identifier = &old_socket;
197 break;
198 }
199 }
200 bNodeSocket *new_socket = nullptr;
201 if (old_socket_with_same_identifier == nullptr) {
202 /* Create a completely new socket. */
203 new_socket = &socket_decl.build(ntree, node);
204 SET_FLAG_FROM_TEST(new_socket->flag, hide_new_sockets, SOCK_HIDDEN);
205 }
206 else {
207 STRNCPY(old_socket_with_same_identifier->name, socket_decl.name.c_str());
208 if (socket_decl.matches(*old_socket_with_same_identifier)) {
209 /* The existing socket matches exactly, just use it. */
210 new_socket = old_socket_with_same_identifier;
211 }
212 else {
213 /* Clear out identifier to avoid name collisions when a new socket is created. */
214 old_socket_with_same_identifier->identifier[0] = '\0';
215 new_socket = &socket_decl.update_or_build(ntree, node, *old_socket_with_same_identifier);
216
217 if (new_socket == old_socket_with_same_identifier) {
218 /* The existing socket has been updated, set the correct identifier again. */
219 STRNCPY(new_socket->identifier, socket_decl.identifier.c_str());
220 }
221 else {
222 /* Move links to new socket with same identifier. */
223 LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
224 if (link->fromsock == old_socket_with_same_identifier) {
225 link->fromsock = new_socket;
226 }
227 else if (link->tosock == old_socket_with_same_identifier) {
228 link->tosock = new_socket;
229 }
230 }
231 for (bNodeLink &internal_link : node.runtime->internal_links) {
232 if (internal_link.fromsock == old_socket_with_same_identifier) {
233 internal_link.fromsock = new_socket;
234 }
235 else if (internal_link.tosock == old_socket_with_same_identifier) {
236 internal_link.tosock = new_socket;
237 }
238 }
239 }
240 }
242 new_socket->flag, old_socket_with_same_identifier->is_user_hidden(), SOCK_HIDDEN);
243 }
244 new_sockets.add_new(new_socket);
245 BKE_ntree_update_tag_socket_new(&ntree, new_socket);
246}
247
248static void refresh_node_panel(const PanelDeclaration &panel_decl,
249 Vector<bNodePanelState> &old_panels,
250 bNodePanelState &new_panel)
251{
252 /* Try to find a panel that corresponds to the declaration. */
253 bNodePanelState *old_panel_with_same_identifier = nullptr;
254 for (const int i : old_panels.index_range()) {
255 bNodePanelState &old_panel = old_panels[i];
256 if (old_panel.identifier == panel_decl.identifier) {
257 /* Panel is removed after copying to #new_panel. */
258 old_panel_with_same_identifier = &old_panel;
259 break;
260 }
261 }
262
263 if (old_panel_with_same_identifier == nullptr) {
264 /* Create a completely new panel. */
265 panel_decl.build(new_panel);
266 }
267 else {
268 if (panel_decl.matches(*old_panel_with_same_identifier)) {
269 /* The existing socket matches exactly, just use it. */
270 new_panel = *old_panel_with_same_identifier;
271 }
272 else {
273 /* Clear out identifier to avoid name collisions when a new panel is created. */
274 old_panel_with_same_identifier->identifier = -1;
275 panel_decl.update_or_build(*old_panel_with_same_identifier, new_panel);
276 }
277
278 /* Remove from old panels. */
279 const int64_t old_panel_index = old_panel_with_same_identifier - old_panels.begin();
280 old_panels.remove_and_reorder(old_panel_index);
281 }
282}
283
284static const char *get_identifier_from_decl(const char *identifier_prefix,
285 const bNodeSocket &socket,
286 const Span<const SocketDeclaration *> socket_decls)
287{
288 if (!BLI_str_startswith(socket.identifier, identifier_prefix)) {
289 return nullptr;
290 }
291 for (const SocketDeclaration *socket_decl : socket_decls) {
292 if (BLI_str_startswith(socket_decl->identifier.c_str(), identifier_prefix)) {
293 if (socket.type == socket_decl->socket_type) {
294 return socket_decl->identifier.c_str();
295 }
296 }
297 }
298 return nullptr;
299}
300
301static const char *get_identifier_from_decl(const Span<const char *> identifier_prefixes,
302 const bNodeSocket &socket,
303 const Span<const SocketDeclaration *> socket_decls)
304{
305 for (const char *identifier_prefix : identifier_prefixes) {
306 if (const char *identifier = get_identifier_from_decl(identifier_prefix, socket, socket_decls))
307 {
308 return identifier;
309 }
310 }
311 return nullptr;
312}
313
327 const bNode &node,
328 const bNodeSocket &socket,
329 const Span<const SocketDeclaration *> socket_decls)
330{
331 switch (node.type_legacy) {
333 return get_identifier_from_decl({"Min", "Max", "Value"}, socket, socket_decls);
334 }
335 case SH_NODE_MIX: {
336 return get_identifier_from_decl({"A", "B", "Result"}, socket, socket_decls);
337 }
338 case FN_NODE_COMPARE: {
339 if (STREQ(socket.identifier, "Angle")) {
340 return nullptr;
341 }
342 return get_identifier_from_decl({"A", "B"}, socket, socket_decls);
343 }
344 case SH_NODE_MAP_RANGE: {
345 if (socket.type == SOCK_VECTOR) {
346 if (STREQ(socket.identifier, "Value")) {
347 return "Vector";
348 }
349 if (STREQ(socket.identifier, "From Min")) {
350 return "From_Min_FLOAT3";
351 }
352 if (STREQ(socket.identifier, "From Max")) {
353 return "From_Max_FLOAT3";
354 }
355 if (STREQ(socket.identifier, "To Min")) {
356 return "To_Min_FLOAT3";
357 }
358 if (STREQ(socket.identifier, "To Max")) {
359 return "To_Max_FLOAT3";
360 }
361 if (STREQ(socket.identifier, "Steps")) {
362 return "Steps_FLOAT3";
363 }
364 if (STREQ(socket.identifier, "Result")) {
365 return "Vector";
366 }
367 }
368 return nullptr;
369 }
370 }
371 return nullptr;
372}
373
377static void do_forward_compat_versioning(bNode &node, const NodeDeclaration &node_decl)
378{
379 LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) {
380 if (socket->is_available()) {
381 if (const char *new_identifier = get_current_socket_identifier_for_future_socket(
382 node, *socket, node_decl.inputs))
383 {
384 STRNCPY(socket->identifier, new_identifier);
385 }
386 }
387 }
388 LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) {
389 if (socket->is_available()) {
390 if (const char *new_identifier = get_current_socket_identifier_for_future_socket(
391 node, *socket, node_decl.outputs))
392 {
393 STRNCPY(socket->identifier, new_identifier);
394 }
395 }
396 }
397}
398
403static bool hide_new_group_input_sockets(const bNode &node)
404{
405 BLI_assert(node.is_group_input());
406 /* Check needed to handle newly added group input nodes. */
407 if (const bNodeSocket *extension_socket = static_cast<bNodeSocket *>(node.outputs.last)) {
408 return extension_socket->is_user_hidden();
409 }
410 return false;
411}
412
414 bNode &node,
415 const NodeDeclaration &node_decl,
416 const bool do_id_user)
417{
418 if (!node.runtime->forward_compatible_versioning_done) {
419 do_forward_compat_versioning(node, node_decl);
420 node.runtime->forward_compatible_versioning_done = true;
421 }
422
423 /* Count panels */
424 int new_num_panels = 0;
425 for (const ItemDeclarationPtr &item_decl : node_decl.all_items) {
426 if (dynamic_cast<const PanelDeclaration *>(item_decl.get())) {
427 ++new_num_panels;
428 }
429 }
430
431 Vector<bNodeSocket *> old_inputs;
432 LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) {
433 old_inputs.append(socket);
434 }
435
436 Vector<bNodeSocket *> old_outputs;
437 LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) {
438 old_outputs.append(socket);
439 }
440
441 const bool hide_new_sockets = node.is_group_input() ? hide_new_group_input_sockets(node) : false;
442
443 Vector<bNodePanelState> old_panels = Vector<bNodePanelState>(node.panel_states());
444
445 /* New panel states buffer. */
447 node.num_panel_states = new_num_panels;
448 node.panel_states_array = MEM_calloc_arrayN<bNodePanelState>(new_num_panels, __func__);
449
450 /* Find list of sockets to add, mixture of old and new sockets. */
451 VectorSet<bNodeSocket *> new_inputs;
452 VectorSet<bNodeSocket *> new_outputs;
453 bNodePanelState *new_panel = node.panel_states_array;
454 for (const ItemDeclarationPtr &item_decl : node_decl.all_items) {
455 if (const SocketDeclaration *socket_decl = dynamic_cast<const SocketDeclaration *>(
456 item_decl.get()))
457 {
458 if (socket_decl->in_out == SOCK_IN) {
459 refresh_node_socket(ntree, node, *socket_decl, old_inputs, new_inputs, hide_new_sockets);
460 }
461 else {
462 refresh_node_socket(ntree, node, *socket_decl, old_outputs, new_outputs, hide_new_sockets);
463 }
464 }
465 else if (const PanelDeclaration *panel_decl = dynamic_cast<const PanelDeclaration *>(
466 item_decl.get()))
467 {
468 refresh_node_panel(*panel_decl, old_panels, *new_panel);
469 ++new_panel;
470 }
471 }
472
473 /* Destroy any remaining sockets that are no longer in the declaration. */
474 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, old_socket, &node.inputs) {
475 if (!new_inputs.contains(old_socket)) {
476 blender::bke::node_remove_socket_ex(ntree, node, *old_socket, do_id_user);
477 }
478 }
479 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, old_socket, &node.outputs) {
480 if (!new_outputs.contains(old_socket)) {
481 blender::bke::node_remove_socket_ex(ntree, node, *old_socket, do_id_user);
482 }
483 }
484
485 /* Clear and reinsert sockets in the new order. */
488 for (bNodeSocket *socket : new_inputs) {
489 BLI_addtail(&node.inputs, socket);
490 }
491 for (bNodeSocket *socket : new_outputs) {
492 BLI_addtail(&node.outputs, socket);
493 }
494}
495
496static void refresh_node(bNodeTree &ntree,
497 bNode &node,
499 bool do_id_user)
500{
501 if (node_decl.skip_updating_sockets) {
502 return;
503 }
504 if (!node_decl.matches(node)) {
505 refresh_node_sockets_and_panels(ntree, node, node_decl, do_id_user);
506 }
508}
509
511{
512 if (node.typeinfo->declare) {
513 if (node.typeinfo->static_declaration->is_context_dependent) {
514 if (!node.runtime->declaration) {
515 node.runtime->declaration = new NodeDeclaration();
516 }
517 build_node_declaration(*node.typeinfo, *node.runtime->declaration, &ntree, &node);
518 }
519 }
520 refresh_node(ntree, node, *node.runtime->declaration, true);
521}
522
524{
525 return ELEM(socket_type,
528 SOCK_RGBA,
530 SOCK_INT,
532 SOCK_MENU,
534}
535
537{
538 return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR);
539}
540
541} // namespace blender::nodes
542
543void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
544{
545 blender::bke::bNodeType *ntype = node->typeinfo;
546 if (ntype == nullptr) {
547 return;
548 }
549 if (ntype->declare) {
551 refresh_node(*ntree, *node, *node->runtime->declaration, do_id_user);
552 return;
553 }
554 /* Don't try to match socket lists when there are no templates.
555 * This prevents dynamically generated sockets to be removed, like for
556 * group, image or render layer nodes. We have an explicit check for the
557 * render layer node since it still has fixed sockets too.
558 */
559 if (ntype) {
560 if (ntype->inputs && ntype->inputs[0].type >= 0) {
561 verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
562 }
563 if (ntype->outputs && ntype->outputs[0].type >= 0 && node->type_legacy != CMP_NODE_R_LAYERS) {
564 verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
565 }
566 }
567}
568
570{
571 if (!data) {
572 return;
573 }
574
575 switch (datatype) {
576 case SOCK_FLOAT: {
577 bNodeSocketValueFloat *dval = MEM_callocN<bNodeSocketValueFloat>("node socket value float");
578 dval->subtype = subtype;
579 dval->value = 0.0f;
580 dval->min = -FLT_MAX;
581 dval->max = FLT_MAX;
582
583 *data = dval;
584 break;
585 }
586 case SOCK_INT: {
587 bNodeSocketValueInt *dval = MEM_callocN<bNodeSocketValueInt>("node socket value int");
588 dval->subtype = subtype;
589 dval->value = 0;
590 dval->min = INT_MIN;
591 dval->max = INT_MAX;
592
593 *data = dval;
594 break;
595 }
596 case SOCK_BOOLEAN: {
598 "node socket value bool");
599 dval->value = false;
600
601 *data = dval;
602 break;
603 }
604 case SOCK_ROTATION: {
606 *data = dval;
607 break;
608 }
609 case SOCK_VECTOR: {
610 static float default_value[] = {0.0f, 0.0f, 0.0f};
612 "node socket value vector");
613 dval->subtype = subtype;
614 dval->dimensions = 3;
615 copy_v3_v3(dval->value, default_value);
616 dval->min = -FLT_MAX;
617 dval->max = FLT_MAX;
618
619 *data = dval;
620 break;
621 }
622 case SOCK_RGBA: {
623 static float default_value[] = {0.0f, 0.0f, 0.0f, 1.0f};
624 bNodeSocketValueRGBA *dval = MEM_callocN<bNodeSocketValueRGBA>("node socket value color");
625 copy_v4_v4(dval->value, default_value);
626
627 *data = dval;
628 break;
629 }
630 case SOCK_STRING: {
632 "node socket value string");
633 dval->subtype = subtype;
634 dval->value[0] = '\0';
635
636 *data = dval;
637 break;
638 }
639 case SOCK_MENU: {
640 bNodeSocketValueMenu *dval = MEM_callocN<bNodeSocketValueMenu>("node socket value menu");
641 dval->value = -1;
642
643 *data = dval;
644 break;
645 }
646 case SOCK_OBJECT: {
648 "node socket value object");
649 dval->value = nullptr;
650
651 *data = dval;
652 break;
653 }
654 case SOCK_IMAGE: {
655 bNodeSocketValueImage *dval = MEM_callocN<bNodeSocketValueImage>("node socket value image");
656 dval->value = nullptr;
657
658 *data = dval;
659 break;
660 }
661 case SOCK_COLLECTION: {
663 "node socket value object");
664 dval->value = nullptr;
665
666 *data = dval;
667 break;
668 }
669 case SOCK_TEXTURE: {
671 "node socket value texture");
672 dval->value = nullptr;
673
674 *data = dval;
675 break;
676 }
677 case SOCK_MATERIAL: {
679 "node socket value material");
680 dval->value = nullptr;
681
682 *data = dval;
683 break;
684 }
685
686 case SOCK_CUSTOM:
687 case SOCK_GEOMETRY:
688 case SOCK_MATRIX:
689 case SOCK_SHADER:
690 case SOCK_BUNDLE:
691 case SOCK_CLOSURE:
692 break;
693 }
694}
695
696void node_socket_copy_default_value_data(eNodeSocketDatatype datatype, void *to, const void *from)
697{
698 if (!to || !from) {
699 return;
700 }
701
702 switch (datatype) {
703 case SOCK_FLOAT: {
706 *toval = *fromval;
707 break;
708 }
709 case SOCK_INT: {
711 bNodeSocketValueInt *fromval = (bNodeSocketValueInt *)from;
712 *toval = *fromval;
713 break;
714 }
715 case SOCK_BOOLEAN: {
718 *toval = *fromval;
719 break;
720 }
721 case SOCK_VECTOR: {
724 *toval = *fromval;
725 break;
726 }
727 case SOCK_RGBA: {
730 *toval = *fromval;
731 break;
732 }
733 case SOCK_ROTATION: {
736 *toval = *fromval;
737 break;
738 }
739 case SOCK_STRING: {
742 *toval = *fromval;
743 break;
744 }
745 case SOCK_MENU: {
748 *toval = *fromval;
749 break;
750 }
751 case SOCK_OBJECT: {
754 *toval = *fromval;
755 id_us_plus(reinterpret_cast<ID *>(toval->value));
756 break;
757 }
758 case SOCK_IMAGE: {
761 *toval = *fromval;
762 id_us_plus(reinterpret_cast<ID *>(toval->value));
763 break;
764 }
765 case SOCK_COLLECTION: {
768 *toval = *fromval;
769 id_us_plus(reinterpret_cast<ID *>(toval->value));
770 break;
771 }
772 case SOCK_TEXTURE: {
775 *toval = *fromval;
776 id_us_plus(reinterpret_cast<ID *>(toval->value));
777 break;
778 }
779 case SOCK_MATERIAL: {
782 *toval = *fromval;
783 id_us_plus(reinterpret_cast<ID *>(toval->value));
784 break;
785 }
786
787 case SOCK_CUSTOM:
788 case SOCK_GEOMETRY:
789 case SOCK_MATRIX:
790 case SOCK_SHADER:
791 case SOCK_BUNDLE:
792 case SOCK_CLOSURE:
793 break;
794 }
795}
796
798{
799 if (sock->default_value) {
800 return; /* already initialized */
801 }
802
804 sock->typeinfo->type, PropertySubType(sock->typeinfo->subtype), &sock->default_value);
805}
806
808{
809 /* sanity check */
810 if (to->type != from->type) {
811 return;
812 }
813
814 /* make sure both exist */
815 if (!from->default_value) {
816 return;
817 }
819
820 /* use label instead of name if it has been set */
821 if (from->label[0] != '\0') {
822 STRNCPY(to->name, from->label);
823 }
824
826
827 to->flag |= (from->flag & SOCK_HIDE_VALUE);
828}
829
831 ID * /*id*/,
832 const bNodeTreeInterfaceSocket *interface_socket,
833 bNode * /*node*/,
834 bNodeSocket *sock,
835 StringRefNull /*data_path*/)
836{
837 /* initialize the type value */
838 sock->type = sock->typeinfo->type;
839
841 eNodeSocketDatatype(sock->type), sock->typeinfo->subtype, &sock->default_value);
843 eNodeSocketDatatype(sock->type), sock->default_value, interface_socket->socket_data);
844}
845
848 const bNode * /*node*/,
849 const bNodeSocket *sock)
850{
851 /* initialize settings */
852 iosock->init_from_socket_instance(sock);
853}
854
856
858 const eNodeSocketDatatype type, int subtype, std::optional<int> dimensions = std::nullopt)
859{
860 const StringRefNull socket_idname = *bke::node_static_socket_type(type, subtype, dimensions);
862 type, subtype, dimensions);
863 const StringRefNull socket_label = *bke::node_static_socket_label(type, subtype);
864 const StringRefNull socket_subtype_label = blender::bke::node_socket_sub_type_label(subtype);
866 StructRNA *srna;
867
868 stype = MEM_new<bke::bNodeSocketType>(__func__);
869 stype->free_self = [](bke::bNodeSocketType *type) { MEM_delete(type); };
870 stype->idname = socket_idname;
871 stype->label = socket_label;
872 stype->subtype_label = socket_subtype_label;
873
874 /* set the RNA type
875 * uses the exact same identifier as the socket type idname */
876 srna = stype->ext_socket.srna = RNA_struct_find(socket_idname.c_str());
877 BLI_assert(srna != nullptr);
878 /* associate the RNA type with the socket type */
879 RNA_struct_blender_type_set(srna, stype);
880
881 /* set the interface RNA type */
882 srna = stype->ext_interface.srna = RNA_struct_find(interface_idname.c_str());
883 BLI_assert(srna != nullptr);
884 /* associate the RNA type with the socket type */
885 RNA_struct_blender_type_set(srna, stype);
886
887 /* extra type info for standard socket types */
888 stype->type = type;
889 stype->subtype = subtype;
890
891 /* XXX bad-level call! needed for setting draw callbacks */
893
896
897 stype->use_link_limits_of_type = true;
898 stype->input_link_limit = 1;
899 stype->output_link_limit = 0xFFF;
900
901 return stype;
902}
903
905
907{
908 const char *socket_idname = "NodeSocketVirtual";
910 StructRNA *srna;
911
912 stype = MEM_new<bke::bNodeSocketType>(__func__);
913 stype->free_self = [](bke::bNodeSocketType *type) { MEM_delete(type); };
914 stype->idname = socket_idname;
915
916 /* set the RNA type
917 * uses the exact same identifier as the socket type idname */
918 srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
919 BLI_assert(srna != nullptr);
920 /* associate the RNA type with the socket type */
921 RNA_struct_blender_type_set(srna, stype);
922
923 /* extra type info for standard socket types */
924 stype->type = SOCK_CUSTOM;
925
927
928 stype->use_link_limits_of_type = true;
929 stype->input_link_limit = 0xFFF;
930 stype->output_link_limit = 0xFFF;
931
932 return stype;
933}
934
936{
939 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
940 *(bool *)r_value = ((bNodeSocketValueBoolean *)socket_value)->value;
941 };
943 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
944 const bool value = ((bNodeSocketValueBoolean *)socket_value)->value;
945 new (r_value) SocketValueVariant(value);
946 };
947 static SocketValueVariant default_value{false};
948 socktype->geometry_nodes_default_cpp_value = &default_value;
949 return socktype;
950}
951
953{
956 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
957 const auto &typed_value = *(bNodeSocketValueRotation *)socket_value;
958 const math::EulerXYZ euler(float3(typed_value.value_euler));
959 *static_cast<math::Quaternion *>(r_value) = math::to_quaternion(euler);
960 };
962 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
963 const auto &typed_value = *(bNodeSocketValueRotation *)socket_value;
964 const math::EulerXYZ euler(float3(typed_value.value_euler));
965 const math::Quaternion value = math::to_quaternion(euler);
966 new (r_value) SocketValueVariant(value);
967 };
968 static SocketValueVariant default_value{math::Quaternion::identity()};
969 socktype->geometry_nodes_default_cpp_value = &default_value;
970 return socktype;
971}
972
974{
977 socktype->get_base_cpp_value = [](const void * /*socket_value*/, void *r_value) {
978 *static_cast<float4x4 *>(r_value) = float4x4::identity();
979 };
981 socktype->get_geometry_nodes_cpp_value = [](const void * /*socket_value*/, void *r_value) {
982 new (r_value) SocketValueVariant(float4x4::identity());
983 };
984 static SocketValueVariant default_value{float4x4::identity()};
985 socktype->geometry_nodes_default_cpp_value = &default_value;
986 return socktype;
987}
988
990{
993 socktype->get_base_cpp_value = [](const void * /*socket_value*/, void *r_value) {
994 new (r_value) nodes::BundlePtr();
995 };
997 socktype->get_geometry_nodes_cpp_value = [](const void * /*socket_value*/, void *r_value) {
998 new (r_value) SocketValueVariant(nodes::BundlePtr());
999 };
1000 static SocketValueVariant default_value{nodes::BundlePtr()};
1001 socktype->geometry_nodes_default_cpp_value = &default_value;
1002 return socktype;
1003}
1004
1006{
1009 socktype->get_base_cpp_value = [](const void * /*socket_value*/, void *r_value) {
1010 new (r_value) nodes::ClosurePtr();
1011 };
1013 socktype->get_geometry_nodes_cpp_value = [](const void * /*socket_value*/, void *r_value) {
1014 new (r_value) SocketValueVariant(nodes::ClosurePtr());
1015 };
1016 static SocketValueVariant default_value{nodes::ClosurePtr()};
1017 socktype->geometry_nodes_default_cpp_value = &default_value;
1018 return socktype;
1019}
1020
1022{
1025 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1026 *(float *)r_value = ((bNodeSocketValueFloat *)socket_value)->value;
1027 };
1029 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1030 const float value = ((bNodeSocketValueFloat *)socket_value)->value;
1031 new (r_value) SocketValueVariant(value);
1032 };
1033 static SocketValueVariant default_value{0.0f};
1034 socktype->geometry_nodes_default_cpp_value = &default_value;
1035 return socktype;
1036}
1037
1039{
1042 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1043 *(int *)r_value = ((bNodeSocketValueInt *)socket_value)->value;
1044 };
1046 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1047 const int value = ((bNodeSocketValueInt *)socket_value)->value;
1048 new (r_value) SocketValueVariant(value);
1049 };
1050 static SocketValueVariant default_value{0};
1051 socktype->geometry_nodes_default_cpp_value = &default_value;
1052 return socktype;
1053}
1054
1056{
1057 bke::bNodeSocketType *socktype = make_standard_socket_type(SOCK_VECTOR, subtype, dimensions);
1059 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1060 *(blender::float3 *)r_value = ((bNodeSocketValueVector *)socket_value)->value;
1061 };
1063 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1064 const blender::float3 value = ((bNodeSocketValueVector *)socket_value)->value;
1065 new (r_value) SocketValueVariant(value);
1066 };
1067 static SocketValueVariant default_value{blender::float3(0, 0, 0)};
1068 socktype->geometry_nodes_default_cpp_value = &default_value;
1069 return socktype;
1070}
1071
1073{
1076 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1077 *(blender::ColorGeometry4f *)r_value = ((bNodeSocketValueRGBA *)socket_value)->value;
1078 };
1080 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1081 const blender::ColorGeometry4f value = ((bNodeSocketValueRGBA *)socket_value)->value;
1082 new (r_value) SocketValueVariant(value);
1083 };
1084 static SocketValueVariant default_value{blender::ColorGeometry4f(0, 0, 0, 0)};
1085 socktype->geometry_nodes_default_cpp_value = &default_value;
1086 return socktype;
1087}
1088
1090{
1093 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1094 new (r_value) std::string(((bNodeSocketValueString *)socket_value)->value);
1095 };
1097 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1098 std::string value = ((bNodeSocketValueString *)socket_value)->value;
1099 new (r_value) SocketValueVariant(value);
1100 };
1101 static SocketValueVariant default_value{std::string()};
1102 socktype->geometry_nodes_default_cpp_value = &default_value;
1103 return socktype;
1104}
1105
1107{
1110 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1111 *(int *)r_value = ((bNodeSocketValueMenu *)socket_value)->value;
1112 };
1114 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1115 const int value = ((bNodeSocketValueMenu *)socket_value)->value;
1116 new (r_value) SocketValueVariant(value);
1117 };
1118 static SocketValueVariant default_value{0};
1119 socktype->geometry_nodes_default_cpp_value = &default_value;
1120 return socktype;
1121}
1122
1124{
1127 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1128 *(Object **)r_value = ((bNodeSocketValueObject *)socket_value)->value;
1129 };
1130 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1132 return socktype;
1133}
1134
1136{
1139 socktype->get_base_cpp_value = [](const void * /*socket_value*/, void *r_value) {
1140 new (r_value) blender::bke::GeometrySet();
1141 };
1142 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1144 return socktype;
1145}
1146
1148{
1151 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1152 *(Collection **)r_value = ((bNodeSocketValueCollection *)socket_value)->value;
1153 };
1154 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1156 return socktype;
1157}
1158
1160{
1163 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1164 *(Tex **)r_value = ((bNodeSocketValueTexture *)socket_value)->value;
1165 };
1166 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1168 return socktype;
1169}
1170
1172{
1175 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1176 *(Image **)r_value = ((bNodeSocketValueImage *)socket_value)->value;
1177 };
1178 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1180 return socktype;
1181}
1182
1184{
1187 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1188 *(Material **)r_value = ((bNodeSocketValueMaterial *)socket_value)->value;
1189 };
1190 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1192 return socktype;
1193}
1194
1196{
1197 /* Draw callbacks are set in `drawnode.cc` to avoid bad-level calls. */
1198
1210
1215
1219
1229
1239
1249
1251
1254
1256
1258
1260
1262
1264
1266
1268
1270
1273
1275}
void id_us_plus(ID *id)
Definition lib_id.cc:353
#define FN_NODE_RANDOM_VALUE
#define SH_NODE_MAP_RANGE
#define FN_NODE_COMPARE
#define SH_NODE_MIX
#define CMP_NODE_R_LAYERS
void BKE_ntree_update_tag_socket_new(bNodeTree *ntree, bNodeSocket *socket)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:371
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
int bool BLI_str_startswith(const char *__restrict str, const char *__restrict start) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define STREQLEN(a, b, n)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define STREQ(a, b)
float[3] Vector
Object groups, one object can be in many groups at once.
#define NODE_MAXSTR
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
@ SOCK_HIDE_VALUE
@ SOCK_HIDDEN
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_TEXTURE
@ SOCK_VECTOR
@ SOCK_CLOSURE
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_SHADER
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_CUSTOM
@ SOCK_BUNDLE
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_OBJECT
@ SOCK_STRING
@ SOCK_RGBA
@ SOCK_MENU
Read Guarded memory(de)allocation.
PropertySubType
Definition RNA_types.hh:220
@ PROP_TIME
Definition RNA_types.hh:241
@ PROP_DIRECTION
Definition RNA_types.hh:250
@ PROP_XYZ
Definition RNA_types.hh:257
@ PROP_DISTANCE
Definition RNA_types.hh:244
@ PROP_ACCELERATION
Definition RNA_types.hh:252
@ PROP_ANGLE
Definition RNA_types.hh:240
@ PROP_TIME_ABSOLUTE
Definition RNA_types.hh:242
@ PROP_EULER
Definition RNA_types.hh:254
@ PROP_COLOR_TEMPERATURE
Definition RNA_types.hh:278
@ PROP_NONE
Definition RNA_types.hh:221
@ PROP_PERCENTAGE
Definition RNA_types.hh:238
@ PROP_FREQUENCY
Definition RNA_types.hh:280
@ PROP_FACTOR
Definition RNA_types.hh:239
@ PROP_TRANSLATION
Definition RNA_types.hh:249
@ PROP_UNSIGNED
Definition RNA_types.hh:237
@ PROP_FILEPATH
Definition RNA_types.hh:224
@ PROP_VELOCITY
Definition RNA_types.hh:251
@ PROP_WAVELENGTH
Definition RNA_types.hh:275
BMesh const char void * data
long long int int64_t
static const CPPType & get()
constexpr const char * c_str() const
bool contains(const Key &key) const
void add_new(const Key &key)
void remove_and_reorder(const int64_t index)
void append(const T &value)
IndexRange index_range() const
Vector< SocketDeclaration * > inputs
bool matches(const bNode &node) const
Vector< SocketDeclaration * > outputs
Vector< ItemDeclarationPtr > all_items
void update_or_build(const bNodePanelState &old_panel, bNodePanelState &new_panel) const
bool matches(const bNodePanelState &panel) const
void build(bNodePanelState &panel) const
virtual bool matches(const bNodeSocket &socket) const =0
virtual bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
virtual bNodeSocket & build(bNodeTree &ntree, bNode &node) const =0
#define MEM_SAFE_FREE(v)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void node_socket_declarations_update(bNode *node)
Definition node.cc:5058
void node_modify_socket_type_static(bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype)
Definition node.cc:3123
void node_remove_socket(bNodeTree &ntree, bNode &node, bNodeSocket &sock)
Definition node.cc:3575
std::optional< StringRefNull > node_static_socket_interface_type_new(int type, int subtype, std::optional< int > dimensions=std::nullopt)
Definition node.cc:3327
bool node_declaration_ensure_on_outdated_node(bNodeTree &ntree, bNode &node)
Definition node.cc:5070
void node_register_socket_type(bNodeSocketType &stype)
Definition node.cc:2826
bNodeSocket * node_add_static_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out, int type, int subtype, StringRefNull identifier, StringRefNull name)
Definition node.cc:3529
void node_remove_socket_ex(bNodeTree &ntree, bNode &node, bNodeSocket &sock, bool do_id_user)
Definition node.cc:3580
std::optional< StringRefNull > node_static_socket_label(int type, int subtype)
Definition node.cc:3484
std::optional< StringRefNull > node_static_socket_type(int type, int subtype, std::optional< int > dimensions=std::nullopt)
Definition node.cc:3167
StringRefNull node_socket_sub_type_label(int subtype)
Definition node.cc:2855
QuaternionBase< float > Quaternion
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
EulerXYZBase< float > EulerXYZ
ImplicitSharingPtr< Bundle > BundlePtr
std::unique_ptr< SocketDeclaration > SocketDeclarationPtr
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
void build_node_declaration(const bke::bNodeType &typeinfo, NodeDeclaration &r_declaration, const bNodeTree *ntree, const bNode *node)
std::unique_ptr< ItemDeclaration > ItemDeclarationPtr
static void do_forward_compat_versioning(bNode &node, const NodeDeclaration &node_decl)
static void refresh_node_sockets_and_panels(bNodeTree &ntree, bNode &node, const NodeDeclaration &node_decl, const bool do_id_user)
static void refresh_node_socket(bNodeTree &ntree, bNode &node, const SocketDeclaration &socket_decl, Vector< bNodeSocket * > &old_sockets, VectorSet< bNodeSocket * > &new_sockets, const bool hide_new_sockets)
bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
static bool hide_new_group_input_sockets(const bNode &node)
ImplicitSharingPtr< Closure > ClosurePtr
static void refresh_node_panel(const PanelDeclaration &panel_decl, Vector< bNodePanelState > &old_panels, bNodePanelState &new_panel)
static const char * get_identifier_from_decl(const char *identifier_prefix, const bNodeSocket &socket, const Span< const SocketDeclaration * > socket_decls)
bool socket_type_supports_grids(const eNodeSocketDatatype socket_type)
static const char * get_current_socket_identifier_for_future_socket(const bNode &node, const bNodeSocket &socket, const Span< const SocketDeclaration * > socket_decls)
static void refresh_node(bNodeTree &ntree, bNode &node, blender::nodes::NodeDeclaration &node_decl, bool do_id_user)
MatBase< float, 4, 4 > float4x4
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:342
VecBase< float, 3 > float3
static bke::bNodeSocketType * make_socket_type_matrix()
static bke::bNodeSocketType * make_socket_type_rotation()
static void verify_socket_template_list(bNodeTree *ntree, bNode *node, eNodeSocketInOut in_out, ListBase *socklist, bke::bNodeSocketTemplate *stemp_first)
void node_socket_init_default_value(bNodeSocket *sock)
static bke::bNodeSocketType * make_socket_type_float(PropertySubType subtype)
static bke::bNodeSocketType * make_socket_type_texture()
static bke::bNodeSocketType * make_socket_type_object()
void ED_init_standard_node_socket_type(bke::bNodeSocketType *)
Definition drawnode.cc:1516
bNodeSocket * node_add_socket_from_template(bNodeTree *ntree, bNode *node, bke::bNodeSocketTemplate *stemp, eNodeSocketInOut in_out)
static bNodeSocket * verify_socket_template(bNodeTree *ntree, bNode *node, eNodeSocketInOut in_out, ListBase *socklist, bke::bNodeSocketTemplate *stemp)
void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
static bke::bNodeSocketType * make_socket_type_rgba()
static bke::bNodeSocketType * make_standard_socket_type(const eNodeSocketDatatype type, int subtype, std::optional< int > dimensions=std::nullopt)
static bke::bNodeSocketType * make_socket_type_int(PropertySubType subtype)
static void standard_node_socket_interface_from_socket(ID *, bNodeTreeInterfaceSocket *iosock, const bNode *, const bNodeSocket *sock)
static bke::bNodeSocketType * make_socket_type_geometry()
static void standard_node_socket_interface_init_socket(ID *, const bNodeTreeInterfaceSocket *interface_socket, bNode *, bNodeSocket *sock, StringRefNull)
static bke::bNodeSocketType * make_socket_type_menu()
static bke::bNodeSocketType * make_socket_type_image()
static bke::bNodeSocketType * make_socket_type_collection()
void ED_init_node_socket_type_virtual(bke::bNodeSocketType *)
Definition drawnode.cc:1525
static bke::bNodeSocketType * make_socket_type_bundle()
static bke::bNodeSocketType * make_socket_type_vector(PropertySubType subtype, const int dimensions)
static bke::bNodeSocketType * make_socket_type_closure()
void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
static bke::bNodeSocketType * make_socket_type_material()
static bke::bNodeSocketType * make_socket_type_bool()
void register_standard_node_socket_types()
void node_socket_init_default_value_data(eNodeSocketDatatype datatype, int subtype, void **data)
static bke::bNodeSocketType * make_socket_type_string(PropertySubType subtype)
void node_socket_copy_default_value_data(eNodeSocketDatatype datatype, void *to, const void *from)
static bke::bNodeSocketType * make_socket_type_virtual()
StructRNA * RNA_struct_find(const char *identifier)
void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
#define FLT_MAX
Definition stdcycles.h:14
StructRNA * srna
Definition RNA_types.hh:909
Definition DNA_ID.h:404
void * last
void * first
struct Collection * value
bNodeSocketTypeHandle * typeinfo
struct bNodeSocket * next
void * default_value
char identifier[64]
ListBase links
bNodeTypeHandle * typeinfo
ListBase inputs
int num_panel_states
bNodePanelState * panel_states_array
int16_t type_legacy
bNodeRuntimeHandle * runtime
ListBase outputs
Compact definition of a node socket.
Definition BKE_node.hh:98
Defines a socket type.
Definition BKE_node.hh:152
const blender::CPPType * geometry_nodes_cpp_type
Definition BKE_node.hh:203
SocketGetCPPValueFunction get_base_cpp_value
Definition BKE_node.hh:201
void(* interface_init_socket)(ID *id, const bNodeTreeInterfaceSocket *interface_socket, bNode *node, bNodeSocket *socket, StringRefNull data_path)
Definition BKE_node.hh:172
void(* free_self)(bNodeSocketType *stype)
Definition BKE_node.hh:196
const void * geometry_nodes_default_cpp_value
Definition BKE_node.hh:207
eNodeSocketDatatype type
Definition BKE_node.hh:187
SocketGetGeometryNodesCPPValueFunction get_geometry_nodes_cpp_value
Definition BKE_node.hh:205
const blender::CPPType * base_cpp_type
Definition BKE_node.hh:199
void(* interface_from_socket)(ID *id, bNodeTreeInterfaceSocket *interface_socket, const bNode *node, const bNodeSocket *socket)
Definition BKE_node.hh:177
Defines a node type.
Definition BKE_node.hh:226
bNodeSocketTemplate * inputs
Definition BKE_node.hh:242
bNodeSocketTemplate * outputs
Definition BKE_node.hh:242
NodeDeclareFunction declare
Definition BKE_node.hh:355
i
Definition text_draw.cc:230