Blender V4.3
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
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"
16#include "BLI_math_matrix.h"
17#include "BLI_math_matrix.hh"
19#include "BLI_math_vector.h"
21#include "BLI_string.h"
22#include "BLI_utildefines.h"
23
24#include "BKE_geometry_set.hh"
25#include "BKE_lib_id.hh"
26#include "BKE_node.hh"
27#include "BKE_node_runtime.hh"
30
32#include "DNA_material_types.h"
33
34#include "RNA_access.hh"
35
36#include "MEM_guardedalloc.h"
37
39#include "NOD_socket.hh"
42
43using namespace blender;
46
48 bNode *node,
50 eNodeSocketInOut in_out)
51{
53 ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
54
55 sock->flag |= stemp->flag;
56
57 /* initialize default_value */
58 switch (stemp->type) {
59 case SOCK_FLOAT: {
61 dval->value = stemp->val1;
62 dval->min = stemp->min;
63 dval->max = stemp->max;
64 break;
65 }
66 case SOCK_INT: {
68 dval->value = int(stemp->val1);
69 dval->min = int(stemp->min);
70 dval->max = int(stemp->max);
71 break;
72 }
73 case SOCK_BOOLEAN: {
75 dval->value = int(stemp->val1);
76 break;
77 }
78 case SOCK_VECTOR: {
80 dval->value[0] = stemp->val1;
81 dval->value[1] = stemp->val2;
82 dval->value[2] = stemp->val3;
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_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) {
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_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.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. */
446 MEM_SAFE_FREE(node.panel_states_array);
447 node.num_panel_states = new_num_panels;
448 node.panel_states_array = MEM_cnew_array<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.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. */
486 BLI_listbase_clear(&node.inputs);
487 BLI_listbase_clear(&node.outputs);
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 != CMP_NODE_R_LAYERS) {
564 verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
565 }
566 }
567}
568
569void node_socket_init_default_value_data(eNodeSocketDatatype datatype, int subtype, void **data)
570{
571 if (!data) {
572 return;
573 }
574
575 switch (datatype) {
576 case SOCK_FLOAT: {
577 bNodeSocketValueFloat *dval = MEM_cnew<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_cnew<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: {
597 bNodeSocketValueBoolean *dval = MEM_cnew<bNodeSocketValueBoolean>("node socket value bool");
598 dval->value = false;
599
600 *data = dval;
601 break;
602 }
603 case SOCK_ROTATION: {
604 bNodeSocketValueRotation *dval = MEM_cnew<bNodeSocketValueRotation>(__func__);
605 *data = dval;
606 break;
607 }
608 case SOCK_VECTOR: {
609 static float default_value[] = {0.0f, 0.0f, 0.0f};
610 bNodeSocketValueVector *dval = MEM_cnew<bNodeSocketValueVector>("node socket value vector");
611 dval->subtype = subtype;
612 copy_v3_v3(dval->value, default_value);
613 dval->min = -FLT_MAX;
614 dval->max = FLT_MAX;
615
616 *data = dval;
617 break;
618 }
619 case SOCK_RGBA: {
620 static float default_value[] = {0.0f, 0.0f, 0.0f, 1.0f};
621 bNodeSocketValueRGBA *dval = MEM_cnew<bNodeSocketValueRGBA>("node socket value color");
622 copy_v4_v4(dval->value, default_value);
623
624 *data = dval;
625 break;
626 }
627 case SOCK_STRING: {
628 bNodeSocketValueString *dval = MEM_cnew<bNodeSocketValueString>("node socket value string");
629 dval->subtype = subtype;
630 dval->value[0] = '\0';
631
632 *data = dval;
633 break;
634 }
635 case SOCK_MENU: {
636 bNodeSocketValueMenu *dval = MEM_cnew<bNodeSocketValueMenu>("node socket value menu");
637 dval->value = -1;
638
639 *data = dval;
640 break;
641 }
642 case SOCK_OBJECT: {
643 bNodeSocketValueObject *dval = MEM_cnew<bNodeSocketValueObject>("node socket value object");
644 dval->value = nullptr;
645
646 *data = dval;
647 break;
648 }
649 case SOCK_IMAGE: {
650 bNodeSocketValueImage *dval = MEM_cnew<bNodeSocketValueImage>("node socket value image");
651 dval->value = nullptr;
652
653 *data = dval;
654 break;
655 }
656 case SOCK_COLLECTION: {
657 bNodeSocketValueCollection *dval = MEM_cnew<bNodeSocketValueCollection>(
658 "node socket value object");
659 dval->value = nullptr;
660
661 *data = dval;
662 break;
663 }
664 case SOCK_TEXTURE: {
665 bNodeSocketValueTexture *dval = MEM_cnew<bNodeSocketValueTexture>(
666 "node socket value texture");
667 dval->value = nullptr;
668
669 *data = dval;
670 break;
671 }
672 case SOCK_MATERIAL: {
673 bNodeSocketValueMaterial *dval = MEM_cnew<bNodeSocketValueMaterial>(
674 "node socket value material");
675 dval->value = nullptr;
676
677 *data = dval;
678 break;
679 }
680
681 case SOCK_CUSTOM:
682 case SOCK_GEOMETRY:
683 case SOCK_MATRIX:
684 case SOCK_SHADER:
685 break;
686 }
687}
688
689void node_socket_copy_default_value_data(eNodeSocketDatatype datatype, void *to, const void *from)
690{
691 if (!to || !from) {
692 return;
693 }
694
695 switch (datatype) {
696 case SOCK_FLOAT: {
699 *toval = *fromval;
700 break;
701 }
702 case SOCK_INT: {
704 bNodeSocketValueInt *fromval = (bNodeSocketValueInt *)from;
705 *toval = *fromval;
706 break;
707 }
708 case SOCK_BOOLEAN: {
711 *toval = *fromval;
712 break;
713 }
714 case SOCK_VECTOR: {
717 *toval = *fromval;
718 break;
719 }
720 case SOCK_RGBA: {
723 *toval = *fromval;
724 break;
725 }
726 case SOCK_ROTATION: {
729 *toval = *fromval;
730 break;
731 }
732 case SOCK_STRING: {
735 *toval = *fromval;
736 break;
737 }
738 case SOCK_MENU: {
741 *toval = *fromval;
742 break;
743 }
744 case SOCK_OBJECT: {
747 *toval = *fromval;
748 id_us_plus(&toval->value->id);
749 break;
750 }
751 case SOCK_IMAGE: {
754 *toval = *fromval;
755 id_us_plus(&toval->value->id);
756 break;
757 }
758 case SOCK_COLLECTION: {
761 *toval = *fromval;
762 id_us_plus(&toval->value->id);
763 break;
764 }
765 case SOCK_TEXTURE: {
768 *toval = *fromval;
769 id_us_plus(&toval->value->id);
770 break;
771 }
772 case SOCK_MATERIAL: {
775 *toval = *fromval;
776 id_us_plus(&toval->value->id);
777 break;
778 }
779
780 case SOCK_CUSTOM:
781 case SOCK_GEOMETRY:
782 case SOCK_MATRIX:
783 case SOCK_SHADER:
784 break;
785 }
786}
787
789{
790 if (sock->default_value) {
791 return; /* already initialized */
792 }
793
795 PropertySubType(sock->typeinfo->subtype),
796 &sock->default_value);
797}
798
800{
801 /* sanity check */
802 if (to->type != from->type) {
803 return;
804 }
805
806 /* make sure both exist */
807 if (!from->default_value) {
808 return;
809 }
811
812 /* use label instead of name if it has been set */
813 if (from->label[0] != '\0') {
814 STRNCPY(to->name, from->label);
815 }
816
818 eNodeSocketDatatype(to->typeinfo->type), to->default_value, from->default_value);
819
820 to->flag |= (from->flag & SOCK_HIDE_VALUE);
821}
822
824 ID * /*id*/,
825 const bNodeTreeInterfaceSocket *interface_socket,
826 bNode * /*node*/,
827 bNodeSocket *sock,
828 const char * /*data_path*/)
829{
830 /* initialize the type value */
831 sock->type = sock->typeinfo->type;
832
834 eNodeSocketDatatype(sock->type), sock->typeinfo->subtype, &sock->default_value);
836 eNodeSocketDatatype(sock->type), sock->default_value, interface_socket->socket_data);
837}
838
841 const bNode * /*node*/,
842 const bNodeSocket *sock)
843{
844 /* initialize settings */
845 iosock->init_from_socket_instance(sock);
846}
847
849
851{
852 const char *socket_idname = bke::node_static_socket_type(type, subtype);
853 const char *interface_idname = bke::node_static_socket_interface_type_new(type, subtype);
854 const char *socket_label = bke::node_static_socket_label(type, subtype);
855 const char *socket_subtype_label = blender::bke::node_socket_sub_type_label(subtype);
857 StructRNA *srna;
858
859 stype = MEM_cnew<bke::bNodeSocketType>("node socket C type");
860 stype->free_self = (void (*)(bke::bNodeSocketType *stype))MEM_freeN;
861 STRNCPY(stype->idname, socket_idname);
862 STRNCPY(stype->label, socket_label);
863 STRNCPY(stype->subtype_label, socket_subtype_label);
864
865 /* set the RNA type
866 * uses the exact same identifier as the socket type idname */
867 srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
868 BLI_assert(srna != nullptr);
869 /* associate the RNA type with the socket type */
870 RNA_struct_blender_type_set(srna, stype);
871
872 /* set the interface RNA type */
873 srna = stype->ext_interface.srna = RNA_struct_find(interface_idname);
874 BLI_assert(srna != nullptr);
875 /* associate the RNA type with the socket type */
876 RNA_struct_blender_type_set(srna, stype);
877
878 /* extra type info for standard socket types */
879 stype->type = type;
880 stype->subtype = subtype;
881
882 /* XXX bad-level call! needed for setting draw callbacks */
884
887
888 stype->use_link_limits_of_type = true;
889 stype->input_link_limit = 1;
890 stype->output_link_limit = 0xFFF;
891
892 return stype;
893}
894
896
898{
899 const char *socket_idname = "NodeSocketVirtual";
901 StructRNA *srna;
902
903 stype = MEM_cnew<bke::bNodeSocketType>("node socket C type");
904 stype->free_self = (void (*)(bke::bNodeSocketType *stype))MEM_freeN;
905 STRNCPY(stype->idname, socket_idname);
906
907 /* set the RNA type
908 * uses the exact same identifier as the socket type idname */
909 srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
910 BLI_assert(srna != nullptr);
911 /* associate the RNA type with the socket type */
912 RNA_struct_blender_type_set(srna, stype);
913
914 /* extra type info for standard socket types */
915 stype->type = SOCK_CUSTOM;
916
918
919 stype->use_link_limits_of_type = true;
920 stype->input_link_limit = 0xFFF;
921 stype->output_link_limit = 0xFFF;
922
923 return stype;
924}
925
927{
930 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
931 *(bool *)r_value = ((bNodeSocketValueBoolean *)socket_value)->value;
932 };
934 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
935 const bool value = ((bNodeSocketValueBoolean *)socket_value)->value;
936 new (r_value) SocketValueVariant(value);
937 };
938 static SocketValueVariant default_value{false};
939 socktype->geometry_nodes_default_cpp_value = &default_value;
940 return socktype;
941}
942
944{
947 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
948 const auto &typed_value = *(bNodeSocketValueRotation *)socket_value;
949 const math::EulerXYZ euler(float3(typed_value.value_euler));
950 *static_cast<math::Quaternion *>(r_value) = math::to_quaternion(euler);
951 };
953 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
954 const auto &typed_value = *(bNodeSocketValueRotation *)socket_value;
955 const math::EulerXYZ euler(float3(typed_value.value_euler));
956 const math::Quaternion value = math::to_quaternion(euler);
957 new (r_value) SocketValueVariant(value);
958 };
959 static SocketValueVariant default_value{math::Quaternion::identity()};
960 socktype->geometry_nodes_default_cpp_value = &default_value;
961 return socktype;
962}
963
965{
968 socktype->get_base_cpp_value = [](const void * /*socket_value*/, void *r_value) {
969 *static_cast<float4x4 *>(r_value) = float4x4::identity();
970 };
972 socktype->get_geometry_nodes_cpp_value = [](const void * /*socket_value*/, void *r_value) {
973 new (r_value) SocketValueVariant(float4x4::identity());
974 };
975 static SocketValueVariant default_value{float4x4::identity()};
976 socktype->geometry_nodes_default_cpp_value = &default_value;
977 return socktype;
978}
979
981{
984 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
985 *(float *)r_value = ((bNodeSocketValueFloat *)socket_value)->value;
986 };
988 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
989 const float value = ((bNodeSocketValueFloat *)socket_value)->value;
990 new (r_value) SocketValueVariant(value);
991 };
992 static SocketValueVariant default_value{0.0f};
993 socktype->geometry_nodes_default_cpp_value = &default_value;
994 return socktype;
995}
996
998{
1001 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1002 *(int *)r_value = ((bNodeSocketValueInt *)socket_value)->value;
1003 };
1005 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1006 const int value = ((bNodeSocketValueInt *)socket_value)->value;
1007 new (r_value) SocketValueVariant(value);
1008 };
1009 static SocketValueVariant default_value{0};
1010 socktype->geometry_nodes_default_cpp_value = &default_value;
1011 return socktype;
1012}
1013
1015{
1018 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1019 *(blender::float3 *)r_value = ((bNodeSocketValueVector *)socket_value)->value;
1020 };
1022 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1023 const blender::float3 value = ((bNodeSocketValueVector *)socket_value)->value;
1024 new (r_value) SocketValueVariant(value);
1025 };
1026 static SocketValueVariant default_value{blender::float3(0, 0, 0)};
1027 socktype->geometry_nodes_default_cpp_value = &default_value;
1028 return socktype;
1029}
1030
1032{
1035 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1036 *(blender::ColorGeometry4f *)r_value = ((bNodeSocketValueRGBA *)socket_value)->value;
1037 };
1039 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1040 const blender::ColorGeometry4f value = ((bNodeSocketValueRGBA *)socket_value)->value;
1041 new (r_value) SocketValueVariant(value);
1042 };
1043 static SocketValueVariant default_value{blender::ColorGeometry4f(0, 0, 0, 0)};
1044 socktype->geometry_nodes_default_cpp_value = &default_value;
1045 return socktype;
1046}
1047
1049{
1052 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1053 new (r_value) std::string(((bNodeSocketValueString *)socket_value)->value);
1054 };
1056 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1057 std::string value = ((bNodeSocketValueString *)socket_value)->value;
1058 new (r_value) SocketValueVariant(value);
1059 };
1060 static SocketValueVariant default_value{std::string()};
1061 socktype->geometry_nodes_default_cpp_value = &default_value;
1062 return socktype;
1063}
1064
1066{
1069 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1070 *(int *)r_value = ((bNodeSocketValueMenu *)socket_value)->value;
1071 };
1073 socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
1074 const int value = ((bNodeSocketValueMenu *)socket_value)->value;
1075 new (r_value) SocketValueVariant(value);
1076 };
1077 static SocketValueVariant default_value{0};
1078 socktype->geometry_nodes_default_cpp_value = &default_value;
1079 return socktype;
1080}
1081
1083{
1086 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1087 *(Object **)r_value = ((bNodeSocketValueObject *)socket_value)->value;
1088 };
1089 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1091 return socktype;
1092}
1093
1095{
1098 socktype->get_base_cpp_value = [](const void * /*socket_value*/, void *r_value) {
1099 new (r_value) blender::bke::GeometrySet();
1100 };
1101 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1103 return socktype;
1104}
1105
1107{
1110 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1111 *(Collection **)r_value = ((bNodeSocketValueCollection *)socket_value)->value;
1112 };
1113 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1115 return socktype;
1116}
1117
1119{
1122 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1123 *(Tex **)r_value = ((bNodeSocketValueTexture *)socket_value)->value;
1124 };
1125 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1127 return socktype;
1128}
1129
1131{
1134 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1135 *(Image **)r_value = ((bNodeSocketValueImage *)socket_value)->value;
1136 };
1137 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1139 return socktype;
1140}
1141
1143{
1146 socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
1147 *(Material **)r_value = ((bNodeSocketValueMaterial *)socket_value)->value;
1148 };
1149 socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
1151 return socktype;
1152}
1153
1155{
1156 /* Draw callbacks are set in `drawnode.cc` to avoid bad-level calls. */
1157
1169
1174
1178
1186
1188
1191
1193
1195
1197
1199
1201
1203
1205
1207
1209}
void id_us_plus(ID *id)
Definition lib_id.cc:351
#define FN_NODE_RANDOM_VALUE
Definition BKE_node.hh:1398
#define SH_NODE_MAP_RANGE
Definition BKE_node.hh:985
#define FN_NODE_COMPARE
Definition BKE_node.hh:1389
#define SH_NODE_MIX
Definition BKE_node.hh:996
void BKE_ntree_update_tag_socket_new(bNodeTree *ntree, bNodeSocket *socket)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:370
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
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define STREQLEN(a, b, n)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define STREQ(a, b)
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_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
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
PropertySubType
Definition RNA_types.hh:135
@ PROP_TIME
Definition RNA_types.hh:156
@ PROP_DIRECTION
Definition RNA_types.hh:165
@ PROP_XYZ
Definition RNA_types.hh:172
@ PROP_DISTANCE
Definition RNA_types.hh:159
@ PROP_ACCELERATION
Definition RNA_types.hh:167
@ PROP_ANGLE
Definition RNA_types.hh:155
@ PROP_TIME_ABSOLUTE
Definition RNA_types.hh:157
@ PROP_EULER
Definition RNA_types.hh:169
@ PROP_COLOR_TEMPERATURE
Definition RNA_types.hh:193
@ PROP_NONE
Definition RNA_types.hh:136
@ PROP_PERCENTAGE
Definition RNA_types.hh:153
@ PROP_FREQUENCY
Definition RNA_types.hh:195
@ PROP_FACTOR
Definition RNA_types.hh:154
@ PROP_TRANSLATION
Definition RNA_types.hh:164
@ PROP_UNSIGNED
Definition RNA_types.hh:152
@ PROP_FILEPATH
Definition RNA_types.hh:139
@ PROP_VELOCITY
Definition RNA_types.hh:166
@ PROP_WAVELENGTH
Definition RNA_types.hh:190
static const CPPType & get()
void add_new(const Key &key)
bool contains(const Key &key) const
void remove_and_reorder(const int64_t index)
void append(const T &value)
IndexRange index_range() const
Vector< ItemDeclarationPtr > items
Vector< SocketDeclaration * > inputs
bool matches(const bNode &node) const
Vector< SocketDeclaration * > outputs
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
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void node_socket_declarations_update(bNode *node)
Definition node.cc:3958
void node_modify_socket_type_static(bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype)
Definition node.cc:2082
bool node_declaration_ensure_on_outdated_node(bNodeTree *ntree, bNode *node)
Definition node.cc:3970
const char * node_socket_sub_type_label(int subtype)
Definition node.cc:1820
bNodeSocket * node_add_static_socket(bNodeTree *ntree, bNode *node, eNodeSocketInOut in_out, int type, int subtype, const char *identifier, const char *name)
Definition node.cc:2359
void node_remove_socket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
Definition node.cc:2405
void node_register_socket_type(bNodeSocketType *stype)
Definition node.cc:1787
const char * node_static_socket_type(int type, int subtype)
Definition node.cc:2126
const char * node_static_socket_label(int type, int subtype)
Definition node.cc:2318
void node_remove_socket_ex(bNodeTree *ntree, bNode *node, bNodeSocket *sock, bool do_id_user)
Definition node.cc:2410
const char * node_static_socket_interface_type_new(int type, int subtype)
Definition node.cc:2222
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
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)
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)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
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 void standard_node_socket_interface_init_socket(ID *, const bNodeTreeInterfaceSocket *interface_socket, bNode *, bNodeSocket *sock, const char *)
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:1603
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_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 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:1612
static bke::bNodeSocketType * make_standard_socket_type(int type, int subtype)
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()
static bke::bNodeSocketType * make_socket_type_vector(PropertySubType subtype)
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
__int64 int64_t
Definition stdint.h:89
StructRNA * srna
Definition RNA_types.hh:780
Definition DNA_ID.h:413
void * first
struct Collection * value
struct Material * value
bNodeSocketTypeHandle * typeinfo
struct bNodeSocket * next
void * default_value
char identifier[64]
bNodeTreeRuntimeHandle * runtime
ListBase links
Compact definition of a node socket.
Definition BKE_node.hh:103
Defines a socket type.
Definition BKE_node.hh:151
const blender::CPPType * geometry_nodes_cpp_type
Definition BKE_node.hh:195
SocketGetCPPValueFunction get_base_cpp_value
Definition BKE_node.hh:193
void(* interface_init_socket)(ID *id, const bNodeTreeInterfaceSocket *interface_socket, bNode *node, bNodeSocket *socket, const char *data_path)
Definition BKE_node.hh:165
void(* free_self)(bNodeSocketType *stype)
Definition BKE_node.hh:188
const void * geometry_nodes_default_cpp_value
Definition BKE_node.hh:199
SocketGetGeometryNodesCPPValueFunction get_geometry_nodes_cpp_value
Definition BKE_node.hh:197
const blender::CPPType * base_cpp_type
Definition BKE_node.hh:191
void(* interface_from_socket)(ID *id, bNodeTreeInterfaceSocket *interface_socket, const bNode *node, const bNodeSocket *socket)
Definition BKE_node.hh:170
Defines a node type.
Definition BKE_node.hh:218
bNodeSocketTemplate * inputs
Definition BKE_node.hh:233
bNodeSocketTemplate * outputs
Definition BKE_node.hh:233
NodeDeclareFunction declare
Definition BKE_node.hh:347