Blender V5.0
graph/node.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "graph/node.h"
6#include "graph/node_type.h"
7
8#include "util/md5.h"
9#include "util/param.h"
10#include "util/transform.h"
11
13
14/* Node Type */
15
16NodeOwner::~NodeOwner() = default;
17
18Node::Node(const NodeType *type_, ustring name_) : name(name_), type(type_)
19{
20 assert(type);
21
22 owner = nullptr;
24
25 /* assign non-empty name, convenient for debugging */
26 if (name.empty()) {
27 name = type->name;
28 }
29
30 /* initialize default values */
31 for (const SocketType &socket : type->inputs) {
32 set_default_value(socket);
33 }
34}
35
37
38#ifndef NDEBUG
39static bool is_socket_float3(const SocketType &socket)
40{
41 return socket.type == SocketType::COLOR || socket.type == SocketType::POINT ||
42 socket.type == SocketType::VECTOR || socket.type == SocketType::NORMAL;
43}
44
45static bool is_socket_array_float3(const SocketType &socket)
46{
47 return socket.type == SocketType::COLOR_ARRAY || socket.type == SocketType::POINT_ARRAY ||
49}
50#endif
51
52/* set values */
53void Node::set(const SocketType &input, bool value)
54{
56 set_if_different(input, value);
57}
58
59void Node::set(const SocketType &input, const int value)
60{
62 set_if_different(input, value);
63}
64
65void Node::set(const SocketType &input, const uint value)
66{
68 set_if_different(input, value);
69}
70
71void Node::set(const SocketType &input, const uint64_t value)
72{
74 set_if_different(input, value);
75}
76
77void Node::set(const SocketType &input, const float value)
78{
80 set_if_different(input, value);
81}
82
83void Node::set(const SocketType &input, const float2 value)
84{
86 set_if_different(input, value);
87}
88
89void Node::set(const SocketType &input, const float3 value)
90{
92 set_if_different(input, value);
93}
94
95void Node::set(const SocketType &input, const char *value)
96{
97 set(input, ustring(value));
98}
99
100void Node::set(const SocketType &input, ustring value)
101{
102 if (input.type == SocketType::STRING) {
103 set_if_different(input, value);
104 }
105 else if (input.type == SocketType::ENUM) {
106 const NodeEnum &enm = *input.enum_values;
107 if (enm.exists(value)) {
108 set_if_different(input, enm[value]);
109 }
110 else {
111 assert(0);
112 }
113 }
114 else {
115 assert(0);
116 }
117}
118
119void Node::set(const SocketType &input, const Transform &value)
120{
122 set_if_different(input, value);
123}
124
125void Node::set(const SocketType &input, Node *value)
126{
128 set_if_different(input, value);
129}
130
131/* set array values */
133{
135 set_if_different(input, value);
136}
137
139{
141 set_if_different(input, value);
142}
143
145{
147 set_if_different(input, value);
148}
149
151{
153 set_if_different(input, value);
154}
155
161
163{
165 set_if_different(input, value);
166}
167
173
175{
177 set_if_different(input, value);
178}
179
180/* get values */
182{
184 return get_socket_value<bool>(this, input);
185}
186
188{
190 return get_socket_value<int>(this, input);
191}
192
194{
196 return get_socket_value<uint>(this, input);
197}
198
204
206{
208 return get_socket_value<float>(this, input);
209}
210
212{
214 return get_socket_value<float2>(this, input);
215}
216
222
223ustring Node::get_string(const SocketType &input) const
224{
225 if (input.type == SocketType::STRING) {
226 return get_socket_value<ustring>(this, input);
227 }
228 if (input.type == SocketType::ENUM) {
229 const NodeEnum &enm = *input.enum_values;
230 const int intvalue = get_socket_value<int>(this, input);
231 return (enm.exists(intvalue)) ? enm[intvalue] : ustring();
232 }
233 assert(0);
234 return ustring();
235}
236
242
244{
246 return get_socket_value<Node *>(this, input);
247}
248
249/* get array values */
255
261
267
273
279
285
291
297
298/* generic value operations */
299
301{
302 const void *src = input.default_value;
303 void *dst = &get_socket_value<char>(this, input);
304 return memcmp(dst, src, input.packed_size()) == 0;
305}
306
308{
309 const void *src = input.default_value;
310 void *dst = ((char *)this) + input.struct_offset;
311 if (input.packed_size() > 0) {
312 memcpy(dst, src, input.packed_size());
313 }
314}
315
316template<typename T>
317static void copy_array(const Node *node,
318 const SocketType &socket,
319 const Node *other,
320 const SocketType &other_socket)
321{
322 const array<T> *src = (const array<T> *)(((char *)other) + other_socket.struct_offset);
323 array<T> *dst = (array<T> *)(((char *)node) + socket.struct_offset);
324 *dst = *src;
325}
326
327void Node::copy_value(const SocketType &socket, const Node &other, const SocketType &other_socket)
328{
329 assert(socket.type == other_socket.type);
330
331 if (socket.is_array()) {
332 switch (socket.type) {
334 copy_array<bool>(this, socket, &other, other_socket);
335 break;
337 copy_array<float>(this, socket, &other, other_socket);
338 break;
340 copy_array<int>(this, socket, &other, other_socket);
341 break;
343 copy_array<float3>(this, socket, &other, other_socket);
344 break;
346 copy_array<float3>(this, socket, &other, other_socket);
347 break;
349 copy_array<float3>(this, socket, &other, other_socket);
350 break;
352 copy_array<float3>(this, socket, &other, other_socket);
353 break;
355 copy_array<float2>(this, socket, &other, other_socket);
356 break;
358 copy_array<ustring>(this, socket, &other, other_socket);
359 break;
361 copy_array<Transform>(this, socket, &other, other_socket);
362 break;
364 copy_array<void *>(this, socket, &other, other_socket);
365
366 const array<Node *> &node_array = get_socket_value<array<Node *>>(this, socket);
367
368 for (Node *node : node_array) {
369 node->reference();
370 }
371
372 break;
373 }
374 default:
375 assert(0);
376 break;
377 }
378 }
379 else {
380 const void *src = ((char *)&other) + other_socket.struct_offset;
381 void *dst = ((char *)this) + socket.struct_offset;
382 memcpy(dst, src, socket.storage_size());
383
384 if (socket.type == SocketType::NODE) {
385 Node *node = get_socket_value<Node *>(this, socket);
386
387 if (node) {
388 node->reference();
389 }
390 }
391 }
392}
393
394void Node::set_value(const SocketType &socket, const Node &other, const SocketType &other_socket)
395{
396 assert(socket.type == other_socket.type);
397 (void)other_socket;
398
399 if (socket.is_array()) {
400 switch (socket.type) {
402 set(socket, get_socket_value<array<bool>>(&other, socket));
403 break;
405 set(socket, get_socket_value<array<float>>(&other, socket));
406 break;
408 set(socket, get_socket_value<array<int>>(&other, socket));
409 break;
414 set(socket, get_socket_value<array<float3>>(&other, socket));
415 break;
417 set(socket, get_socket_value<array<float2>>(&other, socket));
418 break;
420 set(socket, get_socket_value<array<ustring>>(&other, socket));
421 break;
423 set(socket, get_socket_value<array<Transform>>(&other, socket));
424 break;
426 set(socket, get_socket_value<array<Node *>>(&other, socket));
427 break;
428 default:
429 assert(0);
430 break;
431 }
432 }
433 else {
434 switch (socket.type) {
436 set(socket, get_socket_value<bool>(&other, socket));
437 break;
439 set(socket, get_socket_value<float>(&other, socket));
440 break;
441 case SocketType::INT:
442 set(socket, get_socket_value<int>(&other, socket));
443 break;
444 case SocketType::UINT:
445 set(socket, get_socket_value<uint>(&other, socket));
446 break;
448 set(socket, get_socket_value<uint64_t>(&other, socket));
449 break;
454 set(socket, get_socket_value<float3>(&other, socket));
455 break;
457 set(socket, get_socket_value<float2>(&other, socket));
458 break;
460 set(socket, get_socket_value<ustring>(&other, socket));
461 break;
462 case SocketType::ENUM:
463 set(socket, get_socket_value<int>(&other, socket));
464 break;
466 set(socket, get_socket_value<Transform>(&other, socket));
467 break;
468 case SocketType::NODE:
469 set(socket, get_socket_value<Node *>(&other, socket));
470 break;
471 default:
472 assert(0);
473 break;
474 }
475 }
476}
477
478template<typename T>
479static bool is_array_equal(const Node *node, const Node *other, const SocketType &socket)
480{
481 const array<T> *a = (const array<T> *)(((char *)node) + socket.struct_offset);
482 const array<T> *b = (const array<T> *)(((char *)other) + socket.struct_offset);
483 return *a == *b;
484}
485
486template<typename T>
487static bool is_value_equal(const Node *node, const Node *other, const SocketType &socket)
488{
489 const T *a = (const T *)(((char *)node) + socket.struct_offset);
490 const T *b = (const T *)(((char *)other) + socket.struct_offset);
491 return *a == *b;
492}
493
494bool Node::equals_value(const Node &other, const SocketType &socket) const
495{
496 switch (socket.type) {
498 return is_value_equal<bool>(this, &other, socket);
500 return is_value_equal<float>(this, &other, socket);
501 case SocketType::INT:
502 return is_value_equal<int>(this, &other, socket);
503 case SocketType::UINT:
504 return is_value_equal<uint>(this, &other, socket);
506 return is_value_equal<uint64_t>(this, &other, socket);
508 return is_value_equal<float3>(this, &other, socket);
510 return is_value_equal<float3>(this, &other, socket);
512 return is_value_equal<float3>(this, &other, socket);
514 return is_value_equal<float3>(this, &other, socket);
516 return is_value_equal<float2>(this, &other, socket);
518 return true;
520 return is_value_equal<ustring>(this, &other, socket);
521 case SocketType::ENUM:
522 return is_value_equal<int>(this, &other, socket);
524 return is_value_equal<Transform>(this, &other, socket);
525 case SocketType::NODE:
526 return is_value_equal<void *>(this, &other, socket);
527
529 return is_array_equal<bool>(this, &other, socket);
531 return is_array_equal<float>(this, &other, socket);
533 return is_array_equal<int>(this, &other, socket);
535 return is_array_equal<float3>(this, &other, socket);
537 return is_array_equal<float3>(this, &other, socket);
539 return is_array_equal<float3>(this, &other, socket);
541 return is_array_equal<float3>(this, &other, socket);
543 return is_array_equal<float2>(this, &other, socket);
545 return is_array_equal<ustring>(this, &other, socket);
547 return is_array_equal<Transform>(this, &other, socket);
549 return is_array_equal<void *>(this, &other, socket);
550
553 return true;
554 }
555
556 return true;
557}
558
559/* equals */
560
561bool Node::equals(const Node &other) const
562{
563 assert(type == other.type);
564
565 for (const SocketType &socket : type->inputs) {
566 if (!equals_value(other, socket)) {
567 return false;
568 }
569 }
570
571 return true;
572}
573
574/* Hash */
575
576namespace {
577
578template<typename T> void value_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
579{
580 md5.append(((uint8_t *)node) + socket.struct_offset, socket.packed_size());
581}
582
583void float3_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
584{
585 /* Don't compare 4th element used for padding. */
586 md5.append(((uint8_t *)node) + socket.struct_offset, sizeof(float) * 3);
587}
588
589template<typename T> void array_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
590{
591 const array<T> &a = *(const array<T> *)(((char *)node) + socket.struct_offset);
592 for (size_t i = 0; i < a.size(); i++) {
593 md5.append((uint8_t *)&a[i], sizeof(T));
594 }
595}
596
597void float3_array_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
598{
599 /* Don't compare 4th element used for padding. */
600 const array<float3> &a = *(const array<float3> *)(((char *)node) + socket.struct_offset);
601 for (size_t i = 0; i < a.size(); i++) {
602 md5.append((uint8_t *)&a[i], sizeof(float) * 3);
603 }
604}
605
606} // namespace
607
609{
610 md5.append(type->name.string());
611
612 for (const SocketType &socket : type->inputs) {
613 md5.append(socket.name.string());
614
615 switch (socket.type) {
617 value_hash<bool>(this, socket, md5);
618 break;
620 value_hash<float>(this, socket, md5);
621 break;
622 case SocketType::INT:
623 value_hash<int>(this, socket, md5);
624 break;
625 case SocketType::UINT:
626 value_hash<uint>(this, socket, md5);
627 break;
629 value_hash<uint64_t>(this, socket, md5);
630 break;
632 float3_hash(this, socket, md5);
633 break;
635 float3_hash(this, socket, md5);
636 break;
638 float3_hash(this, socket, md5);
639 break;
641 float3_hash(this, socket, md5);
642 break;
644 value_hash<float2>(this, socket, md5);
645 break;
647 break;
649 value_hash<ustring>(this, socket, md5);
650 break;
651 case SocketType::ENUM:
652 value_hash<int>(this, socket, md5);
653 break;
655 value_hash<Transform>(this, socket, md5);
656 break;
657 case SocketType::NODE:
658 value_hash<void *>(this, socket, md5);
659 break;
660
662 array_hash<bool>(this, socket, md5);
663 break;
665 array_hash<float>(this, socket, md5);
666 break;
668 array_hash<int>(this, socket, md5);
669 break;
671 float3_array_hash(this, socket, md5);
672 break;
674 float3_array_hash(this, socket, md5);
675 break;
677 float3_array_hash(this, socket, md5);
678 break;
680 float3_array_hash(this, socket, md5);
681 break;
683 array_hash<float2>(this, socket, md5);
684 break;
686 array_hash<ustring>(this, socket, md5);
687 break;
689 array_hash<Transform>(this, socket, md5);
690 break;
692 array_hash<void *>(this, socket, md5);
693 break;
694
697 break;
698 }
699 }
700}
701
702namespace {
703
704template<typename T> size_t array_size_in_bytes(const Node *node, const SocketType &socket)
705{
706 const array<T> &a = *(const array<T> *)(((char *)node) + socket.struct_offset);
707 return a.size() * sizeof(T);
708}
709
710} // namespace
711
713{
714 size_t total_size = 0;
715 for (const SocketType &socket : type->inputs) {
716 switch (socket.type) {
719 case SocketType::INT:
720 case SocketType::UINT:
729 case SocketType::ENUM:
731 case SocketType::NODE:
732 total_size += socket.storage_size();
733 break;
734
736 total_size += array_size_in_bytes<bool>(this, socket);
737 break;
739 total_size += array_size_in_bytes<float>(this, socket);
740 break;
742 total_size += array_size_in_bytes<int>(this, socket);
743 break;
745 total_size += array_size_in_bytes<float3>(this, socket);
746 break;
748 total_size += array_size_in_bytes<float3>(this, socket);
749 break;
751 total_size += array_size_in_bytes<float3>(this, socket);
752 break;
754 total_size += array_size_in_bytes<float3>(this, socket);
755 break;
757 total_size += array_size_in_bytes<float2>(this, socket);
758 break;
760 total_size += array_size_in_bytes<ustring>(this, socket);
761 break;
763 total_size += array_size_in_bytes<Transform>(this, socket);
764 break;
766 total_size += array_size_in_bytes<void *>(this, socket);
767 break;
768
771 break;
772 }
773 }
774 return total_size;
775}
776
777bool Node::is_a(const NodeType *type_)
778{
779 for (const NodeType *base = type; base; base = base->base) {
780 if (base == type_) {
781 return true;
782 }
783 }
784 return false;
785}
786
788{
789 return owner;
790}
791
792void Node::set_owner(const NodeOwner *owner_)
793{
794 assert(owner_);
795 owner = owner_;
796}
797
799{
800 for (const SocketType &socket : type->inputs) {
801 if (socket.type == SocketType::NODE) {
802 Node *node = get_socket_value<Node *>(this, socket);
803
804 if (node) {
805 node->dereference();
806 }
807 }
808 else if (socket.type == SocketType::NODE_ARRAY) {
809 const array<Node *> &nodes = get_socket_value<array<Node *>>(this, socket);
810
811 for (Node *node : nodes) {
812 node->dereference();
813 }
814 }
815 }
816}
817
819{
820 return (socket_modified & input.modified_flag_bit) != 0;
821}
822
824{
825 return socket_modified != 0;
826}
827
829{
830 socket_modified = ~0ull;
831}
832
834{
835 socket_modified = 0;
836}
837
838template<typename T> void Node::set_if_different(const SocketType &input, T value)
839{
840 if (get_socket_value<T>(this, input) == value) {
841 return;
842 }
843
844 get_socket_value<T>(this, input) = value;
845 socket_modified |= input.modified_flag_bit;
846}
847
849{
850 if (get_socket_value<Node *>(this, input) == value) {
851 return;
852 }
853
854 Node *old_node = get_socket_value<Node *>(this, input);
855 if (old_node) {
856 old_node->dereference();
857 }
858
859 if (value) {
860 value->reference();
861 }
862
863 get_socket_value<Node *>(this, input) = value;
864 socket_modified |= input.modified_flag_bit;
865}
866
867template<typename T> void Node::set_if_different(const SocketType &input, array<T> &value)
868{
870 if (get_socket_value<array<T>>(this, input) == value) {
871 return;
872 }
873 }
874
875 get_socket_value<array<T>>(this, input).steal_data(value);
876 socket_modified |= input.modified_flag_bit;
877}
878
880{
882 if (get_socket_value<array<Node *>>(this, input) == value) {
883 return;
884 }
885 }
886
887 const array<Node *> &old_nodes = get_socket_value<array<Node *>>(this, input);
888 for (Node *old_node : old_nodes) {
889 old_node->dereference();
890 }
891
892 for (Node *new_node : value) {
893 new_node->reference();
894 }
895
896 get_socket_value<array<Node *>>(this, input).steal_data(value);
897 socket_modified |= input.modified_flag_bit;
898}
899
901{
902 printf("Node : %s\n", name.c_str());
903 for (const auto &socket : type->inputs) {
904 if (socket_is_modified(socket)) {
905 printf("-- socket modified : %s\n", socket.name.c_str());
906 }
907 }
908}
909
unsigned int uint
unsigned long long int uint64_t
Definition md5.h:19
void append(const uint8_t *data, const int nbytes)
Definition md5.cpp:268
size_t size() const
#define CCL_NAMESPACE_END
#define input
#define assert(assertion)
#define printf(...)
static bool is_socket_array_float3(const SocketType &socket)
static bool is_array_equal(const Node *node, const Node *other, const SocketType &socket)
static bool is_value_equal(const Node *node, const Node *other, const SocketType &socket)
static bool is_socket_float3(const SocketType &socket)
static void copy_array(const Node *node, const SocketType &socket, const Node *other, const SocketType &other_socket)
#define T
bool exists(ustring x) const
Definition node_enum.h:29
virtual ~NodeOwner()
bool has_default_value(const SocketType &input) const
const array< float3 > & get_float3_array(const SocketType &input) const
bool equals(const Node &other) const
const array< float > & get_float_array(const SocketType &input) const
const array< int > & get_int_array(const SocketType &input) const
void dereference()
Definition graph/node.h:193
const NodeOwner * owner
Definition graph/node.h:207
float get_float(const SocketType &input) const
Transform get_transform(const SocketType &input) const
void set(const SocketType &input, bool value)
uint64_t get_uint64(const SocketType &input) const
const NodeType * type
Definition graph/node.h:178
void dereference_all_used_nodes()
float3 get_float3(const SocketType &input) const
void set_default_value(const SocketType &input)
static T & get_socket_value(const Node *node, const SocketType &socket)
Definition graph/node.h:210
const array< bool > & get_bool_array(const SocketType &input) const
const array< Node * > & get_node_array(const SocketType &input) const
void set_value(const SocketType &socket, const Node &other, const SocketType &other_socket)
ustring name
Definition graph/node.h:177
size_t get_total_size_in_bytes() const
void copy_value(const SocketType &socket, const Node &other, const SocketType &other_socket)
SocketModifiedFlags socket_modified
Definition graph/node.h:215
bool get_bool(const SocketType &input) const
float2 get_float2(const SocketType &input) const
void clear_modified()
bool equals_value(const Node &other, const SocketType &socket) const
void reference()
Definition graph/node.h:188
const array< ustring > & get_string_array(const SocketType &input) const
const array< float2 > & get_float2_array(const SocketType &input) const
void hash(MD5Hash &md5)
bool socket_is_modified(const SocketType &input) const
ustring get_string(const SocketType &input) const
bool is_a(const NodeType *type)
void set_if_different(const SocketType &input, T value)
Node * get_node(const SocketType &input) const
virtual ~Node()=0
const NodeOwner * get_owner() const
void tag_modified()
bool is_modified() const
uint get_uint(const SocketType &input) const
Node(const NodeType *type, ustring name=ustring())
int get_int(const SocketType &input) const
const array< Transform > & get_transform_array(const SocketType &input) const
void print_modified_sockets() const
void set_owner(const NodeOwner *owner_)
ustring name
Definition node_type.h:81
@ BOOLEAN_ARRAY
Definition node_type.h:45
@ TRANSFORM_ARRAY
Definition node_type.h:54
Type type
Definition node_type.h:82
size_t storage_size() const
Definition node_type.cpp:15
size_t packed_size() const
Definition node_type.cpp:20
bool is_array() const
Definition node_type.cpp:25
int struct_offset
Definition node_type.h:83
i
Definition text_draw.cc:230