Blender V4.3
node_socket_declarations.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_string.h"
6
9
10#include "BKE_lib_id.hh"
11#include "BKE_node_runtime.hh"
12
13#include "BLI_math_vector.h"
14
16
23 const SocketDeclaration &output)
24{
25 if (output.output_field_dependency.field_type() == OutputSocketFieldType::FieldSource) {
26 if (input.input_field_type == InputSocketFieldType::None) {
27 return false;
28 }
29 }
30 return true;
31}
32
33static bool sockets_can_connect(const SocketDeclaration &socket_decl,
34 const bNodeSocket &other_socket)
35{
36 /* Input sockets cannot connect to input sockets, outputs cannot connect to outputs. */
37 if (socket_decl.in_out == other_socket.in_out) {
38 return false;
39 }
40
41 if (other_socket.runtime->declaration) {
42 if (socket_decl.in_out == SOCK_IN) {
43 if (!field_types_are_compatible(socket_decl, *other_socket.runtime->declaration)) {
44 return false;
45 }
46 }
47 else {
48 if (!field_types_are_compatible(*other_socket.runtime->declaration, socket_decl)) {
49 return false;
50 }
51 }
52 }
53
54 return true;
55}
56
57static bool basic_types_can_connect(const SocketDeclaration & /*socket_decl*/,
58 const bNodeSocket &other_socket)
59{
61}
62
63static void modify_subtype_except_for_storage(bNodeSocket &socket, int new_subtype)
64{
65 const char *idname = bke::node_static_socket_type(socket.type, new_subtype);
66 STRNCPY(socket.idname, idname);
68 socket.typeinfo = socktype;
69}
70
71/* -------------------------------------------------------------------- */
76{
78 &node,
79 this->in_out,
81 this->subtype,
82 this->identifier.c_str(),
83 this->name.c_str());
84 this->set_common_flags(socket);
86 value.min = this->soft_min_value;
87 value.max = this->soft_max_value;
88 value.value = this->default_value;
89 return socket;
90}
91
92bool Float::matches(const bNodeSocket &socket) const
93{
94 if (!this->matches_common_data(socket)) {
95 return false;
96 }
97 if (socket.type != SOCK_FLOAT) {
98 return false;
99 }
100 if (socket.typeinfo->subtype != this->subtype) {
101 return false;
102 }
104 if (value.min != this->soft_min_value) {
105 return false;
106 }
107 if (value.max != this->soft_max_value) {
108 return false;
109 }
110 return true;
111}
112
113bool Float::can_connect(const bNodeSocket &socket) const
114{
115 if (!sockets_can_connect(*this, socket)) {
116 return false;
117 }
118 if (this->in_out == SOCK_OUT && socket.type == SOCK_ROTATION) {
119 return true;
120 }
121 return basic_types_can_connect(*this, socket);
122}
123
125{
126 if (socket.type != SOCK_FLOAT) {
127 BLI_assert(socket.in_out == this->in_out);
128 return this->build(ntree, node);
129 }
130 if (socket.typeinfo->subtype != this->subtype) {
132 }
133 this->set_common_flags(socket);
135 value.min = this->soft_min_value;
136 value.max = this->soft_max_value;
137 value.subtype = this->subtype;
138 return socket;
139}
140
143/* -------------------------------------------------------------------- */
148{
150 &node,
151 this->in_out,
152 SOCK_INT,
153 this->subtype,
154 this->identifier.c_str(),
155 this->name.c_str());
156 this->set_common_flags(socket);
158 value.min = this->soft_min_value;
159 value.max = this->soft_max_value;
160 value.value = this->default_value;
161 return socket;
162}
163
164bool Int::matches(const bNodeSocket &socket) const
165{
166 if (!this->matches_common_data(socket)) {
167 return false;
168 }
169 if (socket.type != SOCK_INT) {
170 return false;
171 }
172 if (socket.typeinfo->subtype != this->subtype) {
173 return false;
174 }
176 if (value.min != this->soft_min_value) {
177 return false;
178 }
179 if (value.max != this->soft_max_value) {
180 return false;
181 }
182 return true;
183}
184
185bool Int::can_connect(const bNodeSocket &socket) const
186{
187 if (!sockets_can_connect(*this, socket)) {
188 return false;
189 }
190 return basic_types_can_connect(*this, socket);
191}
192
194{
195 if (socket.type != SOCK_INT) {
196 BLI_assert(socket.in_out == this->in_out);
197 return this->build(ntree, node);
198 }
199 if (socket.typeinfo->subtype != this->subtype) {
201 }
202 this->set_common_flags(socket);
204 value.min = this->soft_min_value;
205 value.max = this->soft_max_value;
206 value.subtype = this->subtype;
207 return socket;
208}
209
212/* -------------------------------------------------------------------- */
217{
219 &node,
220 this->in_out,
222 this->subtype,
223 this->identifier.c_str(),
224 this->name.c_str());
225 this->set_common_flags(socket);
227 copy_v3_v3(value.value, this->default_value);
228 value.min = this->soft_min_value;
229 value.max = this->soft_max_value;
230 return socket;
231}
232
233bool Vector::matches(const bNodeSocket &socket) const
234{
235 if (!this->matches_common_data(socket)) {
236 return false;
237 }
238 if (socket.type != SOCK_VECTOR) {
239 return false;
240 }
241 if (socket.typeinfo->subtype != this->subtype) {
242 return false;
243 }
244 const bNodeSocketValueVector &value = *static_cast<const bNodeSocketValueVector *>(
245 socket.default_value);
246 if (value.min != this->soft_min_value) {
247 return false;
248 }
249 if (value.max != this->soft_max_value) {
250 return false;
251 }
252 return true;
253}
254
255bool Vector::can_connect(const bNodeSocket &socket) const
256{
257 if (!sockets_can_connect(*this, socket)) {
258 return false;
259 }
260 if (socket.type == SOCK_ROTATION) {
261 return true;
262 }
263 return basic_types_can_connect(*this, socket);
264}
265
267{
268 if (socket.type != SOCK_VECTOR) {
269 BLI_assert(socket.in_out == this->in_out);
270 return this->build(ntree, node);
271 }
272 if (socket.typeinfo->subtype != this->subtype) {
274 }
275 this->set_common_flags(socket);
277 value.subtype = this->subtype;
278 value.min = this->soft_min_value;
279 value.max = this->soft_max_value;
280 return socket;
281}
282
285/* -------------------------------------------------------------------- */
290{
292 &node,
293 this->in_out,
295 PROP_NONE,
296 this->identifier.c_str(),
297 this->name.c_str());
298 this->set_common_flags(socket);
300 value.value = this->default_value;
301 return socket;
302}
303
304bool Bool::matches(const bNodeSocket &socket) const
305{
306 if (!this->matches_common_data(socket)) {
307 return false;
308 }
309 if (socket.type != SOCK_BOOLEAN) {
310 return false;
311 }
312 return true;
313}
314
315bool Bool::can_connect(const bNodeSocket &socket) const
316{
317 if (!sockets_can_connect(*this, socket)) {
318 return false;
319 }
320 return basic_types_can_connect(*this, socket);
321}
322
324{
325 if (socket.type != SOCK_BOOLEAN) {
326 BLI_assert(socket.in_out == this->in_out);
327 return this->build(ntree, node);
328 }
329 this->set_common_flags(socket);
330 return socket;
331}
332
335/* -------------------------------------------------------------------- */
340{
342 &node,
343 this->in_out,
344 SOCK_RGBA,
345 PROP_NONE,
346 this->identifier.c_str(),
347 this->name.c_str());
348 this->set_common_flags(socket);
350 copy_v4_v4(value.value, this->default_value);
351 return socket;
352}
353
354bool Color::matches(const bNodeSocket &socket) const
355{
356 if (!this->matches_common_data(socket)) {
357 return false;
358 }
359 if (socket.type != SOCK_RGBA) {
360 return false;
361 }
362 return true;
363}
364
365bool Color::can_connect(const bNodeSocket &socket) const
366{
367 if (!sockets_can_connect(*this, socket)) {
368 return false;
369 }
370 return basic_types_can_connect(*this, socket);
371}
372
374{
375 if (socket.type != SOCK_RGBA) {
376 BLI_assert(socket.in_out == this->in_out);
377 return this->build(ntree, node);
378 }
379 this->set_common_flags(socket);
380 return socket;
381}
382
384/* -------------------------------------------------------------------- */
389{
391 &node,
392 this->in_out,
394 PROP_NONE,
395 this->identifier.c_str(),
396 this->name.c_str());
397 this->set_common_flags(socket);
398 bNodeSocketValueRotation &value = *static_cast<bNodeSocketValueRotation *>(socket.default_value);
399 copy_v3_v3(value.value_euler, float3(this->default_value));
400 return socket;
401}
402
403bool Rotation::matches(const bNodeSocket &socket) const
404{
405 if (!this->matches_common_data(socket)) {
406 return false;
407 }
408 if (socket.type != SOCK_ROTATION) {
409 return false;
410 }
411 return true;
412}
413
414bool Rotation::can_connect(const bNodeSocket &socket) const
415{
416 if (!sockets_can_connect(*this, socket)) {
417 return false;
418 }
419 if (this->in_out == SOCK_IN) {
421 }
423}
424
426{
427 if (socket.type != SOCK_ROTATION) {
428 BLI_assert(socket.in_out == this->in_out);
429 return this->build(ntree, node);
430 }
431 this->set_common_flags(socket);
432 return socket;
433}
434
437/* -------------------------------------------------------------------- */
442{
444 &node,
445 this->in_out,
447 PROP_NONE,
448 this->identifier.c_str(),
449 this->name.c_str());
450 this->set_common_flags(socket);
451 return socket;
452}
453
454bool Matrix::matches(const bNodeSocket &socket) const
455{
456 if (!this->matches_common_data(socket)) {
457 return false;
458 }
459 if (socket.type != SOCK_MATRIX) {
460 return false;
461 }
462 return true;
463}
464
465bool Matrix::can_connect(const bNodeSocket &socket) const
466{
467 if (!sockets_can_connect(*this, socket)) {
468 return false;
469 }
470 if (this->in_out == SOCK_IN) {
472 }
473 return ELEM(socket.type, SOCK_MATRIX, SOCK_VECTOR, SOCK_MATRIX);
474}
475
477{
478 if (socket.type != SOCK_MATRIX) {
479 BLI_assert(socket.in_out == this->in_out);
480 return this->build(ntree, node);
481 }
482 this->set_common_flags(socket);
483 return socket;
484}
485
488/* -------------------------------------------------------------------- */
493{
495 &node,
496 this->in_out,
498 this->subtype,
499 this->identifier.c_str(),
500 this->name.c_str());
501 STRNCPY(((bNodeSocketValueString *)socket.default_value)->value, this->default_value.c_str());
502 this->set_common_flags(socket);
503 return socket;
504}
505
506bool String::matches(const bNodeSocket &socket) const
507{
508 if (!this->matches_common_data(socket)) {
509 return false;
510 }
511 if (socket.type != SOCK_STRING) {
512 return false;
513 }
514 if (socket.typeinfo->subtype != this->subtype) {
515 return false;
516 }
517 return true;
518}
519
520bool String::can_connect(const bNodeSocket &socket) const
521{
522 return sockets_can_connect(*this, socket) && socket.type == SOCK_STRING;
523}
524
526{
527 if (socket.type != SOCK_STRING) {
528 BLI_assert(socket.in_out == this->in_out);
529 return this->build(ntree, node);
530 }
531 if (socket.typeinfo->subtype != this->subtype) {
533 }
534 this->set_common_flags(socket);
536 value.subtype = this->subtype;
537 return socket;
538}
539
542/* -------------------------------------------------------------------- */
547{
549 &node,
550 this->in_out,
551 SOCK_MENU,
552 PROP_NONE,
553 this->identifier.c_str(),
554 this->name.c_str());
555
556 ((bNodeSocketValueMenu *)socket.default_value)->value = this->default_value;
557 this->set_common_flags(socket);
558 return socket;
559}
560
561bool Menu::matches(const bNodeSocket &socket) const
562{
563 if (!this->matches_common_data(socket)) {
564 return false;
565 }
566 if (socket.type != SOCK_MENU) {
567 return false;
568 }
569 return true;
570}
571
572bool Menu::can_connect(const bNodeSocket &socket) const
573{
574 return sockets_can_connect(*this, socket) && socket.type == SOCK_MENU;
575}
576
578{
579 if (socket.type != SOCK_MENU) {
580 BLI_assert(socket.in_out == this->in_out);
581 return this->build(ntree, node);
582 }
583 this->set_common_flags(socket);
584 return socket;
585}
586
589/* -------------------------------------------------------------------- */
594{
596 &ntree, &node, this->in_out, this->idname, this->identifier.c_str(), this->name.c_str());
597 if (this->default_value_fn) {
598 ID *id = this->default_value_fn(node);
599 /* Assumes that all ID sockets like #bNodeSocketValueObject and #bNodeSocketValueImage have the
600 * ID pointer at the start of the struct. */
601 *static_cast<ID **>(socket.default_value) = id;
602 id_us_plus(id);
603 }
604 this->set_common_flags(socket);
605 return socket;
606}
607
609{
610 if (!this->matches_common_data(socket)) {
611 return false;
612 }
613 if (!STREQ(socket.idname, this->idname)) {
614 return false;
615 }
616 return true;
617}
618
620{
621 return sockets_can_connect(*this, socket) && STREQ(socket.idname, this->idname);
622}
623
625 bNode &node,
626 bNodeSocket &socket) const
627{
628 if (StringRef(socket.idname) != this->idname) {
629 BLI_assert(socket.in_out == this->in_out);
630 return this->build(ntree, node);
631 }
632 this->set_common_flags(socket);
633 return socket;
634}
635
638/* -------------------------------------------------------------------- */
643{
644 bNodeSocket &socket = *bke::node_add_socket(&ntree,
645 &node,
646 this->in_out,
647 "NodeSocketGeometry",
648 this->identifier.c_str(),
649 this->name.c_str());
650 this->set_common_flags(socket);
651 return socket;
652}
653
654bool Geometry::matches(const bNodeSocket &socket) const
655{
656 if (!this->matches_common_data(socket)) {
657 return false;
658 }
659 if (socket.type != SOCK_GEOMETRY) {
660 return false;
661 }
662 return true;
663}
664
665bool Geometry::can_connect(const bNodeSocket &socket) const
666{
667 return sockets_can_connect(*this, socket) && socket.type == SOCK_GEOMETRY;
668}
669
671{
672 return supported_types_;
673}
674
676{
677 return only_realized_data_;
678}
679
681{
682 return only_instances_;
683}
684
686{
687 decl_->supported_types_ = {supported_type};
688 return *this;
689}
690
693{
694 decl_->supported_types_ = supported_types;
695 return *this;
696}
697
699{
700 decl_->only_realized_data_ = value;
701 return *this;
702}
703
705{
706 decl_->only_instances_ = value;
707 return *this;
708}
709
712/* -------------------------------------------------------------------- */
717{
718 bNodeSocket &socket = *bke::node_add_socket(&ntree,
719 &node,
720 this->in_out,
721 "NodeSocketShader",
722 this->identifier.c_str(),
723 this->name.c_str());
724 this->set_common_flags(socket);
725 return socket;
726}
727
728bool Shader::matches(const bNodeSocket &socket) const
729{
730 if (!this->matches_common_data(socket)) {
731 return false;
732 }
733 if (socket.type != SOCK_SHADER) {
734 return false;
735 }
736 return true;
737}
738
739bool Shader::can_connect(const bNodeSocket &socket) const
740{
741 if (!sockets_can_connect(*this, socket)) {
742 return false;
743 }
744 /* Basic types can convert to shaders, but not the other way around. */
745 if (this->in_out == SOCK_IN) {
746 return ELEM(
748 }
749 return socket.type == SOCK_SHADER;
750}
751
754/* -------------------------------------------------------------------- */
759{
760 bNodeSocket &socket = *bke::node_add_socket(&ntree,
761 &node,
762 this->in_out,
763 "NodeSocketVirtual",
764 this->identifier.c_str(),
765 this->name.c_str());
766 return socket;
767}
768
769bool Extend::matches(const bNodeSocket &socket) const
770{
771 if (socket.identifier != this->identifier) {
772 return false;
773 }
774 return true;
775}
776
777bool Extend::can_connect(const bNodeSocket & /*socket*/) const
778{
779 return false;
780}
781
783 bNode & /*node*/,
784 bNodeSocket &socket) const
785{
786 return socket;
787}
788
791/* -------------------------------------------------------------------- */
796{
798 &ntree, &node, this->in_out, idname_, this->identifier.c_str(), this->name.c_str());
799 if (this->init_socket_fn) {
800 this->init_socket_fn(node, socket, "interface");
801 }
802 return socket;
803}
804
805bool Custom::matches(const bNodeSocket &socket) const
806{
807 if (!this->matches_common_data(socket)) {
808 return false;
809 }
810 if (socket.type != SOCK_CUSTOM) {
811 return false;
812 }
813 if (!STREQ(socket.typeinfo->idname, idname_)) {
814 return false;
815 }
816 return true;
817}
818
819bool Custom::can_connect(const bNodeSocket &socket) const
820{
821 return sockets_can_connect(*this, socket) && STREQ(socket.idname, idname_);
822}
823
825{
826 if (!STREQ(socket.typeinfo->idname, idname_)) {
827 return this->build(ntree, node);
828 }
829 this->set_common_flags(socket);
830 return socket;
831}
832
834{
835 std::unique_ptr<decl::Extend> decl = std::make_unique<decl::Extend>();
836 decl->name = "";
837 decl->identifier = "__extend__";
838 decl->in_out = in_out;
839 return decl;
840}
841
844} // namespace blender::nodes::decl
void id_us_plus(ID *id)
Definition lib_id.cc:351
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ELEM(...)
#define STREQ(a, b)
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_SHADER
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_CUSTOM
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_STRING
@ SOCK_RGBA
@ SOCK_MENU
@ PROP_NONE
Definition RNA_types.hh:136
bool matches_common_data(const bNodeSocket &socket) const
void set_common_flags(bNodeSocket &socket) const
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
std::function< void(bNode &node, bNodeSocket &socket, const char *data_path)> init_socket_fn
bool can_connect(const bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool matches(const bNodeSocket &socket) const override
GeometryBuilder & only_realized_data(bool value=true)
GeometryBuilder & only_instances(bool value=true)
GeometryBuilder & supported_type(bke::GeometryComponent::Type supported_type)
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool can_connect(const bNodeSocket &socket) const override
Span< bke::GeometryComponent::Type > supported_types() const
bool matches(const bNodeSocket &socket) const override
std::function< ID *(const bNode &node)> default_value_fn
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool matches(const bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool matches(const bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool matches(const bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bool matches(const bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
bool can_connect(const bNodeSocket &socket) const override
bool matches(const bNodeSocket &socket) const override
bNodeSocket & build(bNodeTree &ntree, bNode &node) const override
bNodeSocket & update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override
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
bNodeSocketType * node_socket_type_find(const char *idname)
Definition node.cc:1763
const char * node_static_socket_type(int type, int subtype)
Definition node.cc:2126
bNodeSocket * node_add_socket(bNodeTree *ntree, bNode *node, eNodeSocketInOut in_out, const char *idname, const char *identifier, const char *name)
Definition node.cc:2095
static bool basic_types_can_connect(const SocketDeclaration &, const bNodeSocket &other_socket)
SocketDeclarationPtr create_extend_declaration(const eNodeSocketInOut in_out)
static void modify_subtype_except_for_storage(bNodeSocket &socket, int new_subtype)
static bool field_types_are_compatible(const SocketDeclaration &input, const SocketDeclaration &output)
static bool sockets_can_connect(const SocketDeclaration &socket_decl, const bNodeSocket &other_socket)
std::unique_ptr< SocketDeclaration > SocketDeclarationPtr
Definition DNA_ID.h:413
bNodeSocketRuntimeHandle * runtime
bNodeSocketTypeHandle * typeinfo
void * default_value
char identifier[64]
char idname[64]
Defines a socket type.
Definition BKE_node.hh:151