Blender V4.3
node.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "CLG_log.h"
10
11#include "MEM_guardedalloc.h"
12
13#include <climits>
14#include <cstddef>
15#include <cstdlib>
16#include <cstring>
17#include <optional>
18
19/* Allow using deprecated functionality for .blend file I/O. */
20#define DNA_DEPRECATED_ALLOW
21
22#include "DNA_action_types.h"
23#include "DNA_anim_types.h"
26#include "DNA_light_types.h"
27#include "DNA_linestyle_types.h"
28#include "DNA_material_types.h"
29#include "DNA_modifier_types.h"
30#include "DNA_node_types.h"
31#include "DNA_scene_types.h"
32#include "DNA_texture_types.h"
33#include "DNA_world_types.h"
34
35#include "BLI_color.hh"
36#include "BLI_ghash.h"
37#include "BLI_listbase.h"
38#include "BLI_map.hh"
40#include "BLI_path_utils.hh"
41#include "BLI_rand.hh"
42#include "BLI_set.hh"
43#include "BLI_stack.hh"
44#include "BLI_string.h"
45#include "BLI_string_utf8.h"
46#include "BLI_string_utils.hh"
47#include "BLI_threads.h"
48#include "BLI_time.h"
49#include "BLI_utildefines.h"
50#include "BLI_vector_set.hh"
51#include "BLT_translation.hh"
52
53#include "IMB_imbuf.hh"
54
55#include "BKE_anim_data.hh"
56#include "BKE_animsys.h"
57#include "BKE_asset.hh"
58#include "BKE_bpath.hh"
59#include "BKE_colortools.hh"
60#include "BKE_context.hh"
61#include "BKE_cryptomatte.h"
62#include "BKE_global.hh"
63#include "BKE_idprop.hh"
64#include "BKE_idtype.hh"
65#include "BKE_image_format.hh"
66#include "BKE_lib_id.hh"
67#include "BKE_lib_query.hh"
68#include "BKE_main.hh"
69#include "BKE_node.hh"
70#include "BKE_node_enum.hh"
71#include "BKE_node_runtime.hh"
76#include "BKE_preview_image.hh"
78
79#include "RNA_access.hh"
80#include "RNA_define.hh"
81#include "RNA_enum_types.hh"
82#include "RNA_prototypes.hh"
83
84#include "NOD_common.h"
85#include "NOD_composite.hh"
86#include "NOD_geo_bake.hh"
91#include "NOD_geo_repeat.hh"
92#include "NOD_geo_simulation.hh"
93#include "NOD_geometry.hh"
97#include "NOD_register.hh"
98#include "NOD_shader.h"
99#include "NOD_socket.hh"
100#include "NOD_texture.h"
101
102#include "DEG_depsgraph.hh"
103#include "DEG_depsgraph_build.hh"
104
105#include "BLO_read_write.hh"
106
107using blender::Array;
108using blender::Map;
110using blender::Set;
111using blender::Span;
112using blender::Stack;
114using blender::Vector;
122using blender::nodes::OutputFieldDependency;
125
126static CLG_LogRef LOG = {"bke.node"};
127
128namespace blender::bke {
129
130/* Forward declaration. */
131static void write_node_socket_default_value(BlendWriter *writer, const bNodeSocket *sock);
132
133/* Fallback types for undefined tree, nodes, sockets. */
137
138static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo);
139static void node_socket_set_typeinfo(bNodeTree *ntree,
140 bNodeSocket *sock,
141 bNodeSocketType *typeinfo);
142static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag);
143static void free_localized_node_groups(bNodeTree *ntree);
144static bool socket_id_user_decrement(bNodeSocket *sock);
145
146static void ntree_init_data(ID *id)
147{
148 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
149 ntree->tree_interface.init_data();
150 ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
152 ntree_set_typeinfo(ntree, nullptr);
153}
154
155static void ntree_copy_data(Main * /*bmain*/,
156 std::optional<Library *> /*owner_library*/,
157 ID *id_dst,
158 const ID *id_src,
159 const int flag)
160{
161 bNodeTree *ntree_dst = reinterpret_cast<bNodeTree *>(id_dst);
162 const bNodeTree *ntree_src = reinterpret_cast<const bNodeTree *>(id_src);
163
164 /* We never handle user-count here for owned data. */
165 const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
166
167 ntree_dst->runtime = MEM_new<bNodeTreeRuntime>(__func__);
168 bNodeTreeRuntime &dst_runtime = *ntree_dst->runtime;
169
171
172 dst_runtime.nodes_by_id.reserve(ntree_src->all_nodes().size());
173 BLI_listbase_clear(&ntree_dst->nodes);
174 int i;
175 LISTBASE_FOREACH_INDEX (const bNode *, src_node, &ntree_src->nodes, i) {
176 /* Don't find a unique name for every node, since they should have valid names already. */
177 bNode *new_node = node_copy_with_mapping(
178 ntree_dst, *src_node, flag_subdata, false, socket_map);
179 dst_runtime.nodes_by_id.add_new(new_node);
180 new_node->runtime->index_in_tree = i;
181 }
182
183 /* copy links */
184 BLI_listbase_clear(&ntree_dst->links);
185 LISTBASE_FOREACH (const bNodeLink *, src_link, &ntree_src->links) {
186 bNodeLink *dst_link = static_cast<bNodeLink *>(MEM_dupallocN(src_link));
187 dst_link->fromnode = dst_runtime.nodes_by_id.lookup_key_as(src_link->fromnode->identifier);
188 dst_link->fromsock = socket_map.lookup(src_link->fromsock);
189 dst_link->tonode = dst_runtime.nodes_by_id.lookup_key_as(src_link->tonode->identifier);
190 dst_link->tosock = socket_map.lookup(src_link->tosock);
191 BLI_assert(dst_link->tosock);
192 dst_link->tosock->link = dst_link;
193 BLI_addtail(&ntree_dst->links, dst_link);
194 }
195
196 /* update node->parent pointers */
197 for (bNode *node : ntree_dst->all_nodes()) {
198 if (node->parent) {
199 node->parent = dst_runtime.nodes_by_id.lookup_key_as(node->parent->identifier);
200 }
201 }
202
203 for (bNode *node : ntree_dst->all_nodes()) {
204 node_declaration_ensure(ntree_dst, node);
205 }
206
207 ntree_dst->tree_interface.copy_data(ntree_src->tree_interface, flag);
208 /* copy preview hash */
209 if (ntree_src->previews && (flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
211
212 ntree_dst->previews = node_instance_hash_new("node previews");
213
214 NODE_INSTANCE_HASH_ITER (iter, ntree_src->previews) {
216 bNodePreview *preview = static_cast<bNodePreview *>(
218 node_instance_hash_insert(ntree_dst->previews, key, node_preview_copy(preview));
219 }
220 }
221 else {
222 ntree_dst->previews = nullptr;
223 }
224
225 if (ntree_src->runtime->field_inferencing_interface) {
226 dst_runtime.field_inferencing_interface = std::make_unique<FieldInferencingInterface>(
227 *ntree_src->runtime->field_inferencing_interface);
228 }
229 if (ntree_src->runtime->anonymous_attribute_inferencing) {
230 using namespace anonymous_attribute_inferencing;
232 std::make_unique<AnonymousAttributeInferencingResult>(
233 *ntree_src->runtime->anonymous_attribute_inferencing);
234 for (FieldSource &field_source :
235 dst_runtime.anonymous_attribute_inferencing->all_field_sources)
236 {
237 if (auto *socket_field_source = std::get_if<SocketFieldSource>(&field_source.data)) {
238 socket_field_source->socket = socket_map.lookup(socket_field_source->socket);
239 }
240 }
241 for (GeometrySource &geometry_source :
242 dst_runtime.anonymous_attribute_inferencing->all_geometry_sources)
243 {
244 if (auto *socket_geometry_source = std::get_if<SocketGeometrySource>(&geometry_source.data))
245 {
246 socket_geometry_source->socket = socket_map.lookup(socket_geometry_source->socket);
247 }
248 }
249 }
250
251 if (ntree_src->geometry_node_asset_traits) {
252 ntree_dst->geometry_node_asset_traits = MEM_cnew<GeometryNodeAssetTraits>(
253 __func__, *ntree_src->geometry_node_asset_traits);
254 }
255
256 if (ntree_src->nested_node_refs) {
257 ntree_dst->nested_node_refs = static_cast<bNestedNodeRef *>(
258 MEM_malloc_arrayN(ntree_src->nested_node_refs_num, sizeof(bNestedNodeRef), __func__));
260 ntree_src->nested_node_refs, ntree_src->nested_node_refs_num, ntree_dst->nested_node_refs);
261 }
262
264 ntree_dst->preview = nullptr;
265 }
266 else {
267 BKE_previewimg_id_copy(&ntree_dst->id, &ntree_src->id);
268 }
269
270 ntree_dst->description = BLI_strdup_null(ntree_src->description);
271}
272
273static void ntree_free_data(ID *id)
274{
275 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
276
277 /* XXX hack! node trees should not store execution graphs at all.
278 * This should be removed when old tree types no longer require it.
279 * Currently the execution data for texture nodes remains in the tree
280 * after execution, until the node tree is updated or freed. */
281 if (ntree->runtime->execdata) {
282 switch (ntree->type) {
283 case NTREE_SHADER:
284 ntreeShaderEndExecTree(ntree->runtime->execdata);
285 break;
286 case NTREE_TEXTURE:
287 ntreeTexEndExecTree(ntree->runtime->execdata);
288 ntree->runtime->execdata = nullptr;
289 break;
290 }
291 }
292
293 /* XXX not nice, but needed to free localized node groups properly */
295
296 BLI_freelistN(&ntree->links);
297
298 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
299 node_free_node(ntree, node);
300 }
301
302 ntree->tree_interface.free_data();
303
304 /* free preview hash */
305 if (ntree->previews) {
307 }
308
309 if (ntree->id.tag & ID_TAG_LOCALIZED) {
310 BKE_libblock_free_data(&ntree->id, true);
311 }
312
313 if (ntree->geometry_node_asset_traits) {
315 }
316
317 if (ntree->nested_node_refs) {
319 }
320
323 MEM_delete(ntree->runtime);
324}
325
327{
329 data, IDP_foreach_property(sock->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
330 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
331 }));
332
333 switch (eNodeSocketDatatype(sock->type)) {
334 case SOCK_OBJECT: {
335 bNodeSocketValueObject &default_value = *sock->default_value_typed<bNodeSocketValueObject>();
337 break;
338 }
339 case SOCK_IMAGE: {
340 bNodeSocketValueImage &default_value = *sock->default_value_typed<bNodeSocketValueImage>();
342 break;
343 }
344 case SOCK_COLLECTION: {
345 bNodeSocketValueCollection &default_value =
346 *sock->default_value_typed<bNodeSocketValueCollection>();
348 break;
349 }
350 case SOCK_TEXTURE: {
351 bNodeSocketValueTexture &default_value =
352 *sock->default_value_typed<bNodeSocketValueTexture>();
354 break;
355 }
356 case SOCK_MATERIAL: {
357 bNodeSocketValueMaterial &default_value =
358 *sock->default_value_typed<bNodeSocketValueMaterial>();
360 break;
361 }
362 case SOCK_FLOAT:
363 case SOCK_VECTOR:
364 case SOCK_RGBA:
365 case SOCK_BOOLEAN:
366 case SOCK_ROTATION:
367 case SOCK_MATRIX:
368 case SOCK_INT:
369 case SOCK_STRING:
370 case SOCK_CUSTOM:
371 case SOCK_SHADER:
372 case SOCK_GEOMETRY:
373 case SOCK_MENU:
374 break;
375 }
376}
377
379{
381
383 data, IDP_foreach_property(node->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
384 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
385 }));
386 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
388 }
389 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
391 }
392
393 /* Note that this ID pointer is only a cache, it may be outdated. */
394 BKE_LIB_FOREACHID_PROCESS_ID(data, node->runtime->owner_tree, IDWALK_CB_LOOPBACK);
395}
396
398{
399 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
400
402 data,
403 ntree->owner_id,
405
407
408 for (bNode *node : ntree->all_nodes()) {
409 node_node_foreach_id(node, data);
410 }
411
412 ntree->tree_interface.foreach_id(data);
413}
414
415static void node_foreach_cache(ID *id,
416 IDTypeForeachCacheFunctionCallback function_callback,
417 void *user_data)
418{
419 bNodeTree *nodetree = reinterpret_cast<bNodeTree *>(id);
420 IDCacheKey key = {0};
421 key.id_session_uid = id->session_uid;
422 key.identifier = offsetof(bNodeTree, previews);
423
424 /* TODO: see also `direct_link_nodetree()` in `readfile.cc`. */
425#if 0
426 function_callback(id, &key, static_cast<void **>(&nodetree->previews), 0, user_data);
427#endif
428
429 if (nodetree->type == NTREE_COMPOSIT) {
430 for (bNode *node : nodetree->all_nodes()) {
431 if (node->type == CMP_NODE_MOVIEDISTORTION) {
432 key.identifier = size_t(BLI_ghashutil_strhash_p(node->name));
433 function_callback(id, &key, static_cast<void **>(&node->storage), 0, user_data);
434 }
435 }
436 }
437}
438
439static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
440{
441 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
442
443 switch (ntree->type) {
444 case NTREE_SHADER: {
445 for (bNode *node : ntree->all_nodes()) {
446 if (node->type == SH_NODE_SCRIPT) {
447 NodeShaderScript *nss = static_cast<NodeShaderScript *>(node->storage);
448 BKE_bpath_foreach_path_fixed_process(bpath_data, nss->filepath, sizeof(nss->filepath));
449 }
450 else if (node->type == SH_NODE_TEX_IES) {
451 NodeShaderTexIES *ies = static_cast<NodeShaderTexIES *>(node->storage);
452 BKE_bpath_foreach_path_fixed_process(bpath_data, ies->filepath, sizeof(ies->filepath));
453 }
454 }
455 break;
456 }
457 default:
458 break;
459 }
460}
461
462static ID **node_owner_pointer_get(ID *id, const bool debug_relationship_assert)
463{
464 if ((id->flag & ID_FLAG_EMBEDDED_DATA) == 0) {
465 return nullptr;
466 }
467 /* TODO: Sort this NO_MAIN or not for embedded node trees. See #86119. */
468 // BLI_assert((id->tag & ID_TAG_NO_MAIN) == 0);
469
470 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
471 if (debug_relationship_assert) {
472 BLI_assert(ntree->owner_id != nullptr);
473 BLI_assert(node_tree_from_id(ntree->owner_id) == ntree);
474 }
475
476 return &ntree->owner_id;
477}
478
479namespace forward_compat {
480
481static void write_node_socket_interface(BlendWriter *writer, const bNodeSocket *sock)
482{
483 BLO_write_struct(writer, bNodeSocket, sock);
484
485 if (sock->prop) {
486 IDP_BlendWrite(writer, sock->prop);
487 }
488
490
492}
493
494/* Construct a bNodeSocket that represents a node group socket the old way. */
496 const eNodeSocketInOut in_out,
497 const StringRef idname,
498
499 const StringRef name,
500 const StringRef identifier)
501{
502 bNodeSocketType *stype = node_socket_type_find(idname.data());
503 if (stype == nullptr) {
504 return nullptr;
505 }
506
507 bNodeSocket *sock = MEM_cnew<bNodeSocket>(__func__);
508 sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
509 STRNCPY(sock->idname, stype->idname);
510 sock->in_out = int(in_out);
511 sock->type = int(SOCK_CUSTOM); /* int type undefined by default */
512 node_socket_set_typeinfo(ntree, sock, stype);
513
514 sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
515
516 STRNCPY(sock->identifier, identifier.data());
517 STRNCPY(sock->name, name.data());
518 sock->storage = nullptr;
519 sock->flag |= SOCK_COLLAPSED;
520
521 return sock;
522}
523
524/* Include the subtype suffix for old socket idnames. */
525static StringRef get_legacy_socket_subtype_idname(StringRef idname, const void *socket_data)
526{
527 if (idname == "NodeSocketFloat") {
528 const bNodeSocketValueFloat &float_data = *static_cast<const bNodeSocketValueFloat *>(
529 socket_data);
530 switch (float_data.subtype) {
531 case PROP_UNSIGNED:
532 return "NodeSocketFloatUnsigned";
533 case PROP_PERCENTAGE:
534 return "NodeSocketFloatPercentage";
535 case PROP_FACTOR:
536 return "NodeSocketFloatFactor";
537 case PROP_ANGLE:
538 return "NodeSocketFloatAngle";
539 case PROP_TIME:
540 return "NodeSocketFloatTime";
542 return "NodeSocketFloatTimeAbsolute";
543 case PROP_DISTANCE:
544 return "NodeSocketFloatDistance";
545 case PROP_WAVELENGTH:
546 return "NodeSocketFloatWavelength";
548 return "NodeSocketFloatColorTemperature";
549 case PROP_FREQUENCY:
550 return "NodeSocketFloatFrequency";
551 }
552 }
553 if (idname == "NodeSocketInt") {
554 const bNodeSocketValueInt &int_data = *static_cast<const bNodeSocketValueInt *>(socket_data);
555 switch (int_data.subtype) {
556 case PROP_UNSIGNED:
557 return "NodeSocketIntUnsigned";
558 case PROP_PERCENTAGE:
559 return "NodeSocketIntPercentage";
560 case PROP_FACTOR:
561 return "NodeSocketIntFactor";
562 }
563 }
564 if (idname == "NodeSocketVector") {
565 const bNodeSocketValueVector &vector_data = *static_cast<const bNodeSocketValueVector *>(
566 socket_data);
567 switch (vector_data.subtype) {
568 case PROP_TRANSLATION:
569 return "NodeSocketVectorTranslation";
570 case PROP_DIRECTION:
571 return "NodeSocketVectorDirection";
572 case PROP_VELOCITY:
573 return "NodeSocketVectorVelocity";
575 return "NodeSocketVectorAcceleration";
576 case PROP_EULER:
577 return "NodeSocketVectorEuler";
578 }
579 }
580 return idname;
581}
582
591{
592 BLI_assert(BLI_listbase_is_empty(&ntree->inputs_legacy));
593 BLI_assert(BLI_listbase_is_empty(&ntree->outputs_legacy));
594
595 auto make_legacy_socket = [&](const bNodeTreeInterfaceSocket &socket,
596 eNodeSocketInOut in_out) -> bNodeSocket * {
597 bNodeSocket *iosock = make_socket(
598 ntree,
599 in_out,
601 socket.name ? socket.name : "",
602 socket.identifier);
603 if (!iosock) {
604 return nullptr;
605 }
606
607 if (socket.description) {
608 STRNCPY(iosock->description, socket.description);
609 }
611 eNodeSocketDatatype(iosock->typeinfo->type), iosock->default_value, socket.socket_data);
612 if (socket.properties) {
613 iosock->prop = IDP_CopyProperty(socket.properties);
614 }
619 iosock->attribute_domain = socket.attribute_domain;
621 return iosock;
622 };
623
624 /* Construct inputs/outputs socket lists in the node tree. */
625 ntree->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) {
626 if (const bNodeTreeInterfaceSocket *socket =
628 {
629 if (socket->flag & NODE_INTERFACE_SOCKET_INPUT) {
630 if (bNodeSocket *legacy_socket = make_legacy_socket(*socket, SOCK_IN)) {
631 BLI_addtail(&ntree->inputs_legacy, legacy_socket);
632 }
633 }
634 if (socket->flag & NODE_INTERFACE_SOCKET_OUTPUT) {
635 if (bNodeSocket *legacy_socket = make_legacy_socket(*socket, SOCK_OUT)) {
636 BLI_addtail(&ntree->outputs_legacy, legacy_socket);
637 }
638 }
639 }
640 return true;
641 });
642}
643
644static void write_legacy_sockets(BlendWriter *writer, bNodeTree *ntree)
645{
646 /* Write inputs/outputs */
647 LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs_legacy) {
648 write_node_socket_interface(writer, sock);
649 }
650 LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs_legacy) {
651 write_node_socket_interface(writer, sock);
652 }
653}
654
656{
657 if (sock->prop) {
658 IDP_FreeProperty_ex(sock->prop, false);
659 }
660
661 if (sock->default_value) {
663 }
664 if (sock->default_attribute_name) {
666 }
667 MEM_delete(sock->runtime);
668}
669
671{
672 /* Clean up temporary inputs/outputs. */
673 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, socket, &ntree->inputs_legacy) {
675 MEM_freeN(socket);
676 }
677 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, socket, &ntree->outputs_legacy) {
679 MEM_freeN(socket);
680 }
681 BLI_listbase_clear(&ntree->inputs_legacy);
682 BLI_listbase_clear(&ntree->outputs_legacy);
683}
684
685} // namespace forward_compat
686
688{
689 if (sock->default_value == nullptr) {
690 return;
691 }
692
693 switch (eNodeSocketDatatype(sock->type)) {
694 case SOCK_FLOAT:
696 break;
697 case SOCK_VECTOR:
699 break;
700 case SOCK_RGBA:
702 break;
703 case SOCK_BOOLEAN:
705 break;
706 case SOCK_INT:
708 break;
709 case SOCK_STRING:
711 break;
712 case SOCK_OBJECT:
714 break;
715 case SOCK_IMAGE:
717 break;
718 case SOCK_COLLECTION:
720 break;
721 case SOCK_TEXTURE:
723 break;
724 case SOCK_MATERIAL:
726 break;
727 case SOCK_ROTATION:
729 break;
730 case SOCK_MENU:
732 break;
733 case SOCK_MATRIX:
734 /* Matrix sockets currently have no default value. */
735 break;
736 case SOCK_CUSTOM:
737 /* Custom node sockets where default_value is defined uses custom properties for storage. */
738 break;
739 case SOCK_SHADER:
740 case SOCK_GEOMETRY:
742 break;
743 }
744}
745
746static void write_node_socket(BlendWriter *writer, const bNodeSocket *sock)
747{
748 BLO_write_struct(writer, bNodeSocket, sock);
749
750 if (sock->prop) {
751 IDP_BlendWrite(writer, sock->prop);
752 }
753
754 /* This property should only be used for group node "interface" sockets. */
755 BLI_assert(sock->default_attribute_name == nullptr);
756
758}
759
761{
762 BKE_id_blend_write(writer, &ntree->id);
763 BLO_write_string(writer, ntree->description);
764
765 for (bNode *node : ntree->all_nodes()) {
766 if (ntree->type == NTREE_SHADER && node->type == SH_NODE_BSDF_HAIR_PRINCIPLED) {
767 /* For Principeld Hair BSDF, also write to `node->custom1` for forward compatibility, because
768 * prior to 4.0 `node->custom1` was used for color parametrization instead of
769 * `node->storage->parametrization`. */
770 NodeShaderHairPrincipled *data = static_cast<NodeShaderHairPrincipled *>(node->storage);
771 node->custom1 = data->parametrization;
772 }
773
774 BLO_write_struct(writer, bNode, node);
775
776 if (node->prop) {
777 IDP_BlendWrite(writer, node->prop);
778 }
779
780 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
781 write_node_socket(writer, sock);
782 }
783 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
784 write_node_socket(writer, sock);
785 }
787 writer, bNodePanelState, node->num_panel_states, node->panel_states_array);
788
789 if (node->storage) {
790 if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY) &&
792 {
793 BKE_curvemapping_blend_write(writer, static_cast<const CurveMapping *>(node->storage));
794 }
795 else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) {
796 NodeShaderScript *nss = static_cast<NodeShaderScript *>(node->storage);
797 if (nss->bytecode) {
798 BLO_write_string(writer, nss->bytecode);
799 }
800 BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
801 }
802 else if ((ntree->type == NTREE_COMPOSIT) && ELEM(node->type,
803 CMP_NODE_TIME,
804 CMP_NODE_CURVE_VEC,
805 CMP_NODE_CURVE_RGB,
806 CMP_NODE_HUECORRECT))
807 {
808 BKE_curvemapping_blend_write(writer, static_cast<const CurveMapping *>(node->storage));
809 }
810 else if ((ntree->type == NTREE_TEXTURE) &&
811 ELEM(node->type, TEX_NODE_CURVE_RGB, TEX_NODE_CURVE_TIME))
812 {
813 BKE_curvemapping_blend_write(writer, static_cast<const CurveMapping *>(node->storage));
814 }
815 else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) {
816 /* pass */
817 }
818 else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) {
819 /* Simple forward compatibility for fix for #50736.
820 * Not ideal (there is no ideal solution here), but should do for now. */
821 NodeGlare *ndg = static_cast<NodeGlare *>(node->storage);
822 /* Not in undo case. */
823 if (!BLO_write_is_undo(writer)) {
824 switch (ndg->type) {
826 ndg->angle = ndg->streaks;
827 break;
829 ndg->angle = ndg->star_45;
830 break;
831 default:
832 break;
833 }
834 }
835 BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
836 }
837 else if ((ntree->type == NTREE_COMPOSIT) &&
838 ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY))
839 {
840 NodeCryptomatte *nc = static_cast<NodeCryptomatte *>(node->storage);
841 BLO_write_string(writer, nc->matte_id);
842 LISTBASE_FOREACH (CryptomatteEntry *, entry, &nc->entries) {
843 BLO_write_struct(writer, CryptomatteEntry, entry);
844 }
845 BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
846 }
847 else if (node->type == FN_NODE_INPUT_STRING) {
848 NodeInputString *storage = static_cast<NodeInputString *>(node->storage);
849 if (storage->string) {
850 BLO_write_string(writer, storage->string);
851 }
852 BLO_write_struct_by_name(writer, node->typeinfo->storagename, storage);
853 }
854 else if (node->type == GEO_NODE_CAPTURE_ATTRIBUTE) {
855 auto &storage = *static_cast<NodeGeometryAttributeCapture *>(node->storage);
856 /* Improve forward compatibility. */
858 for (const NodeGeometryAttributeCaptureItem &item :
859 Span{storage.capture_items, storage.capture_items_num})
860 {
861 if (item.identifier == 0) {
862 /* The sockets of this item have the same identifiers that have been used by older
863 * Blender versions before the node supported capturing multiple attributes. */
864 storage.data_type_legacy = item.data_type;
865 break;
866 }
867 }
868 BLO_write_struct(writer, NodeGeometryAttributeCapture, node->storage);
869 nodes::CaptureAttributeItemsAccessor::blend_write(writer, *node);
870 }
871 else if (node->typeinfo != &NodeTypeUndefined) {
872 BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
873 }
874 }
875
876 if (node->type == CMP_NODE_OUTPUT_FILE) {
877 /* Inputs have their own storage data. */
878 NodeImageMultiFile *nimf = (NodeImageMultiFile *)node->storage;
879 BKE_image_format_blend_write(writer, &nimf->format);
880
881 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
882 NodeImageMultiFileSocket *sockdata = static_cast<NodeImageMultiFileSocket *>(
883 sock->storage);
885 BKE_image_format_blend_write(writer, &sockdata->format);
886 }
887 }
888 if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
889 /* Write extra socket info. */
890 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
891 BLO_write_struct(writer, NodeImageLayer, sock->storage);
892 }
893 }
894 if (node->type == GEO_NODE_SIMULATION_OUTPUT) {
895 nodes::SimulationItemsAccessor::blend_write(writer, *node);
896 }
897 if (node->type == GEO_NODE_REPEAT_OUTPUT) {
898 nodes::RepeatItemsAccessor::blend_write(writer, *node);
899 }
900 if (node->type == GEO_NODE_INDEX_SWITCH) {
901 nodes::IndexSwitchItemsAccessor::blend_write(writer, *node);
902 }
903 if (node->type == GEO_NODE_BAKE) {
904 nodes::BakeItemsAccessor::blend_write(writer, *node);
905 }
906 if (node->type == GEO_NODE_MENU_SWITCH) {
907 nodes::MenuSwitchItemsAccessor::blend_write(writer, *node);
908 }
909 if (node->type == GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT) {
910 nodes::ForeachGeometryElementInputItemsAccessor::blend_write(writer, *node);
911 nodes::ForeachGeometryElementGenerationItemsAccessor::blend_write(writer, *node);
912 nodes::ForeachGeometryElementMainItemsAccessor::blend_write(writer, *node);
913 }
914 }
915
916 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
917 BLO_write_struct(writer, bNodeLink, link);
918 }
919
920 ntree->tree_interface.write(writer);
921 if (!BLO_write_is_undo(writer)) {
922 forward_compat::write_legacy_sockets(writer, ntree);
923 }
924
926
929
930 BKE_previewimg_blend_write(writer, ntree->preview);
931}
932
933static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_address)
934{
935 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
936
937 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
938 ntree->typeinfo = nullptr;
939 ntree->runtime->execdata = nullptr;
940
941 if (!BLO_write_is_undo(writer)) {
942 /* Generate legacy inputs/outputs socket ListBase for forward compatibility.
943 * NOTE: this has to happen before writing the ntree struct itself so that the ListBase
944 * first/last pointers are valid. */
945 forward_compat::construct_interface_as_legacy_sockets(ntree);
946 }
947
948 BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
949
950 node_tree_blend_write(writer, ntree);
951
952 if (!BLO_write_is_undo(writer)) {
953 forward_compat::cleanup_legacy_sockets(ntree);
954 }
955}
956
962static bool is_node_socket_supported(const bNodeSocket *sock)
963{
964 switch (eNodeSocketDatatype(sock->type)) {
965 case SOCK_FLOAT:
966 case SOCK_VECTOR:
967 case SOCK_RGBA:
968 case SOCK_BOOLEAN:
969 case SOCK_INT:
970 case SOCK_STRING:
971 case SOCK_CUSTOM:
972 case SOCK_SHADER:
973 case SOCK_GEOMETRY:
974 case SOCK_OBJECT:
975 case SOCK_IMAGE:
976 case SOCK_COLLECTION:
977 case SOCK_TEXTURE:
978 case SOCK_MATERIAL:
979 case SOCK_ROTATION:
980 case SOCK_MENU:
981 case SOCK_MATRIX:
982 return true;
983 }
984 return false;
985}
986
988{
989 BLO_read_struct(reader, IDProperty, &sock->prop);
990 IDP_BlendDataRead(reader, &sock->prop);
991
992 BLO_read_struct(reader, bNodeLink, &sock->link);
993 sock->typeinfo = nullptr;
994 /* FIXME Avoid using low-level untyped read function here. Although this seems to be only for
995 * versioning code now? Does not seem to be written anymore at least. */
996 BLO_read_data_address(reader, &sock->storage);
997 /* FIXME Avoid using low-level untyped read function here. Most likely by just mirroring
998 * #write_node_socket_default_value ? */
999 BLO_read_data_address(reader, &sock->default_value);
1001 sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
1002
1003 switch (eNodeSocketDatatype(sock->type)) {
1004 case SOCK_MENU: {
1005 bNodeSocketValueMenu &default_value = *sock->default_value_typed<bNodeSocketValueMenu>();
1006 /* Clear runtime data. */
1007 default_value.enum_items = nullptr;
1008 default_value.runtime_flag = 0;
1009 break;
1010 }
1011 default:
1012 break;
1013 }
1014}
1015
1016static void remove_unsupported_sockets(ListBase *sockets, ListBase *links)
1017{
1018 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, sockets) {
1019 if (is_node_socket_supported(sock)) {
1020 continue;
1021 }
1022
1023 /* First remove any link pointing to the socket. */
1024 if (links) {
1025 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, links) {
1026 if (link->fromsock == sock || link->tosock == sock) {
1027 BLI_remlink(links, link);
1028 if (link->tosock) {
1029 link->tosock->link = nullptr;
1030 }
1031 MEM_freeN(link);
1032 }
1033 }
1034 }
1035
1036 BLI_remlink(sockets, sock);
1037 MEM_delete(sock->runtime);
1038 MEM_freeN(sock);
1039 }
1040}
1041
1043{
1044 /* Special case for this pointer, do not rely on regular `lib_link` process here. Avoids needs
1045 * for do_versioning, and ensures coherence of data in any case.
1046 *
1047 * NOTE: Old versions are very often 'broken' here, just fix it silently in these cases.
1048 */
1049 if (BLO_read_fileversion_get(reader) > 300) {
1050 BLI_assert((ntree->id.flag & ID_FLAG_EMBEDDED_DATA) != 0 || owner_id == nullptr);
1051 }
1052 BLI_assert(owner_id == nullptr || owner_id->lib == ntree->id.lib);
1053 if (owner_id != nullptr && (ntree->id.flag & ID_FLAG_EMBEDDED_DATA) == 0) {
1054 /* This is unfortunate, but currently a lot of existing files (including startup ones) have
1055 * missing `ID_FLAG_EMBEDDED_DATA` flag.
1056 *
1057 * NOTE: Using do_version is not a solution here, since this code will be called before any
1058 * do_version takes place. Keeping it here also ensures future (or unknown existing) similar
1059 * bugs won't go easily unnoticed. */
1060 if (BLO_read_fileversion_get(reader) > 300) {
1061 CLOG_WARN(&LOG,
1062 "Fixing root node tree '%s' owned by '%s' missing EMBEDDED tag, please consider "
1063 "re-saving your (startup) file",
1064 ntree->id.name,
1065 owner_id->name);
1066 }
1067 ntree->id.flag |= ID_FLAG_EMBEDDED_DATA;
1068 }
1069 ntree->owner_id = owner_id;
1070
1071 /* NOTE: writing and reading goes in sync, for speed. */
1072 ntree->typeinfo = nullptr;
1073
1074 ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
1076
1077 BLO_read_string(reader, &ntree->description);
1078
1079 BLO_read_struct_list(reader, bNode, &ntree->nodes);
1080 int i;
1081 LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, i) {
1082 node->runtime = MEM_new<bNodeRuntime>(__func__);
1083 node->typeinfo = nullptr;
1084 node->runtime->index_in_tree = i;
1085
1086 /* Create the `nodes_by_id` cache eagerly so it can be expected to be valid. Because
1087 * we create it here we also have to check for zero identifiers from previous versions. */
1088 if (node->identifier == 0 || ntree->runtime->nodes_by_id.contains_as(node->identifier)) {
1089 node_unique_id(ntree, node);
1090 }
1091 else {
1092 ntree->runtime->nodes_by_id.add_new(node);
1093 }
1094
1095 BLO_read_struct_list(reader, bNodeSocket, &node->inputs);
1096 BLO_read_struct_list(reader, bNodeSocket, &node->outputs);
1098 reader, bNodePanelState, node->num_panel_states, &node->panel_states_array);
1099
1100 BLO_read_struct(reader, IDProperty, &node->prop);
1101 IDP_BlendDataRead(reader, &node->prop);
1102
1103 if (node->type == CMP_NODE_MOVIEDISTORTION) {
1104 /* Do nothing, this is runtime cache and hence handled by generic code using
1105 * `IDTypeInfo.foreach_cache` callback. */
1106 }
1107 else {
1108 /* FIXME Avoid using low-level untyped read function here. Most likely by just mirroring
1109 * the matching logic in #node_tree_blend_write ? */
1110 BLO_read_data_address(reader, &node->storage);
1111 }
1112
1113 if (node->storage) {
1114 switch (node->type) {
1115 case SH_NODE_CURVE_VEC:
1116 case SH_NODE_CURVE_RGB:
1118 case CMP_NODE_TIME:
1119 case CMP_NODE_CURVE_VEC:
1120 case CMP_NODE_CURVE_RGB:
1122 case TEX_NODE_CURVE_RGB:
1123 case TEX_NODE_CURVE_TIME: {
1124 BKE_curvemapping_blend_read(reader, static_cast<CurveMapping *>(node->storage));
1125 break;
1126 }
1127 case SH_NODE_SCRIPT: {
1128 NodeShaderScript *nss = static_cast<NodeShaderScript *>(node->storage);
1129 BLO_read_string(reader, &nss->bytecode);
1130 break;
1131 }
1133 NodeShaderTexPointDensity *npd = static_cast<NodeShaderTexPointDensity *>(node->storage);
1134 npd->pd = dna::shallow_zero_initialize();
1135 break;
1136 }
1137 case SH_NODE_TEX_IMAGE: {
1138 NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
1139 tex->iuser.scene = nullptr;
1140 break;
1141 }
1143 NodeTexEnvironment *tex = static_cast<NodeTexEnvironment *>(node->storage);
1144 tex->iuser.scene = nullptr;
1145 break;
1146 }
1147 case CMP_NODE_IMAGE:
1148 case CMP_NODE_R_LAYERS:
1149 case CMP_NODE_VIEWER: {
1150 ImageUser *iuser = static_cast<ImageUser *>(node->storage);
1151 iuser->scene = nullptr;
1152 break;
1153 }
1155 case CMP_NODE_CRYPTOMATTE: {
1156 NodeCryptomatte *nc = static_cast<NodeCryptomatte *>(node->storage);
1157 BLO_read_string(reader, &nc->matte_id);
1160 break;
1161 }
1162 case TEX_NODE_IMAGE: {
1163 ImageUser *iuser = static_cast<ImageUser *>(node->storage);
1164 iuser->scene = nullptr;
1165 break;
1166 }
1167 case CMP_NODE_OUTPUT_FILE: {
1168 NodeImageMultiFile *nimf = static_cast<NodeImageMultiFile *>(node->storage);
1170 break;
1171 }
1172 case FN_NODE_INPUT_STRING: {
1173 NodeInputString *storage = static_cast<NodeInputString *>(node->storage);
1174 BLO_read_string(reader, &storage->string);
1175 break;
1176 }
1178 nodes::SimulationItemsAccessor::blend_read_data(reader, *node);
1179 break;
1180 }
1182 nodes::RepeatItemsAccessor::blend_read_data(reader, *node);
1183 break;
1184 }
1186 nodes::ForeachGeometryElementInputItemsAccessor::blend_read_data(reader, *node);
1187 nodes::ForeachGeometryElementMainItemsAccessor::blend_read_data(reader, *node);
1188 nodes::ForeachGeometryElementGenerationItemsAccessor::blend_read_data(reader, *node);
1189 break;
1190 }
1191 case GEO_NODE_INDEX_SWITCH: {
1192 nodes::IndexSwitchItemsAccessor::blend_read_data(reader, *node);
1193 break;
1194 }
1195 case GEO_NODE_BAKE: {
1196 nodes::BakeItemsAccessor::blend_read_data(reader, *node);
1197 break;
1198 }
1199 case GEO_NODE_MENU_SWITCH: {
1200 nodes::MenuSwitchItemsAccessor::blend_read_data(reader, *node);
1201 break;
1202 }
1204 nodes::CaptureAttributeItemsAccessor::blend_read_data(reader, *node);
1205 break;
1206 }
1207
1208 default:
1209 break;
1210 }
1211 }
1212 }
1213 BLO_read_struct_list(reader, bNodeLink, &ntree->links);
1214 BLI_assert(ntree->all_nodes().size() == BLI_listbase_count(&ntree->nodes));
1215
1216 /* and we connect the rest */
1217 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1218 BLO_read_struct(reader, bNode, &node->parent);
1219
1220 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
1221 direct_link_node_socket(reader, sock);
1222 }
1223 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
1224 direct_link_node_socket(reader, sock);
1225 }
1226
1227 /* Socket storage. */
1228 if (node->type == CMP_NODE_OUTPUT_FILE) {
1229 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1230 NodeImageMultiFileSocket *sockdata = static_cast<NodeImageMultiFileSocket *>(
1231 sock->storage);
1232 BKE_image_format_blend_read_data(reader, &sockdata->format);
1233 }
1234 }
1235 }
1236
1237 /* Read legacy interface socket lists for versioning. */
1238 BLO_read_struct_list(reader, bNodeSocket, &ntree->inputs_legacy);
1239 BLO_read_struct_list(reader, bNodeSocket, &ntree->outputs_legacy);
1240 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->inputs_legacy) {
1241 direct_link_node_socket(reader, sock);
1242 }
1243 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->outputs_legacy) {
1244 direct_link_node_socket(reader, sock);
1245 }
1246
1247 ntree->tree_interface.read_data(reader);
1248
1249 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
1250 BLO_read_struct(reader, bNode, &link->fromnode);
1251 BLO_read_struct(reader, bNode, &link->tonode);
1252 BLO_read_struct(reader, bNodeSocket, &link->fromsock);
1253 BLO_read_struct(reader, bNodeSocket, &link->tosock);
1254 }
1255
1256 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1257 remove_unsupported_sockets(&node->inputs, &ntree->links);
1258 remove_unsupported_sockets(&node->outputs, &ntree->links);
1259 }
1260 remove_unsupported_sockets(&ntree->inputs_legacy, nullptr);
1261 remove_unsupported_sockets(&ntree->outputs_legacy, nullptr);
1262
1265 reader, bNestedNodeRef, ntree->nested_node_refs_num, &ntree->nested_node_refs);
1266
1267 /* TODO: should be dealt by new generic cache handling of IDs... */
1268 ntree->previews = nullptr;
1269
1270 BLO_read_struct(reader, PreviewImage, &ntree->preview);
1271 BKE_previewimg_blend_read(reader, ntree->preview);
1272
1273 /* type verification is in lib-link */
1274}
1275
1277{
1278 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
1279 node_tree_blend_read_data(reader, nullptr, ntree);
1280}
1281
1283{
1284 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
1285
1286 /* Set `node->typeinfo` pointers. This is done in lib linking, after the
1287 * first versioning that can change types still without functions that
1288 * update the `typeinfo` pointers. Versioning after lib linking needs
1289 * these top be valid. */
1290 node_tree_set_type(nullptr, ntree);
1291
1292 /* For nodes with static socket layout, add/remove sockets as needed
1293 * to match the static layout. */
1294 if (!BLO_read_lib_is_undo(reader)) {
1295 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
1296 /* Don't update node groups here because they may depend on other node groups which are not
1297 * fully versioned yet and don't have `typeinfo` pointers set. */
1298 if (!node->is_group()) {
1299 node_verify_sockets(ntree, node, false);
1300 }
1301 }
1302 }
1303}
1304
1306{
1307 AssetMetaData *asset_data = node_tree.id.asset_data;
1308 if (!asset_data) {
1309 return;
1310 }
1311
1312 BKE_asset_metadata_idprop_ensure(asset_data, idprop::create("type", node_tree.type).release());
1313 auto inputs = idprop::create_group("inputs");
1314 auto outputs = idprop::create_group("outputs");
1315 node_tree.ensure_interface_cache();
1316 for (const bNodeTreeInterfaceSocket *socket : node_tree.interface_inputs()) {
1317 auto property = idprop::create(socket->name ? socket->name : "", socket->socket_type);
1318 IDP_AddToGroup(inputs.get(), property.release());
1319 }
1320 for (const bNodeTreeInterfaceSocket *socket : node_tree.interface_outputs()) {
1321 auto property = idprop::create(socket->name ? socket->name : "", socket->socket_type);
1322 IDP_AddToGroup(outputs.get(), property.release());
1323 }
1324 BKE_asset_metadata_idprop_ensure(asset_data, inputs.release());
1325 BKE_asset_metadata_idprop_ensure(asset_data, outputs.release());
1326 if (node_tree.geometry_node_asset_traits) {
1327 auto property = idprop::create("geometry_node_asset_traits_flag",
1328 node_tree.geometry_node_asset_traits->flag);
1329 BKE_asset_metadata_idprop_ensure(asset_data, property.release());
1330 }
1331}
1332
1333static void node_tree_asset_pre_save(void *asset_ptr, AssetMetaData * /*asset_data*/)
1334{
1335 bNodeTree &ntree = *static_cast<bNodeTree *>(asset_ptr);
1337}
1338
1339static void node_tree_asset_on_mark_asset(void *asset_ptr, AssetMetaData *asset_data)
1340{
1341 bNodeTree &ntree = *static_cast<bNodeTree *>(asset_ptr);
1343
1344 /* Copy node tree description to asset description so that the user does not have to write it
1345 * again. */
1346 if (!asset_data->description) {
1347 asset_data->description = BLI_strdup_null(ntree.description);
1348 }
1349}
1350
1351static void node_tree_asset_on_clear_asset(void *asset_ptr, AssetMetaData *asset_data)
1352{
1353 bNodeTree &ntree = *static_cast<bNodeTree *>(asset_ptr);
1354
1355 /* Copy asset description to node tree description so that it is not lost when the asset data is
1356 * removed. */
1357 if (asset_data->description) {
1359 ntree.description = BLI_strdup_null(asset_data->description);
1360 }
1361}
1362
1363} // namespace blender::bke
1364
1370
1372 /*id_code*/ ID_NT,
1373 /*id_filter*/ FILTER_ID_NT,
1374 /* IDProps of nodes, and #bNode.id, can use any type of ID. */
1375 /*dependencies_id_types*/ FILTER_ID_ALL,
1376 /*main_listbase_index*/ INDEX_ID_NT,
1377 /*struct_size*/ sizeof(bNodeTree),
1378 /*name*/ "NodeTree",
1379 /*name_plural*/ N_("node_groups"),
1380 /*translation_context*/ BLT_I18NCONTEXT_ID_NODETREE,
1382 /*asset_type_info*/ &AssetType_NT,
1383
1384 /*init_data*/ blender::bke::ntree_init_data,
1385 /*copy_data*/ blender::bke::ntree_copy_data,
1386 /*free_data*/ blender::bke::ntree_free_data,
1387 /*make_local*/ nullptr,
1388 /*foreach_id*/ blender::bke::node_foreach_id,
1389 /*foreach_cache*/ blender::bke::node_foreach_cache,
1390 /*foreach_path*/ blender::bke::node_foreach_path,
1391 /*owner_pointer_get*/ blender::bke::node_owner_pointer_get,
1392
1393 /*blend_write*/ blender::bke::ntree_blend_write,
1394 /*blend_read_data*/ blender::bke::ntree_blend_read_data,
1395 /*blend_read_after_liblink*/ blender::bke::ntree_blend_read_after_liblink,
1396
1397 /*blend_read_undo_preserve*/ nullptr,
1398
1399 /*lib_override_apply_post*/ nullptr,
1400};
1401
1402namespace blender::bke {
1403
1404static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
1405{
1406 if (ntype->declare) {
1407 node_verify_sockets(ntree, node, true);
1408 return;
1409 }
1410 bNodeSocketTemplate *sockdef;
1411
1412 if (ntype->inputs) {
1413 sockdef = ntype->inputs;
1414 while (sockdef->type != -1) {
1415 node_add_socket_from_template(ntree, node, sockdef, SOCK_IN);
1416 sockdef++;
1417 }
1418 }
1419 if (ntype->outputs) {
1420 sockdef = ntype->outputs;
1421 while (sockdef->type != -1) {
1422 node_add_socket_from_template(ntree, node, sockdef, SOCK_OUT);
1423 sockdef++;
1424 }
1425 }
1426}
1427
1428/* NOTE: This function is called to initialize node data based on the type.
1429 * The #bNodeType may not be registered at creation time of the node,
1430 * so this can be delayed until the node type gets registered.
1431 */
1432static void node_init(const bContext *C, bNodeTree *ntree, bNode *node)
1433{
1434 BLI_assert(ntree != nullptr);
1435 bNodeType *ntype = node->typeinfo;
1436 if (ntype == &NodeTypeUndefined) {
1437 return;
1438 }
1439
1440 /* only do this once */
1441 if (node->flag & NODE_INIT) {
1442 return;
1443 }
1444
1445 node->flag = NODE_SELECT | NODE_OPTIONS | ntype->flag;
1446 node->width = ntype->width;
1447 node->height = ntype->height;
1448 node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
1449 /* initialize the node name with the node label.
1450 * NOTE: do this after the initfunc so nodes get their data set which may be used in naming
1451 * (node groups for example) */
1452 /* XXX Do not use nodeLabel() here, it returns translated content for UI,
1453 * which should *only* be used in UI, *never* in data...
1454 * Data have their own translation option!
1455 * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
1456 * than adding "do_translate" flags to this func (and labelfunc() as well). */
1457 STRNCPY_UTF8(node->name, DATA_(ntype->ui_name));
1458 node_unique_name(ntree, node);
1459
1460 /* Generally sockets should be added after the initialization, because the set of sockets might
1461 * depend on node properties. */
1462 const bool add_sockets_before_init = node->type == CMP_NODE_R_LAYERS;
1463 if (add_sockets_before_init) {
1464 node_add_sockets_from_type(ntree, node, ntype);
1465 }
1466
1467 if (ntype->initfunc != nullptr) {
1468 ntype->initfunc(ntree, node);
1469 }
1470
1471 if (ntree->typeinfo && ntree->typeinfo->node_add_init) {
1472 ntree->typeinfo->node_add_init(ntree, node);
1473 }
1474
1475 if (!add_sockets_before_init) {
1476 node_add_sockets_from_type(ntree, node, ntype);
1477 }
1478
1479 if (node->id) {
1480 id_us_plus(node->id);
1481 }
1482
1483 if (ntype->initfunc_api) {
1484 PointerRNA ptr = RNA_pointer_create(&ntree->id, &RNA_Node, node);
1485
1486 /* XXX WARNING: context can be nullptr in case nodes are added in do_versions.
1487 * Delayed init is not supported for nodes with context-based `initfunc_api` at the moment. */
1488 BLI_assert(C != nullptr);
1489 ntype->initfunc_api(C, &ptr);
1490 }
1491
1492 node->flag |= NODE_INIT;
1493}
1494
1495static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
1496{
1497 if (typeinfo) {
1498 ntree->typeinfo = typeinfo;
1499 }
1500 else {
1502 }
1503
1504 /* Deprecated integer type. */
1505 ntree->type = ntree->typeinfo->type;
1507}
1508
1509static void node_set_typeinfo(const bContext *C,
1510 bNodeTree *ntree,
1511 bNode *node,
1512 bNodeType *typeinfo)
1513{
1514 /* for nodes saved in older versions storage can get lost, make undefined then */
1515 if (node->flag & NODE_INIT) {
1516 if (typeinfo && typeinfo->storagename[0] && !node->storage) {
1517 typeinfo = nullptr;
1518 }
1519 }
1520
1521 if (typeinfo) {
1522 node->typeinfo = typeinfo;
1523
1524 /* deprecated integer type */
1525 node->type = typeinfo->type;
1526
1527 /* initialize the node if necessary */
1528 node_init(C, ntree, node);
1529 }
1530 else {
1531 node->typeinfo = &NodeTypeUndefined;
1532 }
1533}
1534
1535/* WARNING: default_value must either be null or match the typeinfo at this point.
1536 * This function is called both for initializing new sockets and after loading files.
1537 */
1539 bNodeSocket *sock,
1540 bNodeSocketType *typeinfo)
1541{
1542 if (typeinfo) {
1543 sock->typeinfo = typeinfo;
1544
1545 /* deprecated integer type */
1546 sock->type = typeinfo->type;
1547
1548 if (sock->default_value == nullptr) {
1549 /* initialize the default_value pointer used by standard socket types */
1551 }
1552 }
1553 else {
1555 }
1557}
1558
1559/* Set specific typeinfo pointers in all node trees on register/unregister */
1560static void update_typeinfo(Main *bmain,
1561 const bContext *C,
1562 bNodeTreeType *treetype,
1563 bNodeType *nodetype,
1564 bNodeSocketType *socktype,
1565 const bool unregister)
1566{
1567 if (!bmain) {
1568 return;
1569 }
1570
1571 FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
1572 if (treetype && STREQ(ntree->idname, treetype->idname)) {
1573 ntree_set_typeinfo(ntree, unregister ? nullptr : treetype);
1574 }
1575
1576 /* initialize nodes */
1577 for (bNode *node : ntree->all_nodes()) {
1578 if (nodetype && STREQ(node->idname, nodetype->idname)) {
1579 node_set_typeinfo(C, ntree, node, unregister ? nullptr : nodetype);
1580 }
1581
1582 /* initialize node sockets */
1583 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1584 if (socktype && STREQ(sock->idname, socktype->idname)) {
1585 node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
1586 }
1587 }
1588 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1589 if (socktype && STREQ(sock->idname, socktype->idname)) {
1590 node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
1591 }
1592 }
1593 }
1594 }
1596}
1597
1599{
1601
1602 for (bNode *node : ntree->all_nodes()) {
1603 /* Set socket typeinfo first because node initialization may rely on socket typeinfo for
1604 * generating declarations. */
1605 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1606 node_socket_set_typeinfo(ntree, sock, node_socket_type_find(sock->idname));
1607 }
1608 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1609 node_socket_set_typeinfo(ntree, sock, node_socket_type_find(sock->idname));
1610 }
1611
1612 node_set_typeinfo(C, ntree, node, node_type_find(node->idname));
1613 }
1614}
1615
1616static GHash *nodetreetypes_hash = nullptr;
1617static GHash *nodetypes_hash = nullptr;
1618static GHash *nodetypes_alias_hash = nullptr;
1619static GHash *nodesockettypes_hash = nullptr;
1620
1622{
1623 if (idname[0]) {
1624 bNodeTreeType *nt = static_cast<bNodeTreeType *>(BLI_ghash_lookup(nodetreetypes_hash, idname));
1625 if (nt) {
1626 return nt;
1627 }
1628 }
1629
1630 return nullptr;
1631}
1632
1634{
1636 /* XXX pass Main to register function? */
1637 /* Probably not. It is pretty much expected we want to update G_MAIN here I think -
1638 * or we'd want to update *all* active Mains, which we cannot do anyway currently. */
1639 update_typeinfo(G_MAIN, nullptr, nt, nullptr, nullptr, false);
1640}
1641
1642static void ntree_free_type(void *treetype_v)
1643{
1644 bNodeTreeType *treetype = static_cast<bNodeTreeType *>(treetype_v);
1645 /* XXX pass Main to unregister function? */
1646 /* Probably not. It is pretty much expected we want to update G_MAIN here I think -
1647 * or we'd want to update *all* active Mains, which we cannot do anyway currently. */
1648 update_typeinfo(G_MAIN, nullptr, treetype, nullptr, nullptr, true);
1649 MEM_freeN(treetype);
1650}
1651
1656
1658{
1659 return (ntree->typeinfo != &NodeTreeTypeUndefined);
1660}
1661
1666
1667bNodeType *node_type_find(const char *idname)
1668{
1669 if (idname[0]) {
1670 bNodeType *nt = static_cast<bNodeType *>(BLI_ghash_lookup(nodetypes_hash, idname));
1671 if (nt) {
1672 return nt;
1673 }
1674 }
1675
1676 return nullptr;
1677}
1678
1679const char *node_type_find_alias(const char *alias)
1680{
1681 if (alias[0]) {
1682 const char *idname = static_cast<const char *>(BLI_ghash_lookup(nodetypes_alias_hash, alias));
1683 if (idname) {
1684 return idname;
1685 }
1686 }
1687
1688 return alias;
1689}
1690
1691static void node_free_type(void *nodetype_v)
1692{
1693 bNodeType *nodetype = static_cast<bNodeType *>(nodetype_v);
1694 /* XXX pass Main to unregister function? */
1695 /* Probably not. It is pretty much expected we want to update G_MAIN here I think -
1696 * or we'd want to update *all* active Mains, which we cannot do anyway currently. */
1697 update_typeinfo(G_MAIN, nullptr, nullptr, nodetype, nullptr, true);
1698
1699 delete nodetype->static_declaration;
1700 nodetype->static_declaration = nullptr;
1701
1702 /* Can be null when the type is not dynamically allocated. */
1703 if (nodetype->free_self) {
1704 nodetype->free_self(nodetype);
1705 }
1706}
1707
1709{
1710 /* debug only: basic verification of registered types */
1711 BLI_assert(nt->idname[0] != '\0');
1712 BLI_assert(nt->poll != nullptr);
1713
1714 if (nt->declare) {
1716 nodes::build_node_declaration(*nt, *nt->static_declaration, nullptr, nullptr);
1717 }
1718
1720 /* XXX pass Main to register function? */
1721 /* Probably not. It is pretty much expected we want to update G_MAIN here I think -
1722 * or we'd want to update *all* active Mains, which we cannot do anyway currently. */
1723 update_typeinfo(G_MAIN, nullptr, nullptr, nt, nullptr, false);
1724}
1725
1730
1731void node_register_alias(bNodeType *nt, const char *alias)
1732{
1734}
1735
1737{
1738 if (node->typeinfo == &NodeTypeUndefined) {
1739 return true;
1740 }
1741
1742 if (node->is_group()) {
1743 const ID *group_tree = node->id;
1744 if (group_tree == nullptr) {
1745 return false;
1746 }
1747 if (!ID_IS_LINKED(group_tree)) {
1748 return false;
1749 }
1750 if ((group_tree->tag & ID_TAG_MISSING) == 0) {
1751 return false;
1752 }
1753 return true;
1754 }
1755 return false;
1756}
1757
1762
1764{
1765 if (idname && idname[0]) {
1766 bNodeSocketType *st = static_cast<bNodeSocketType *>(
1768 if (st) {
1769 return st;
1770 }
1771 }
1772
1773 return nullptr;
1774}
1775
1776static void node_free_socket_type(void *socktype_v)
1777{
1778 bNodeSocketType *socktype = static_cast<bNodeSocketType *>(socktype_v);
1779 /* XXX pass Main to unregister function? */
1780 /* Probably not. It is pretty much expected we want to update G_MAIN here I think -
1781 * or we'd want to update *all* active Mains, which we cannot do anyway currently. */
1782 update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, socktype, true);
1783
1784 socktype->free_self(socktype);
1785}
1786
1788{
1790 /* XXX pass Main to register function? */
1791 /* Probably not. It is pretty much expected we want to update G_MAIN here I think -
1792 * or we'd want to update *all* active Mains, which we cannot do anyway currently. */
1793 update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, st, false);
1794}
1795
1800
1802{
1803 return (sock->typeinfo != &NodeSocketTypeUndefined);
1804}
1805
1810
1812{
1813 /* Use socket type name as a fallback if label is undefined. */
1814 if (stype->label[0] == '\0') {
1815 return RNA_struct_ui_name(stype->ext_socket.srna);
1816 }
1817 return stype->label;
1818}
1819
1820const char *node_socket_sub_type_label(int subtype)
1821{
1822 const char *name;
1823 if (RNA_enum_name(rna_enum_property_subtype_items, subtype, &name)) {
1824 return name;
1825 }
1826 return "";
1827}
1828
1830 const eNodeSocketInOut in_out,
1831 const StringRef identifier)
1832{
1833 const ListBase *sockets = (in_out == SOCK_IN) ? &node->inputs : &node->outputs;
1834 LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
1835 if (sock->identifier == identifier) {
1836 return sock;
1837 }
1838 }
1839 return nullptr;
1840}
1841
1843 const eNodeSocketInOut in_out,
1844 const StringRef identifier)
1845{
1846 /* Reuse the implementation of the mutable accessor. */
1847 return node_find_socket(const_cast<bNode *>(node), in_out, identifier);
1848}
1849
1851 const eNodeSocketInOut in_out,
1852 const StringRef name)
1853{
1854 ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs;
1855 LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
1856 if (socket->is_available() && socket->name == name) {
1857 return socket;
1858 }
1859 }
1860 return nullptr;
1861}
1862
1864{
1865 return node_find_enabled_socket(node, SOCK_IN, name);
1866}
1867
1869{
1870 return node_find_enabled_socket(node, SOCK_OUT, name);
1871}
1872
1873static bool unique_identifier_check(void *arg, const char *identifier)
1874{
1875 const ListBase *lb = static_cast<const ListBase *>(arg);
1876 LISTBASE_FOREACH (bNodeSocket *, sock, lb) {
1877 if (STREQ(sock->identifier, identifier)) {
1878 return true;
1879 }
1880 }
1881 return false;
1882}
1883
1885 bNode * /*node*/,
1886 const int in_out,
1887 ListBase *lb,
1888 const char *idname,
1889 const char *identifier,
1890 const char *name)
1891{
1892 char auto_identifier[MAX_NAME];
1893
1894 if (identifier && identifier[0] != '\0') {
1895 /* use explicit identifier */
1896 STRNCPY(auto_identifier, identifier);
1897 }
1898 else {
1899 /* if no explicit identifier is given, assign a unique identifier based on the name */
1900 STRNCPY(auto_identifier, name);
1901 }
1902 /* Make the identifier unique. */
1904 unique_identifier_check, lb, "socket", '_', auto_identifier, sizeof(auto_identifier));
1905
1906 bNodeSocket *sock = MEM_cnew<bNodeSocket>("sock");
1907 sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
1908 sock->in_out = in_out;
1909
1910 STRNCPY(sock->identifier, auto_identifier);
1911 sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
1912
1913 STRNCPY(sock->name, name);
1914 sock->storage = nullptr;
1915 sock->flag |= SOCK_COLLAPSED;
1916 sock->type = SOCK_CUSTOM; /* int type undefined by default */
1917
1918 STRNCPY(sock->idname, idname);
1919 node_socket_set_typeinfo(ntree, sock, node_socket_type_find(idname));
1920
1921 return sock;
1922}
1923
1925{
1926 switch (eNodeSocketDatatype(sock->type)) {
1927 case SOCK_OBJECT: {
1928 bNodeSocketValueObject &default_value = *sock->default_value_typed<bNodeSocketValueObject>();
1929 id_us_plus(reinterpret_cast<ID *>(default_value.value));
1930 break;
1931 }
1932 case SOCK_IMAGE: {
1933 bNodeSocketValueImage &default_value = *sock->default_value_typed<bNodeSocketValueImage>();
1934 id_us_plus(reinterpret_cast<ID *>(default_value.value));
1935 break;
1936 }
1937 case SOCK_COLLECTION: {
1938 bNodeSocketValueCollection &default_value =
1939 *sock->default_value_typed<bNodeSocketValueCollection>();
1940 id_us_plus(reinterpret_cast<ID *>(default_value.value));
1941 break;
1942 }
1943 case SOCK_TEXTURE: {
1944 bNodeSocketValueTexture &default_value =
1945 *sock->default_value_typed<bNodeSocketValueTexture>();
1946 id_us_plus(reinterpret_cast<ID *>(default_value.value));
1947 break;
1948 }
1949 case SOCK_MATERIAL: {
1950 bNodeSocketValueMaterial &default_value =
1951 *sock->default_value_typed<bNodeSocketValueMaterial>();
1952 id_us_plus(reinterpret_cast<ID *>(default_value.value));
1953 break;
1954 }
1955 case SOCK_FLOAT:
1956 case SOCK_VECTOR:
1957 case SOCK_RGBA:
1958 case SOCK_BOOLEAN:
1959 case SOCK_ROTATION:
1960 case SOCK_MATRIX:
1961 case SOCK_INT:
1962 case SOCK_STRING:
1963 case SOCK_MENU:
1964 case SOCK_CUSTOM:
1965 case SOCK_SHADER:
1966 case SOCK_GEOMETRY:
1967 break;
1968 }
1969}
1970
1973{
1974 switch (eNodeSocketDatatype(sock->type)) {
1975 case SOCK_OBJECT: {
1976 bNodeSocketValueObject &default_value = *sock->default_value_typed<bNodeSocketValueObject>();
1977 id_us_min(reinterpret_cast<ID *>(default_value.value));
1978 return default_value.value != nullptr;
1979 }
1980 case SOCK_IMAGE: {
1981 bNodeSocketValueImage &default_value = *sock->default_value_typed<bNodeSocketValueImage>();
1982 id_us_min(reinterpret_cast<ID *>(default_value.value));
1983 return default_value.value != nullptr;
1984 }
1985 case SOCK_COLLECTION: {
1986 bNodeSocketValueCollection &default_value =
1987 *sock->default_value_typed<bNodeSocketValueCollection>();
1988 id_us_min(reinterpret_cast<ID *>(default_value.value));
1989 return default_value.value != nullptr;
1990 }
1991 case SOCK_TEXTURE: {
1992 bNodeSocketValueTexture &default_value =
1993 *sock->default_value_typed<bNodeSocketValueTexture>();
1994 id_us_min(reinterpret_cast<ID *>(default_value.value));
1995 return default_value.value != nullptr;
1996 }
1997 case SOCK_MATERIAL: {
1998 bNodeSocketValueMaterial &default_value =
1999 *sock->default_value_typed<bNodeSocketValueMaterial>();
2000 id_us_min(reinterpret_cast<ID *>(default_value.value));
2001 return default_value.value != nullptr;
2002 }
2003 case SOCK_FLOAT:
2004 case SOCK_VECTOR:
2005 case SOCK_RGBA:
2006 case SOCK_BOOLEAN:
2007 case SOCK_ROTATION:
2008 case SOCK_MATRIX:
2009 case SOCK_INT:
2010 case SOCK_STRING:
2011 case SOCK_MENU:
2012 case SOCK_CUSTOM:
2013 case SOCK_SHADER:
2014 case SOCK_GEOMETRY:
2015 break;
2016 }
2017 return false;
2018}
2019
2021 bNode * /*node*/,
2022 bNodeSocket *sock,
2023 const char *idname)
2024{
2025 bNodeSocketType *socktype = node_socket_type_find(idname);
2026
2027 if (!socktype) {
2028 CLOG_ERROR(&LOG, "node socket type %s undefined", idname);
2029 return;
2030 }
2031
2032 if (sock->default_value) {
2033 if (sock->type != socktype->type) {
2034 /* Only reallocate the default value if the type changed so that UI data like min and max
2035 * isn't removed. This assumes that the default value is stored in the same format for all
2036 * socket types with the same #eNodeSocketDatatype. */
2038 MEM_freeN(sock->default_value);
2039 sock->default_value = nullptr;
2040 }
2041 else {
2042 /* Update the socket subtype when the storage isn't freed and recreated. */
2043 switch (eNodeSocketDatatype(sock->type)) {
2044 case SOCK_FLOAT: {
2045 sock->default_value_typed<bNodeSocketValueFloat>()->subtype = socktype->subtype;
2046 break;
2047 }
2048 case SOCK_VECTOR: {
2049 sock->default_value_typed<bNodeSocketValueVector>()->subtype = socktype->subtype;
2050 break;
2051 }
2052 case SOCK_INT: {
2053 sock->default_value_typed<bNodeSocketValueInt>()->subtype = socktype->subtype;
2054 break;
2055 }
2056 case SOCK_STRING: {
2057 sock->default_value_typed<bNodeSocketValueString>()->subtype = socktype->subtype;
2058 break;
2059 }
2060 case SOCK_RGBA:
2061 case SOCK_SHADER:
2062 case SOCK_BOOLEAN:
2063 case SOCK_ROTATION:
2064 case SOCK_MATRIX:
2065 case SOCK_CUSTOM:
2066 case SOCK_OBJECT:
2067 case SOCK_IMAGE:
2068 case SOCK_GEOMETRY:
2069 case SOCK_COLLECTION:
2070 case SOCK_TEXTURE:
2071 case SOCK_MATERIAL:
2072 case SOCK_MENU:
2073 break;
2074 }
2075 }
2076 }
2077
2078 STRNCPY(sock->idname, idname);
2079 node_socket_set_typeinfo(ntree, sock, socktype);
2080}
2081
2083 bNodeTree *ntree, bNode *node, bNodeSocket *sock, const int type, const int subtype)
2084{
2085 const char *idname = node_static_socket_type(type, subtype);
2086
2087 if (!idname) {
2088 CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
2089 return;
2090 }
2091
2092 node_modify_socket_type(ntree, node, sock, idname);
2093}
2094
2096 bNode *node,
2097 const eNodeSocketInOut in_out,
2098 const char *idname,
2099 const char *identifier,
2100 const char *name)
2101{
2102 BLI_assert(node->type != NODE_FRAME);
2103 BLI_assert(!(in_out == SOCK_IN && node->type == NODE_GROUP_INPUT));
2104 BLI_assert(!(in_out == SOCK_OUT && node->type == NODE_GROUP_OUTPUT));
2105
2106 ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs);
2107 bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name);
2108
2109 BLI_remlink(lb, sock); /* does nothing for new socket */
2110 BLI_addtail(lb, sock);
2111
2113
2114 return sock;
2115}
2116
2118{
2119 /*
2120 * Cannot rely on type==SOCK_CUSTOM here, because type is 0 by default
2121 * and can be changed on custom sockets.
2122 */
2123 return RNA_struct_is_a(stype->ext_socket.srna, &RNA_NodeSocketStandard);
2124}
2125
2126const char *node_static_socket_type(const int type, const int subtype)
2127{
2128 switch (eNodeSocketDatatype(type)) {
2129 case SOCK_FLOAT:
2130 switch (PropertySubType(subtype)) {
2131 case PROP_UNSIGNED:
2132 return "NodeSocketFloatUnsigned";
2133 case PROP_PERCENTAGE:
2134 return "NodeSocketFloatPercentage";
2135 case PROP_FACTOR:
2136 return "NodeSocketFloatFactor";
2137 case PROP_ANGLE:
2138 return "NodeSocketFloatAngle";
2139 case PROP_TIME:
2140 return "NodeSocketFloatTime";
2141 case PROP_TIME_ABSOLUTE:
2142 return "NodeSocketFloatTimeAbsolute";
2143 case PROP_DISTANCE:
2144 return "NodeSocketFloatDistance";
2145 case PROP_WAVELENGTH:
2146 return "NodeSocketFloatWavelength";
2148 return "NodeSocketFloatColorTemperature";
2149 case PROP_FREQUENCY:
2150 return "NodeSocketFloatFrequency";
2151 case PROP_NONE:
2152 default:
2153 return "NodeSocketFloat";
2154 }
2155 case SOCK_INT:
2156 switch (PropertySubType(subtype)) {
2157 case PROP_UNSIGNED:
2158 return "NodeSocketIntUnsigned";
2159 case PROP_PERCENTAGE:
2160 return "NodeSocketIntPercentage";
2161 case PROP_FACTOR:
2162 return "NodeSocketIntFactor";
2163 case PROP_NONE:
2164 default:
2165 return "NodeSocketInt";
2166 }
2167 case SOCK_BOOLEAN:
2168 return "NodeSocketBool";
2169 case SOCK_ROTATION:
2170 return "NodeSocketRotation";
2171 case SOCK_MATRIX:
2172 return "NodeSocketMatrix";
2173 case SOCK_VECTOR:
2174 switch (PropertySubType(subtype)) {
2175 case PROP_TRANSLATION:
2176 return "NodeSocketVectorTranslation";
2177 case PROP_DIRECTION:
2178 return "NodeSocketVectorDirection";
2179 case PROP_VELOCITY:
2180 return "NodeSocketVectorVelocity";
2181 case PROP_ACCELERATION:
2182 return "NodeSocketVectorAcceleration";
2183 case PROP_EULER:
2184 return "NodeSocketVectorEuler";
2185 case PROP_XYZ:
2186 return "NodeSocketVectorXYZ";
2187 case PROP_NONE:
2188 default:
2189 return "NodeSocketVector";
2190 }
2191 case SOCK_RGBA:
2192 return "NodeSocketColor";
2193 case SOCK_STRING:
2194 switch (PropertySubType(subtype)) {
2195 case PROP_FILEPATH:
2196 return "NodeSocketStringFilePath";
2197 default:
2198 return "NodeSocketString";
2199 }
2200 case SOCK_SHADER:
2201 return "NodeSocketShader";
2202 case SOCK_OBJECT:
2203 return "NodeSocketObject";
2204 case SOCK_IMAGE:
2205 return "NodeSocketImage";
2206 case SOCK_GEOMETRY:
2207 return "NodeSocketGeometry";
2208 case SOCK_COLLECTION:
2209 return "NodeSocketCollection";
2210 case SOCK_TEXTURE:
2211 return "NodeSocketTexture";
2212 case SOCK_MATERIAL:
2213 return "NodeSocketMaterial";
2214 case SOCK_MENU:
2215 return "NodeSocketMenu";
2216 case SOCK_CUSTOM:
2217 break;
2218 }
2219 return nullptr;
2220}
2221
2222const char *node_static_socket_interface_type_new(const int type, const int subtype)
2223{
2224 switch (eNodeSocketDatatype(type)) {
2225 case SOCK_FLOAT:
2226 switch (PropertySubType(subtype)) {
2227 case PROP_UNSIGNED:
2228 return "NodeTreeInterfaceSocketFloatUnsigned";
2229 case PROP_PERCENTAGE:
2230 return "NodeTreeInterfaceSocketFloatPercentage";
2231 case PROP_FACTOR:
2232 return "NodeTreeInterfaceSocketFloatFactor";
2233 case PROP_ANGLE:
2234 return "NodeTreeInterfaceSocketFloatAngle";
2235 case PROP_TIME:
2236 return "NodeTreeInterfaceSocketFloatTime";
2237 case PROP_TIME_ABSOLUTE:
2238 return "NodeTreeInterfaceSocketFloatTimeAbsolute";
2239 case PROP_DISTANCE:
2240 return "NodeTreeInterfaceSocketFloatDistance";
2241 case PROP_WAVELENGTH:
2242 return "NodeTreeInterfaceSocketFloatWavelength";
2244 return "NodeTreeInterfaceSocketFloatColorTemperature";
2245 case PROP_FREQUENCY:
2246 return "NodeTreeInterfaceSocketFloatFrequency";
2247 case PROP_NONE:
2248 default:
2249 return "NodeTreeInterfaceSocketFloat";
2250 }
2251 case SOCK_INT:
2252 switch (PropertySubType(subtype)) {
2253 case PROP_UNSIGNED:
2254 return "NodeTreeInterfaceSocketIntUnsigned";
2255 case PROP_PERCENTAGE:
2256 return "NodeTreeInterfaceSocketIntPercentage";
2257 case PROP_FACTOR:
2258 return "NodeTreeInterfaceSocketIntFactor";
2259 case PROP_NONE:
2260 default:
2261 return "NodeTreeInterfaceSocketInt";
2262 }
2263 case SOCK_BOOLEAN:
2264 return "NodeTreeInterfaceSocketBool";
2265 case SOCK_ROTATION:
2266 return "NodeTreeInterfaceSocketRotation";
2267 case SOCK_MATRIX:
2268 return "NodeTreeInterfaceSocketMatrix";
2269 case SOCK_VECTOR:
2270 switch (PropertySubType(subtype)) {
2271 case PROP_TRANSLATION:
2272 return "NodeTreeInterfaceSocketVectorTranslation";
2273 case PROP_DIRECTION:
2274 return "NodeTreeInterfaceSocketVectorDirection";
2275 case PROP_VELOCITY:
2276 return "NodeTreeInterfaceSocketVectorVelocity";
2277 case PROP_ACCELERATION:
2278 return "NodeTreeInterfaceSocketVectorAcceleration";
2279 case PROP_EULER:
2280 return "NodeTreeInterfaceSocketVectorEuler";
2281 case PROP_XYZ:
2282 return "NodeTreeInterfaceSocketVectorXYZ";
2283 case PROP_NONE:
2284 default:
2285 return "NodeTreeInterfaceSocketVector";
2286 }
2287 case SOCK_RGBA:
2288 return "NodeTreeInterfaceSocketColor";
2289 case SOCK_STRING:
2290 switch (PropertySubType(subtype)) {
2291 case PROP_FILEPATH:
2292 return "NodeTreeInterfaceSocketVectorTranslation";
2293 default:
2294 return "NodeTreeInterfaceSocketString";
2295 }
2296 case SOCK_SHADER:
2297 return "NodeTreeInterfaceSocketShader";
2298 case SOCK_OBJECT:
2299 return "NodeTreeInterfaceSocketObject";
2300 case SOCK_IMAGE:
2301 return "NodeTreeInterfaceSocketImage";
2302 case SOCK_GEOMETRY:
2303 return "NodeTreeInterfaceSocketGeometry";
2304 case SOCK_COLLECTION:
2305 return "NodeTreeInterfaceSocketCollection";
2306 case SOCK_TEXTURE:
2307 return "NodeTreeInterfaceSocketTexture";
2308 case SOCK_MATERIAL:
2309 return "NodeTreeInterfaceSocketMaterial";
2310 case SOCK_MENU:
2311 return "NodeTreeInterfaceSocketMenu";
2312 case SOCK_CUSTOM:
2313 break;
2314 }
2315 return nullptr;
2316}
2317
2318const char *node_static_socket_label(const int type, const int /*subtype*/)
2319{
2320 switch (eNodeSocketDatatype(type)) {
2321 case SOCK_FLOAT:
2322 return "Float";
2323 case SOCK_INT:
2324 return "Integer";
2325 case SOCK_BOOLEAN:
2326 return "Boolean";
2327 case SOCK_ROTATION:
2328 return "Rotation";
2329 case SOCK_MATRIX:
2330 return "Matrix";
2331 case SOCK_VECTOR:
2332 return "Vector";
2333 case SOCK_RGBA:
2334 return "Color";
2335 case SOCK_STRING:
2336 return "String";
2337 case SOCK_SHADER:
2338 return "Shader";
2339 case SOCK_OBJECT:
2340 return "Object";
2341 case SOCK_IMAGE:
2342 return "Image";
2343 case SOCK_GEOMETRY:
2344 return "Geometry";
2345 case SOCK_COLLECTION:
2346 return "Collection";
2347 case SOCK_TEXTURE:
2348 return "Texture";
2349 case SOCK_MATERIAL:
2350 return "Material";
2351 case SOCK_MENU:
2352 return "Menu";
2353 case SOCK_CUSTOM:
2354 break;
2355 }
2356 return nullptr;
2357}
2358
2360 bNode *node,
2361 eNodeSocketInOut in_out,
2362 int type,
2363 int subtype,
2364 const char *identifier,
2365 const char *name)
2366{
2367 const char *idname = node_static_socket_type(type, subtype);
2368
2369 if (!idname) {
2370 CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
2371 return nullptr;
2372 }
2373
2374 bNodeSocket *sock = node_add_socket(ntree, node, in_out, idname, identifier, name);
2375 sock->type = type;
2376 return sock;
2377}
2378
2379static void node_socket_free(bNodeSocket *sock, const bool do_id_user)
2380{
2381 if (sock->prop) {
2382 IDP_FreePropertyContent_ex(sock->prop, do_id_user);
2383 MEM_freeN(sock->prop);
2384 }
2385
2386 if (sock->default_value) {
2387 if (do_id_user) {
2389 }
2390 if (sock->type == SOCK_MENU) {
2391 auto &default_value_menu = *sock->default_value_typed<bNodeSocketValueMenu>();
2392 if (default_value_menu.enum_items) {
2393 /* Release shared data pointer. */
2394 default_value_menu.enum_items->remove_user_and_delete_if_last();
2395 }
2396 }
2397 MEM_freeN(sock->default_value);
2398 }
2399 if (sock->default_attribute_name) {
2401 }
2402 MEM_delete(sock->runtime);
2403}
2404
2406{
2407 node_remove_socket_ex(ntree, node, sock, true);
2408}
2409
2410void node_remove_socket_ex(bNodeTree *ntree, bNode *node, bNodeSocket *sock, const bool do_id_user)
2411{
2412 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
2413 if (link->fromsock == sock || link->tosock == sock) {
2414 node_remove_link(ntree, link);
2415 }
2416 }
2417
2418 for (const int64_t i : node->runtime->internal_links.index_range()) {
2419 const bNodeLink &link = node->runtime->internal_links[i];
2420 if (link.fromsock == sock || link.tosock == sock) {
2421 node->runtime->internal_links.remove_and_reorder(i);
2423 break;
2424 }
2425 }
2426
2427 /* this is fast, this way we don't need an in_out argument */
2428 BLI_remlink(&node->inputs, sock);
2429 BLI_remlink(&node->outputs, sock);
2430
2431 node_socket_free(sock, do_id_user);
2432 MEM_freeN(sock);
2433
2435}
2436
2437bNode *node_find_node_by_name(bNodeTree *ntree, const char *name)
2438{
2439 return reinterpret_cast<bNode *>(BLI_findstring(&ntree->nodes, name, offsetof(bNode, name)));
2440}
2441
2442void node_find_node(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
2443{
2444 *r_node = nullptr;
2445 if (ntree->runtime->topology_cache_mutex.is_cached()) {
2446 bNode *node = &sock->owner_node();
2447 *r_node = node;
2448 if (r_sockindex) {
2449 const ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
2450 *r_sockindex = BLI_findindex(sockets, sock);
2451 }
2452 return;
2453 }
2454 const bool success = node_find_node_try(ntree, sock, r_node, r_sockindex);
2455 BLI_assert(success);
2456 UNUSED_VARS_NDEBUG(success);
2457}
2458
2459bool node_find_node_try(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
2460{
2461 for (bNode *node : ntree->all_nodes()) {
2462 const ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
2463 int i;
2464 LISTBASE_FOREACH_INDEX (const bNodeSocket *, tsock, sockets, i) {
2465 if (sock == tsock) {
2466 if (r_node != nullptr) {
2467 *r_node = node;
2468 }
2469 if (r_sockindex != nullptr) {
2470 *r_sockindex = i;
2471 }
2472 return true;
2473 }
2474 }
2475 }
2476 return false;
2477}
2478
2480{
2481 bNode *parent_iter = node;
2482 while (parent_iter->parent != nullptr) {
2483 parent_iter = parent_iter->parent;
2484 }
2485 if (parent_iter->type != NODE_FRAME) {
2486 return nullptr;
2487 }
2488 return parent_iter;
2489}
2490
2491bool node_is_parent_and_child(const bNode *parent, const bNode *child)
2492{
2493 for (const bNode *child_iter = child; child_iter; child_iter = child_iter->parent) {
2494 if (child_iter == parent) {
2495 return true;
2496 }
2497 }
2498 return false;
2499}
2500
2502 const bNode *node_start,
2503 bool (*callback)(bNode *, bNode *, void *, const bool),
2504 void *userdata,
2505 const bool reversed)
2506{
2507 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
2508 if ((link->flag & NODE_LINK_VALID) == 0) {
2509 /* Skip links marked as cyclic. */
2510 continue;
2511 }
2512 /* Is the link part of the chain meaning node_start == fromnode
2513 * (or tonode for reversed case)? */
2514 if (!reversed) {
2515 if (link->fromnode != node_start) {
2516 continue;
2517 }
2518 }
2519 else {
2520 if (link->tonode != node_start) {
2521 continue;
2522 }
2523 }
2524
2525 if (!callback(link->fromnode, link->tonode, userdata, reversed)) {
2526 return;
2527 }
2529 ntree, reversed ? link->fromnode : link->tonode, callback, userdata, reversed);
2530 }
2531}
2532
2533static void iter_backwards_ex(const bNodeTree *ntree,
2534 const bNode *node_start,
2535 bool (*callback)(bNode *, bNode *, void *),
2536 void *userdata,
2537 const char recursion_mask)
2538{
2539 LISTBASE_FOREACH (bNodeSocket *, sock, &node_start->inputs) {
2540 bNodeLink *link = sock->link;
2541 if (link == nullptr) {
2542 continue;
2543 }
2544 if ((link->flag & NODE_LINK_VALID) == 0) {
2545 /* Skip links marked as cyclic. */
2546 continue;
2547 }
2548 if (link->fromnode->runtime->iter_flag & recursion_mask) {
2549 continue;
2550 }
2551
2552 link->fromnode->runtime->iter_flag |= recursion_mask;
2553
2554 if (!callback(link->fromnode, link->tonode, userdata)) {
2555 return;
2556 }
2557 iter_backwards_ex(ntree, link->fromnode, callback, userdata, recursion_mask);
2558 }
2559}
2560
2562 const bNode *node_start,
2563 bool (*callback)(bNode *, bNode *, void *),
2564 void *userdata,
2565 const int recursion_lvl)
2566{
2567 if (!node_start) {
2568 return;
2569 }
2570
2571 /* Limited by iter_flag type. */
2572 BLI_assert(recursion_lvl < 8);
2573 const char recursion_mask = (1 << recursion_lvl);
2574
2575 /* Reset flag. */
2576 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
2577 node->runtime->iter_flag &= ~recursion_mask;
2578 }
2579
2580 iter_backwards_ex(ntree, node_start, callback, userdata, recursion_mask);
2581}
2582
2583void node_parents_iterator(bNode *node, bool (*callback)(bNode *, void *), void *userdata)
2584{
2585 if (node->parent) {
2586 if (!callback(node->parent, userdata)) {
2587 return;
2588 }
2589 node_parents_iterator(node->parent, callback, userdata);
2590 }
2591}
2592
2594{
2596 &ntree->nodes, node, DATA_("Node"), '.', offsetof(bNode, name), sizeof(node->name));
2597}
2598
2599void node_unique_id(bNodeTree *ntree, bNode *node)
2600{
2601 /* Use a pointer cast to avoid overflow warnings. */
2602 const double time = BLI_time_now_seconds() * 1000000.0;
2603 RandomNumberGenerator id_rng{*reinterpret_cast<const uint32_t *>(&time)};
2604
2605 /* In the unlikely case that the random ID doesn't match, choose a new one until it does. */
2606 int32_t new_id = id_rng.get_int32();
2607 while (ntree->runtime->nodes_by_id.contains_as(new_id) || new_id <= 0) {
2608 new_id = id_rng.get_int32();
2609 }
2610
2611 node->identifier = new_id;
2612 ntree->runtime->nodes_by_id.add_new(node);
2613 node->runtime->index_in_tree = ntree->runtime->nodes_by_id.index_range().last();
2614 BLI_assert(node->runtime->index_in_tree == ntree->runtime->nodes_by_id.index_of(node));
2615}
2616
2617bNode *node_add_node(const bContext *C, bNodeTree *ntree, const char *idname)
2618{
2619 bNode *node = MEM_cnew<bNode>("new node");
2620 node->runtime = MEM_new<bNodeRuntime>(__func__);
2621 BLI_addtail(&ntree->nodes, node);
2622 node_unique_id(ntree, node);
2623 node->ui_order = ntree->all_nodes().size();
2624
2625 STRNCPY(node->idname, idname);
2626 node_set_typeinfo(C, ntree, node, node_type_find(idname));
2627
2628 BKE_ntree_update_tag_node_new(ntree, node);
2629
2630 if (ELEM(node->type,
2631 GEO_NODE_INPUT_SCENE_TIME,
2632 GEO_NODE_INPUT_ACTIVE_CAMERA,
2633 GEO_NODE_SELF_OBJECT,
2634 GEO_NODE_SIMULATION_INPUT))
2635 {
2637 }
2638
2639 return node;
2640}
2641
2642bNode *node_add_static_node(const bContext *C, bNodeTree *ntree, const int type)
2643{
2644 const char *idname = nullptr;
2645
2646 NODE_TYPES_BEGIN (ntype) {
2647 /* Do an extra poll here, because some int types are used
2648 * for multiple node types, this helps find the desired type. */
2649 if (ntype->type != type) {
2650 continue;
2651 }
2652
2653 const char *disabled_hint;
2654 if (ntype->poll && ntype->poll(ntype, ntree, &disabled_hint)) {
2655 idname = ntype->idname;
2656 break;
2657 }
2658 }
2660 if (!idname) {
2661 CLOG_ERROR(&LOG, "static node type %d undefined", type);
2662 return nullptr;
2663 }
2664 return node_add_node(C, ntree, idname);
2665}
2666
2667static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag)
2668{
2669 sock_dst->runtime = MEM_new<bNodeSocketRuntime>(__func__);
2670 if (sock_src->prop) {
2671 sock_dst->prop = IDP_CopyProperty_ex(sock_src->prop, flag);
2672 }
2673
2674 if (sock_src->default_value) {
2675 sock_dst->default_value = MEM_dupallocN(sock_src->default_value);
2676
2677 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
2678 socket_id_user_increment(sock_dst);
2679 }
2680
2681 if (sock_src->type == SOCK_MENU) {
2682 auto &default_value_menu = *sock_dst->default_value_typed<bNodeSocketValueMenu>();
2683 if (default_value_menu.enum_items) {
2684 /* Copy of shared data pointer. */
2685 default_value_menu.enum_items->add_user();
2686 }
2687 }
2688 }
2689
2690 sock_dst->default_attribute_name = static_cast<char *>(
2692
2693 sock_dst->stack_index = 0;
2694}
2695
2697 const bNode &node_src,
2698 const int flag,
2699 const bool use_unique,
2701{
2702 bNode *node_dst = static_cast<bNode *>(MEM_mallocN(sizeof(bNode), __func__));
2703 *node_dst = node_src;
2704
2705 node_dst->runtime = MEM_new<bNodeRuntime>(__func__);
2706
2707 /* Can be called for nodes outside a node tree (e.g. clipboard). */
2708 if (dst_tree) {
2709 if (use_unique) {
2710 node_unique_name(dst_tree, node_dst);
2711 node_unique_id(dst_tree, node_dst);
2712 }
2713 BLI_addtail(&dst_tree->nodes, node_dst);
2714 }
2715
2716 BLI_listbase_clear(&node_dst->inputs);
2717 LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.inputs) {
2718 bNodeSocket *dst_socket = static_cast<bNodeSocket *>(MEM_dupallocN(src_socket));
2719 node_socket_copy(dst_socket, src_socket, flag);
2720 BLI_addtail(&node_dst->inputs, dst_socket);
2721 socket_map.add_new(src_socket, dst_socket);
2722 }
2723
2724 BLI_listbase_clear(&node_dst->outputs);
2725 LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.outputs) {
2726 bNodeSocket *dst_socket = static_cast<bNodeSocket *>(MEM_dupallocN(src_socket));
2727 node_socket_copy(dst_socket, src_socket, flag);
2728 BLI_addtail(&node_dst->outputs, dst_socket);
2729 socket_map.add_new(src_socket, dst_socket);
2730 }
2731
2732 if (node_src.prop) {
2733 node_dst->prop = IDP_CopyProperty_ex(node_src.prop, flag);
2734 }
2735
2736 node_dst->panel_states_array = static_cast<bNodePanelState *>(
2738
2739 node_dst->runtime->internal_links = node_src.runtime->internal_links;
2740 for (bNodeLink &dst_link : node_dst->runtime->internal_links) {
2741 dst_link.fromnode = node_dst;
2742 dst_link.tonode = node_dst;
2743 dst_link.fromsock = socket_map.lookup(dst_link.fromsock);
2744 dst_link.tosock = socket_map.lookup(dst_link.tosock);
2745 }
2746
2747 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
2748 id_us_plus(node_dst->id);
2749 }
2750
2751 if (node_src.typeinfo->copyfunc) {
2752 node_src.typeinfo->copyfunc(dst_tree, node_dst, &node_src);
2753 }
2754
2755 if (dst_tree) {
2756 BKE_ntree_update_tag_node_new(dst_tree, node_dst);
2757 }
2758
2759 /* Only call copy function when a copy is made for the main database, not
2760 * for cases like the dependency graph and localization. */
2761 if (node_dst->typeinfo->copyfunc_api && !(flag & LIB_ID_CREATE_NO_MAIN)) {
2762 PointerRNA ptr = RNA_pointer_create(reinterpret_cast<ID *>(dst_tree), &RNA_Node, node_dst);
2763
2764 node_dst->typeinfo->copyfunc_api(&ptr, &node_src);
2765 }
2766
2767 return node_dst;
2768}
2769
2774static void *node_static_value_storage_for(bNode &node, const bNodeSocket &socket)
2775{
2776 if (!socket.is_output()) {
2777 return nullptr;
2778 }
2779
2780 switch (node.type) {
2781 case FN_NODE_INPUT_BOOL:
2782 return &reinterpret_cast<NodeInputBool *>(node.storage)->boolean;
2783 case SH_NODE_VALUE:
2784 /* The value is stored in the default value of the first output socket. */
2785 return &static_cast<bNodeSocket *>(node.outputs.first)
2786 ->default_value_typed<bNodeSocketValueFloat>()
2787 ->value;
2788 case FN_NODE_INPUT_INT:
2789 return &reinterpret_cast<NodeInputInt *>(node.storage)->integer;
2791 return &reinterpret_cast<NodeInputVector *>(node.storage)->vector;
2793 return &reinterpret_cast<NodeInputColor *>(node.storage)->color;
2794 case GEO_NODE_IMAGE:
2795 return &node.id;
2796 default:
2797 break;
2798 }
2799
2800 return nullptr;
2801}
2802
2804{
2805 switch (eNodeSocketDatatype(socket.type)) {
2806 case SOCK_BOOLEAN:
2807 return &socket.default_value_typed<bNodeSocketValueBoolean>()->value;
2808 case SOCK_INT:
2809 return &socket.default_value_typed<bNodeSocketValueInt>()->value;
2810 case SOCK_FLOAT:
2811 return &socket.default_value_typed<bNodeSocketValueFloat>()->value;
2812 case SOCK_VECTOR:
2813 return &socket.default_value_typed<bNodeSocketValueVector>()->value;
2814 case SOCK_RGBA:
2815 return &socket.default_value_typed<bNodeSocketValueRGBA>()->value;
2816 case SOCK_IMAGE:
2817 return &socket.default_value_typed<bNodeSocketValueImage>()->value;
2818 case SOCK_TEXTURE:
2819 return &socket.default_value_typed<bNodeSocketValueTexture>()->value;
2820 case SOCK_COLLECTION:
2821 return &socket.default_value_typed<bNodeSocketValueCollection>()->value;
2822 case SOCK_OBJECT:
2823 return &socket.default_value_typed<bNodeSocketValueObject>()->value;
2824 case SOCK_MATERIAL:
2825 return &socket.default_value_typed<bNodeSocketValueMaterial>()->value;
2826 case SOCK_ROTATION:
2827 return &socket.default_value_typed<bNodeSocketValueRotation>()->value_euler;
2828 case SOCK_MENU:
2829 return &socket.default_value_typed<bNodeSocketValueMenu>()->value;
2830 case SOCK_MATRIX:
2831 /* Matrix sockets currently have no default value. */
2832 return nullptr;
2833 case SOCK_STRING:
2834 /* We don't want do this now! */
2835 return nullptr;
2836 case SOCK_CUSTOM:
2837 case SOCK_SHADER:
2838 case SOCK_GEOMETRY:
2839 /* Unmovable types. */
2840 break;
2841 }
2842
2843 return nullptr;
2844}
2845
2847 bNodeTree &tree,
2848 bNodeSocket &src,
2849 bNodeSocket &dst)
2850{
2851 tree.ensure_topology_cache();
2852
2853 bNode &dst_node = dst.owner_node();
2854 bNode &src_node = src.owner_node();
2855
2856 const CPPType &src_type = *src.typeinfo->base_cpp_type;
2857 const CPPType &dst_type = *dst.typeinfo->base_cpp_type;
2858
2860
2861 if (src.is_multi_input()) {
2862 /* Multi input sockets no have value. */
2863 return;
2864 }
2865 if (ELEM(NODE_REROUTE, dst_node.type, src_node.type)) {
2866 /* Reroute node can't have ownership of socket value directly. */
2867 return;
2868 }
2869 if (&src_type != &dst_type) {
2870 if (!convert.is_convertible(src_type, dst_type)) {
2871 return;
2872 }
2873 }
2874
2875 void *src_value = socket_value_storage(src);
2876 void *dst_value = node_static_value_storage_for(dst_node, dst);
2877 if (!dst_value || !src_value) {
2878 return;
2879 }
2880
2881 convert.convert_to_uninitialized(src_type, dst_type, src_value, dst_value);
2882
2883 src_type.destruct(src_value);
2884 if (ELEM(eNodeSocketDatatype(src.type),
2886 SOCK_IMAGE,
2889 SOCK_OBJECT))
2890 {
2891 src_type.value_initialize(src_value);
2892 }
2893}
2894
2895bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, const int flag, const bool use_unique)
2896{
2898 return node_copy_with_mapping(dst_tree, src_node, flag, use_unique, socket_map);
2899}
2900
2901static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket)
2902{
2903 int count = 0;
2904 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
2905 if (ELEM(socket, link->fromsock, link->tosock)) {
2906 count++;
2907 }
2908 }
2909 return count;
2910}
2911
2913 bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
2914{
2915 BLI_assert(fromnode);
2916 BLI_assert(tonode);
2917 BLI_assert(ntree->all_nodes().contains(fromnode));
2918 BLI_assert(ntree->all_nodes().contains(tonode));
2919
2920 bNodeLink *link = nullptr;
2921 if (eNodeSocketInOut(fromsock->in_out) == SOCK_OUT &&
2922 eNodeSocketInOut(tosock->in_out) == SOCK_IN)
2923 {
2924 link = MEM_cnew<bNodeLink>("link");
2925 if (ntree) {
2926 BLI_addtail(&ntree->links, link);
2927 }
2928 link->fromnode = fromnode;
2929 link->fromsock = fromsock;
2930 link->tonode = tonode;
2931 link->tosock = tosock;
2932 }
2933 else if (eNodeSocketInOut(fromsock->in_out) == SOCK_IN &&
2934 eNodeSocketInOut(tosock->in_out) == SOCK_OUT)
2935 {
2936 /* OK but flip */
2937 link = MEM_cnew<bNodeLink>("link");
2938 if (ntree) {
2939 BLI_addtail(&ntree->links, link);
2940 }
2941 link->fromnode = tonode;
2942 link->fromsock = tosock;
2943 link->tonode = fromnode;
2944 link->tosock = fromsock;
2945 }
2946
2947 if (ntree) {
2949 }
2950
2951 if (link != nullptr && link->tosock->is_multi_input()) {
2952 link->multi_input_sort_id = node_count_links(ntree, link->tosock) - 1;
2953 }
2954
2955 return link;
2956}
2957
2959{
2960 /* Can be called for links outside a node tree (e.g. clipboard). */
2961 if (ntree) {
2962 BLI_remlink(&ntree->links, link);
2963 }
2964
2965 if (link->tosock) {
2966 link->tosock->link = nullptr;
2967 }
2968 MEM_freeN(link);
2969
2970 if (ntree) {
2972 }
2973}
2974
2975void node_link_set_mute(bNodeTree *ntree, bNodeLink *link, const bool muted)
2976{
2977 const bool was_muted = link->is_muted();
2979 if (muted != was_muted) {
2980 BKE_ntree_update_tag_link_mute(ntree, link);
2981 }
2982}
2983
2985{
2986 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
2987 if (link->fromsock == sock || link->tosock == sock) {
2988 node_remove_link(ntree, link);
2989 }
2990 }
2991}
2992
2994{
2995 return !(link->fromsock->is_visible() && link->tosock->is_visible());
2996}
2997
2999{
3000 return (link->fromnode->flag & NODE_SELECT) || (link->tonode->flag & NODE_SELECT);
3001}
3002
3003/* Adjust the indices of links connected to the given multi input socket after deleting the link at
3004 * `deleted_index`. This function also works if the link has not yet been deleted. */
3006 const bNodeSocket *sock,
3007 const int deleted_index)
3008{
3009 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
3010 /* We only need to adjust those with a greater index, because the others will have the same
3011 * index. */
3012 if (link->tosock != sock || link->multi_input_sort_id <= deleted_index) {
3013 continue;
3014 }
3015 link->multi_input_sort_id -= 1;
3016 }
3017}
3018
3020{
3021 /* store link pointers in output sockets, for efficient lookup */
3022 for (bNodeLink &link : node->runtime->internal_links) {
3023 link.tosock->link = &link;
3024 }
3025
3026 Vector<bNodeLink *> duplicate_links_to_remove;
3027
3028 /* redirect downstream links */
3029 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
3030 /* do we have internal link? */
3031 if (link->fromnode != node) {
3032 continue;
3033 }
3034
3035 bNodeLink *internal_link = link->fromsock->link;
3036 bNodeLink *fromlink = internal_link ? internal_link->fromsock->link : nullptr;
3037
3038 if (fromlink == nullptr) {
3039 if (link->tosock->is_multi_input()) {
3041 ntree, link->tosock, link->multi_input_sort_id);
3042 }
3043 node_remove_link(ntree, link);
3044 continue;
3045 }
3046
3047 if (link->tosock->is_multi_input()) {
3048 /* remove the link that would be the same as the relinked one */
3049 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link_to_compare, &ntree->links) {
3050 if (link_to_compare->fromsock == fromlink->fromsock &&
3051 link_to_compare->tosock == link->tosock)
3052 {
3054 ntree, link_to_compare->tosock, link_to_compare->multi_input_sort_id);
3055 duplicate_links_to_remove.append_non_duplicates(link_to_compare);
3056 }
3057 }
3058 }
3059
3060 link->fromnode = fromlink->fromnode;
3061 link->fromsock = fromlink->fromsock;
3062
3063 /* if the up- or downstream link is invalid,
3064 * the replacement link will be invalid too.
3065 */
3066 if (!(fromlink->flag & NODE_LINK_VALID)) {
3067 link->flag &= ~NODE_LINK_VALID;
3068 }
3069
3070 if (fromlink->flag & NODE_LINK_MUTED) {
3071 link->flag |= NODE_LINK_MUTED;
3072 }
3073
3075 }
3076
3077 for (bNodeLink *link : duplicate_links_to_remove) {
3078 node_remove_link(ntree, link);
3079 }
3080
3081 /* remove remaining upstream links */
3082 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
3083 if (link->tonode == node) {
3084 node_remove_link(ntree, link);
3085 }
3086 }
3087}
3088
3089float2 node_to_view(const bNode *node, const float2 loc)
3090{
3091 float2 view_loc = loc;
3092 for (const bNode *node_iter = node; node_iter; node_iter = node_iter->parent) {
3093 view_loc += float2(node_iter->locx, node_iter->locy);
3094 }
3095 return view_loc;
3096}
3097
3098float2 node_from_view(const bNode *node, const float2 view_loc)
3099{
3100 float2 loc = view_loc;
3101 for (const bNode *node_iter = node; node_iter; node_iter = node_iter->parent) {
3102 loc -= float2(node_iter->locx, node_iter->locy);
3103 }
3104 return loc;
3105}
3106
3107void node_attach_node(bNodeTree *ntree, bNode *node, bNode *parent)
3108{
3109 BLI_assert(parent->type == NODE_FRAME);
3110 BLI_assert(!node_is_parent_and_child(parent, node));
3111
3112 const float2 loc = node_to_view(node, {});
3113
3114 node->parent = parent;
3116 /* transform to parent space */
3117 const float2 new_loc = node_from_view(parent, loc);
3118 node->locx = new_loc.x;
3119 node->locy = new_loc.y;
3120}
3121
3123{
3124 if (node->parent) {
3125 BLI_assert(node->parent->type == NODE_FRAME);
3126
3127 /* transform to view space */
3128 const float2 loc = node_to_view(node, {});
3129 node->locx = loc.x;
3130 node->locy = loc.y;
3131 node->parent = nullptr;
3133 }
3134}
3135
3137 const bNode *to_node,
3138 const bNodeSocket *from_sock,
3139 const bNodeSocket *to_sock)
3140{
3141 float offset_x;
3142 int tot_sock_idx;
3143
3144 /* Socket to plug into. */
3145 if (eNodeSocketInOut(to_sock->in_out) == SOCK_IN) {
3146 offset_x = -(from_node->typeinfo->width + 50);
3147 tot_sock_idx = BLI_listbase_count(&to_node->outputs);
3148 tot_sock_idx += BLI_findindex(&to_node->inputs, to_sock);
3149 }
3150 else {
3151 offset_x = to_node->typeinfo->width + 50;
3152 tot_sock_idx = BLI_findindex(&to_node->outputs, to_sock);
3153 }
3154
3155 BLI_assert(tot_sock_idx != -1);
3156
3157 float offset_y = U.widget_unit * tot_sock_idx;
3158
3159 /* Output socket. */
3160 if (from_sock) {
3161 if (eNodeSocketInOut(from_sock->in_out) == SOCK_IN) {
3162 tot_sock_idx = BLI_listbase_count(&from_node->outputs);
3163 tot_sock_idx += BLI_findindex(&from_node->inputs, from_sock);
3164 }
3165 else {
3166 tot_sock_idx = BLI_findindex(&from_node->outputs, from_sock);
3167 }
3168 }
3169
3170 BLI_assert(tot_sock_idx != -1);
3171
3172 offset_y -= U.widget_unit * tot_sock_idx;
3173
3174 from_node->locx = to_node->locx + offset_x;
3175 from_node->locy = to_node->locy - offset_y;
3176}
3177
3179{
3180 LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
3181 if (socket->link != nullptr) {
3182 bNodeLink *link = socket->link;
3183 node_position_relative(link->fromnode, link->tonode, link->fromsock, link->tosock);
3185 }
3186 }
3187}
3188
3190 std::optional<Library *> owner_library,
3191 ID *owner_id,
3192 const bool is_embedded,
3193 const char *name,
3194 const char *idname)
3195{
3196 /* trees are created as local trees for compositor, material or texture nodes,
3197 * node groups and other tree types are created as library data.
3198 */
3199 int flag = 0;
3200 if (is_embedded || bmain == nullptr) {
3202 }
3203 BLI_assert_msg(!owner_library || !owner_id,
3204 "Embedded NTrees should never have a defined owner library here");
3205 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(
3206 BKE_libblock_alloc_in_lib(bmain, owner_library, ID_NT, name, flag));
3207 BKE_libblock_init_empty(&ntree->id);
3208 if (is_embedded) {
3209 BLI_assert(owner_id != nullptr);
3210 ntree->id.flag |= ID_FLAG_EMBEDDED_DATA;
3211 ntree->owner_id = owner_id;
3212 bNodeTree **ntree_owner_ptr = node_tree_ptr_from_id(owner_id);
3213 BLI_assert(ntree_owner_ptr != nullptr);
3214 *ntree_owner_ptr = ntree;
3215 }
3216 else {
3217 BLI_assert(owner_id == nullptr);
3218 }
3219
3220 STRNCPY(ntree->idname, idname);
3222
3223 return ntree;
3224}
3225
3226bNodeTree *node_tree_add_tree(Main *bmain, const char *name, const char *idname)
3227{
3228 return node_tree_add_tree_do(bmain, std::nullopt, nullptr, false, name, idname);
3229}
3230
3232 Library *owner_library,
3233 const char *name,
3234 const char *idname)
3235{
3236 return node_tree_add_tree_do(bmain, owner_library, nullptr, false, name, idname);
3237}
3238
3240 ID *owner_id,
3241 const char *name,
3242 const char *idname)
3243{
3244 return node_tree_add_tree_do(nullptr, std::nullopt, owner_id, true, name, idname);
3245}
3246
3247bNodeTree *node_tree_copy_tree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user)
3248{
3249 const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN;
3250
3251 bNodeTree *ntree_copy = reinterpret_cast<bNodeTree *>(
3252 BKE_id_copy_ex(bmain, reinterpret_cast<const ID *>(ntree), nullptr, flag));
3253 return ntree_copy;
3254}
3256{
3257 return node_tree_copy_tree_ex(ntree, bmain, true);
3258}
3259
3260/* *************** Node Preview *********** */
3261
3262/* XXX this should be removed eventually ...
3263 * Currently BKE functions are modeled closely on previous code,
3264 * using node_preview_init_tree to set up previews for a whole node tree in advance.
3265 * This should be left more to the individual node tree implementations. */
3266
3267bool node_preview_used(const bNode *node)
3268{
3269 /* XXX check for closed nodes? */
3270 return (node->typeinfo->flag & NODE_PREVIEW) != 0;
3271}
3272
3274 bNodeInstanceKey key,
3275 const int xsize,
3276 const int ysize,
3277 const bool create)
3278{
3279 bNodePreview *preview = static_cast<bNodePreview *>(node_instance_hash_lookup(previews, key));
3280 if (!preview) {
3281 if (create) {
3282 preview = MEM_cnew<bNodePreview>("node preview");
3283 preview->ibuf = IMB_allocImBuf(xsize, ysize, 32, IB_rect);
3284 node_instance_hash_insert(previews, key, preview);
3285 }
3286 else {
3287 return nullptr;
3288 }
3289 }
3290
3291 /* node previews can get added with variable size this way */
3292 if (xsize == 0 || ysize == 0) {
3293 return preview;
3294 }
3295
3296 /* sanity checks & initialize */
3297 const uint size[2] = {uint(xsize), uint(ysize)};
3298 IMB_rect_size_set(preview->ibuf, size);
3299 if (preview->ibuf->byte_buffer.data == nullptr) {
3300 imb_addrectImBuf(preview->ibuf);
3301 }
3302 /* no clear, makes nicer previews */
3303
3304 return preview;
3305}
3306
3308{
3309 bNodePreview *new_preview = static_cast<bNodePreview *>(MEM_dupallocN(preview));
3310 new_preview->ibuf = IMB_dupImBuf(preview->ibuf);
3311 return new_preview;
3312}
3313
3315{
3316 if (preview->ibuf) {
3317 IMB_freeImBuf(preview->ibuf);
3318 }
3319 MEM_freeN(preview);
3320}
3321
3323 bNodeTree *ntree,
3324 bNodeInstanceKey parent_key,
3325 const int xsize,
3326 const int ysize)
3327{
3328 for (bNode *node : ntree->all_nodes()) {
3329 bNodeInstanceKey key = node_instance_key(parent_key, ntree, node);
3330
3331 if (node_preview_used(node)) {
3332 node->runtime->preview_xsize = xsize;
3333 node->runtime->preview_ysize = ysize;
3334
3335 node_preview_verify(previews, key, xsize, ysize, false);
3336 }
3337
3338 bNodeTree *group = reinterpret_cast<bNodeTree *>(node->id);
3339 if (node->is_group() && group != nullptr) {
3340 node_preview_init_tree_recursive(previews, group, key, xsize, ysize);
3341 }
3342 }
3343}
3344
3345void node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize)
3346{
3347 if (!ntree) {
3348 return;
3349 }
3350
3351 if (!ntree->previews) {
3352 ntree->previews = node_instance_hash_new("node previews");
3353 }
3354
3356}
3357
3359 bNodeTree *ntree,
3360 bNodeInstanceKey parent_key)
3361{
3362 for (bNode *node : ntree->all_nodes()) {
3363 bNodeInstanceKey key = node_instance_key(parent_key, ntree, node);
3364
3365 if (node_preview_used(node)) {
3366 node_instance_hash_tag_key(previews, key);
3367 }
3368
3369 bNodeTree *group = reinterpret_cast<bNodeTree *>(node->id);
3370 if (node->is_group() && group != nullptr) {
3371 node_preview_tag_used_recursive(previews, group, key);
3372 }
3373 }
3374}
3375
3377{
3378 if (!ntree || !ntree->previews) {
3379 return;
3380 }
3381
3382 /* use the instance hash functions for tagging and removing unused previews */
3385
3387 reinterpret_cast<bNodeInstanceValueFP>(node_preview_free));
3388}
3389
3390void node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool remove_old)
3391{
3392 if (remove_old || !to_ntree->previews) {
3393 /* free old previews */
3394 if (to_ntree->previews) {
3396 reinterpret_cast<bNodeInstanceValueFP>(node_preview_free));
3397 }
3398
3399 /* transfer previews */
3400 to_ntree->previews = from_ntree->previews;
3401 from_ntree->previews = nullptr;
3402
3403 /* clean up, in case any to_ntree nodes have been removed */
3405 }
3406 else {
3407 if (from_ntree->previews) {
3409 NODE_INSTANCE_HASH_ITER (iter, from_ntree->previews) {
3411 bNodePreview *preview = static_cast<bNodePreview *>(
3413
3414 /* replace existing previews */
3416 to_ntree->previews, key, reinterpret_cast<bNodeInstanceValueFP>(node_preview_free));
3417 node_instance_hash_insert(to_ntree->previews, key, preview);
3418 }
3419
3420 /* NOTE: null free function here,
3421 * because pointers have already been moved over to to_ntree->previews! */
3422 node_instance_hash_free(from_ntree->previews, nullptr);
3423 from_ntree->previews = nullptr;
3424 }
3425 }
3426}
3427
3429{
3430 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
3431 ListBase *lb = nullptr;
3432 if (link->fromnode == node) {
3433 lb = &node->outputs;
3434 }
3435 else if (link->tonode == node) {
3436 lb = &node->inputs;
3437 }
3438
3439 if (lb) {
3440 /* Only bother adjusting if the socket is not on the node we're deleting. */
3441 if (link->tonode != node && link->tosock->is_multi_input()) {
3443 ntree, link->tosock, link->multi_input_sort_id);
3444 }
3445 LISTBASE_FOREACH (const bNodeSocket *, sock, lb) {
3446 if (link->fromsock == sock || link->tosock == sock) {
3447 node_remove_link(ntree, link);
3448 break;
3449 }
3450 }
3451 }
3452 }
3453}
3454
3455static void node_unlink_attached(bNodeTree *ntree, const bNode *parent)
3456{
3457 for (bNode *node : ntree->all_nodes()) {
3458 if (node->parent == parent) {
3459 node_detach_node(ntree, node);
3460 }
3461 }
3462}
3463
3465{
3466 /* Rebuild nodes #VectorSet which must have the same order as the list. */
3467 node_tree->runtime->nodes_by_id.clear();
3468 int i;
3469 LISTBASE_FOREACH_INDEX (bNode *, node, &node_tree->nodes, i) {
3470 node_tree->runtime->nodes_by_id.add_new(node);
3471 node->runtime->index_in_tree = i;
3472 }
3473}
3474
3475void node_free_node(bNodeTree *ntree, bNode *node)
3476{
3477 /* since it is called while free database, node->id is undefined */
3478
3479 /* can be called for nodes outside a node tree (e.g. clipboard) */
3480 if (ntree) {
3481 BLI_remlink(&ntree->nodes, node);
3482 /* Rebuild nodes #VectorSet which must have the same order as the list. */
3484
3485 /* texture node has bad habit of keeping exec data around */
3486 if (ntree->type == NTREE_TEXTURE && ntree->runtime->execdata) {
3487 ntreeTexEndExecTree(ntree->runtime->execdata);
3488 ntree->runtime->execdata = nullptr;
3489 }
3490 }
3491
3492 if (node->typeinfo->freefunc) {
3493 node->typeinfo->freefunc(node);
3494 }
3495
3496 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
3497 /* Remember, no ID user refcount management here! */
3498 node_socket_free(sock, false);
3499 MEM_freeN(sock);
3500 }
3501 LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
3502 /* Remember, no ID user refcount management here! */
3503 node_socket_free(sock, false);
3504 MEM_freeN(sock);
3505 }
3506
3507 MEM_SAFE_FREE(node->panel_states_array);
3508
3509 if (node->prop) {
3510 /* Remember, no ID user refcount management here! */
3511 IDP_FreePropertyContent_ex(node->prop, false);
3512 MEM_freeN(node->prop);
3513 }
3514
3515 if (node->runtime->declaration) {
3516 /* Only free if this declaration is not shared with the node type, which can happen if it does
3517 * not depend on any context. */
3518 if (node->runtime->declaration != node->typeinfo->static_declaration) {
3519 delete node->runtime->declaration;
3520 }
3521 }
3522
3523 MEM_delete(node->runtime);
3524 MEM_freeN(node);
3525
3526 if (ntree) {
3528 }
3529}
3530
3532{
3533 /* For removing nodes while editing localized node trees. */
3534 BLI_assert((ntree->id.tag & ID_TAG_LOCALIZED) != 0);
3535
3536 /* These two lines assume the caller might want to free a single node and maintain
3537 * a valid state in the node tree. */
3538 node_unlink_node(ntree, node);
3539 node_unlink_attached(ntree, node);
3540
3541 node_free_node(ntree, node);
3543}
3544
3545void node_remove_node(Main *bmain, bNodeTree *ntree, bNode *node, const bool do_id_user)
3546{
3547 BLI_assert(ntree != nullptr);
3548 /* This function is not for localized node trees, we do not want
3549 * do to ID user reference-counting and removal of animation data then. */
3550 BLI_assert((ntree->id.tag & ID_TAG_LOCALIZED) == 0);
3551
3552 bool node_has_id = false;
3553
3554 if (do_id_user) {
3555 /* Free callback for NodeCustomGroup. */
3556 if (node->typeinfo->freefunc_api) {
3557 PointerRNA ptr = RNA_pointer_create(&ntree->id, &RNA_Node, node);
3558
3559 node->typeinfo->freefunc_api(&ptr);
3560 }
3561
3562 /* Do user counting. */
3563 if (node->id) {
3564 id_us_min(node->id);
3565 node_has_id = true;
3566 }
3567
3568 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
3569 node_has_id |= socket_id_user_decrement(sock);
3570 }
3571 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
3572 node_has_id |= socket_id_user_decrement(sock);
3573 }
3574 }
3575
3576 /* Remove animation data. */
3577 char propname_esc[MAX_IDPROP_NAME * 2];
3578 char prefix[MAX_IDPROP_NAME * 2];
3579
3580 BLI_str_escape(propname_esc, node->name, sizeof(propname_esc));
3581 SNPRINTF(prefix, "nodes[\"%s\"]", propname_esc);
3582
3583 if (BKE_animdata_fix_paths_remove(&ntree->id, prefix)) {
3584 if (bmain != nullptr) {
3586 }
3587 }
3588
3589 /* Also update relations for the scene time node, which causes a dependency
3590 * on time that users expect to be removed when the node is removed. */
3591 if (node_has_id ||
3592 ELEM(node->type, GEO_NODE_INPUT_SCENE_TIME, GEO_NODE_SELF_OBJECT, GEO_NODE_SIMULATION_INPUT))
3593 {
3594 if (bmain != nullptr) {
3596 }
3597 }
3598
3599 node_unlink_node(ntree, node);
3600 node_unlink_attached(ntree, node);
3601
3602 /* Free node itself. */
3603 node_free_node(ntree, node);
3605}
3606
3608{
3609 /* Only localized node trees store a copy for each node group tree.
3610 * Each node group tree in a localized node tree can be freed,
3611 * since it is a localized copy itself (no risk of accessing freed
3612 * data in main, see #37939). */
3613 if (!(ntree->id.tag & ID_TAG_LOCALIZED)) {
3614 return;
3615 }
3616
3617 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3618 bNodeTree *ngroup = reinterpret_cast<bNodeTree *>(node->id);
3619 if (node->is_group() && ngroup != nullptr) {
3620 node_tree_free_tree(ngroup);
3621 MEM_freeN(ngroup);
3622 }
3623 }
3624}
3625
3627{
3628 ntree_free_data(&ntree->id);
3629 BKE_animdata_free(&ntree->id, false);
3630}
3631
3633{
3634 node_tree_free_tree(ntree);
3635 BKE_libblock_free_data(&ntree->id, true);
3637}
3638
3640{
3641 if (ntree->id.tag & ID_TAG_LOCALIZED) {
3642 node_tree_free_tree(ntree);
3643 }
3644 else {
3645 node_tree_free_tree(ntree);
3646 BKE_libblock_free_data(&ntree->id, true);
3647 }
3648}
3649
3651{
3652 const bool is_compositor = ntree->type == NTREE_COMPOSIT;
3653 /* find the active outputs, might become tree type dependent handler */
3654 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3655 if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
3656 /* we need a check for which output node should be tagged like this, below an exception */
3657 if (ELEM(node->type, CMP_NODE_OUTPUT_FILE, GEO_NODE_VIEWER)) {
3658 continue;
3659 }
3660 const bool node_is_output = node->type == CMP_NODE_VIEWER;
3661
3662 int output = 0;
3663 /* there is more types having output class, each one is checked */
3664
3665 LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
3666 if (tnode->typeinfo->nclass != NODE_CLASS_OUTPUT) {
3667 continue;
3668 }
3669
3670 /* same type, exception for viewer */
3671 const bool tnode_is_output = tnode->type == CMP_NODE_VIEWER;
3672 const bool compositor_case = is_compositor && tnode_is_output && node_is_output;
3673 if (tnode->type == node->type || compositor_case) {
3674 if (tnode->flag & NODE_DO_OUTPUT) {
3675 output++;
3676 if (output > 1) {
3677 tnode->flag &= ~NODE_DO_OUTPUT;
3678 }
3679 }
3680 }
3681 }
3682
3683 if (output == 0) {
3684 node->flag |= NODE_DO_OUTPUT;
3685 }
3686 }
3687
3688 /* group node outputs use this flag too */
3689 if (node->type == NODE_GROUP_OUTPUT) {
3690 int output = 0;
3691 LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
3692 if (tnode->type != NODE_GROUP_OUTPUT) {
3693 continue;
3694 }
3695 if (tnode->flag & NODE_DO_OUTPUT) {
3696 output++;
3697 if (output > 1) {
3698 tnode->flag &= ~NODE_DO_OUTPUT;
3699 }
3700 }
3701 }
3702 if (output == 0) {
3703 node->flag |= NODE_DO_OUTPUT;
3704 }
3705 }
3706 }
3707
3708 /* here we could recursively set which nodes have to be done,
3709 * might be different for editor or for "real" use... */
3710}
3711
3713{
3714 switch (GS(id->name)) {
3715 case ID_MA:
3716 return &reinterpret_cast<Material *>(id)->nodetree;
3717 case ID_LA:
3718 return &reinterpret_cast<Light *>(id)->nodetree;
3719 case ID_WO:
3720 return &reinterpret_cast<World *>(id)->nodetree;
3721 case ID_TE:
3722 return &reinterpret_cast<Tex *>(id)->nodetree;
3723 case ID_SCE:
3724 return &reinterpret_cast<Scene *>(id)->nodetree;
3725 case ID_LS:
3726 return &reinterpret_cast<FreestyleLineStyle *>(id)->nodetree;
3727 default:
3728 return nullptr;
3729 }
3730}
3731
3733{
3734 bNodeTree **nodetree = node_tree_ptr_from_id(id);
3735 return (nodetree != nullptr) ? *nodetree : nullptr;
3736}
3737
3738void node_tree_node_flag_set(const bNodeTree *ntree, const int flag, const bool enable)
3739{
3740 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
3741 if (enable) {
3742 node->flag |= flag;
3743 }
3744 else {
3745 node->flag &= ~flag;
3746 }
3747 }
3748}
3749
3751{
3752 if (ntree == nullptr) {
3753 return nullptr;
3754 }
3755
3756 /* Make full copy outside of Main database.
3757 * NOTE: previews are not copied here. */
3758 bNodeTree *ltree = reinterpret_cast<bNodeTree *>(
3759 BKE_id_copy_in_lib(nullptr,
3760 std::nullopt,
3761 &ntree->id,
3762 new_owner_id,
3763 nullptr,
3765
3766 ltree->id.tag |= ID_TAG_LOCALIZED;
3767
3768 LISTBASE_FOREACH (bNode *, node, &ltree->nodes) {
3769 bNodeTree *group = reinterpret_cast<bNodeTree *>(node->id);
3770 if (node->is_group() && group != nullptr) {
3771 node->id = reinterpret_cast<ID *>(node_tree_localize(group, nullptr));
3772 }
3773 }
3774
3775 /* Ensures only a single output node is enabled. */
3776 node_tree_set_output(ntree);
3777
3778 bNode *node_src = reinterpret_cast<bNode *>(ntree->nodes.first);
3779 bNode *node_local = reinterpret_cast<bNode *>(ltree->nodes.first);
3780 while (node_src != nullptr) {
3781 node_local->runtime->original = node_src;
3782 node_src = node_src->next;
3783 node_local = node_local->next;
3784 }
3785
3786 if (ntree->typeinfo->localize) {
3787 ntree->typeinfo->localize(ltree, ntree);
3788 }
3789
3790 return ltree;
3791}
3792
3793void node_tree_local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
3794{
3795 if (ntree && localtree) {
3796 if (ntree->typeinfo->local_merge) {
3797 ntree->typeinfo->local_merge(bmain, localtree, ntree);
3798 }
3799 }
3800}
3801
3802static bool ntree_contains_tree_exec(const bNodeTree *tree_to_search_in,
3803 const bNodeTree *tree_to_search_for,
3804 Set<const bNodeTree *> &already_passed)
3805{
3806 if (tree_to_search_in == tree_to_search_for) {
3807 return true;
3808 }
3809
3810 tree_to_search_in->ensure_topology_cache();
3811 for (const bNode *node_group : tree_to_search_in->group_nodes()) {
3812 const bNodeTree *sub_tree_search_in = reinterpret_cast<const bNodeTree *>(node_group->id);
3813 if (!sub_tree_search_in) {
3814 continue;
3815 }
3816 if (!already_passed.add(sub_tree_search_in)) {
3817 continue;
3818 }
3819 if (ntree_contains_tree_exec(sub_tree_search_in, tree_to_search_for, already_passed)) {
3820 return true;
3821 }
3822 }
3823
3824 return false;
3825}
3826
3827bool node_tree_contains_tree(const bNodeTree *tree_to_search_in,
3828 const bNodeTree *tree_to_search_for)
3829{
3830 if (tree_to_search_in == tree_to_search_for) {
3831 return true;
3832 }
3833
3834 Set<const bNodeTree *> already_passed;
3835 return ntree_contains_tree_exec(tree_to_search_in, tree_to_search_for, already_passed);
3836}
3837
3838int node_count_socket_links(const bNodeTree *ntree, const bNodeSocket *sock)
3839{
3840 int tot = 0;
3841 LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) {
3842 if (link->fromsock == sock || link->tosock == sock) {
3843 tot++;
3844 }
3845 }
3846 return tot;
3847}
3848
3850{
3851 if (ntree == nullptr) {
3852 return nullptr;
3853 }
3854
3855 for (bNode *node : ntree->all_nodes()) {
3856 if (node->flag & NODE_ACTIVE) {
3857 return node;
3858 }
3859 }
3860 return nullptr;
3861}
3862
3863bool node_set_selected(bNode *node, const bool select)
3864{
3865 bool changed = false;
3866 if (select != ((node->flag & NODE_SELECT) != 0)) {
3867 changed = true;
3869 }
3870 if (select) {
3871 return changed;
3872 }
3873 /* Deselect sockets too. */
3874 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
3875 changed |= (sock->flag & NODE_SELECT) != 0;
3876 sock->flag &= ~NODE_SELECT;
3877 }
3878 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
3879 changed |= (sock->flag & NODE_SELECT) != 0;
3880 sock->flag &= ~NODE_SELECT;
3881 }
3882 return changed;
3883}
3884
3886{
3887 if (ntree == nullptr) {
3888 return;
3889 }
3890
3891 for (bNode *node : ntree->all_nodes()) {
3892 node->flag &= ~NODE_ACTIVE;
3893 }
3894}
3895
3897{
3898 const bool is_paint_canvas = node_supports_active_flag(node, NODE_ACTIVE_PAINT_CANVAS);
3899 const bool is_texture_class = node_supports_active_flag(node, NODE_ACTIVE_TEXTURE);
3900 int flags_to_set = NODE_ACTIVE;
3901 SET_FLAG_FROM_TEST(flags_to_set, is_paint_canvas, NODE_ACTIVE_PAINT_CANVAS);
3902 SET_FLAG_FROM_TEST(flags_to_set, is_texture_class, NODE_ACTIVE_TEXTURE);
3903
3904 /* Make sure only one node is active per node tree. */
3905 for (bNode *tnode : ntree->all_nodes()) {
3906 tnode->flag &= ~flags_to_set;
3907 }
3908 node->flag |= flags_to_set;
3909}
3910
3911void node_set_socket_availability(bNodeTree *ntree, bNodeSocket *sock, const bool is_available)
3912{
3913 if (is_available == sock->is_available()) {
3914 return;
3915 }
3916 if (is_available) {
3917 sock->flag &= ~SOCK_UNAVAIL;
3918 }
3919 else {
3920 sock->flag |= SOCK_UNAVAIL;
3921 }
3923}
3924
3926{
3927 if (sock->is_multi_input()) {
3928 return 4095;
3929 }
3930 if (sock->typeinfo == nullptr) {
3931 return sock->limit;
3932 }
3933 const bNodeSocketType &stype = *sock->typeinfo;
3934 if (!stype.use_link_limits_of_type) {
3935 return sock->limit;
3936 }
3937 return eNodeSocketInOut(sock->in_out) == SOCK_IN ? stype.input_link_limit :
3938 stype.output_link_limit;
3939}
3940
3943{
3944 int index;
3945 LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, index) {
3946 const SocketDeclaration &socket_decl = *declarations[index];
3947 socket->runtime->declaration = &socket_decl;
3948 }
3949}
3950
3952{
3953 LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
3954 socket->runtime->declaration = nullptr;
3955 }
3956}
3957
3959{
3960 BLI_assert(node->runtime->declaration != nullptr);
3961 if (node->runtime->declaration->skip_updating_sockets) {
3962 reset_socket_declarations(&node->inputs);
3963 reset_socket_declarations(&node->outputs);
3964 return;
3965 }
3966 update_socket_declarations(&node->inputs, node->runtime->declaration->inputs);
3967 update_socket_declarations(&node->outputs, node->runtime->declaration->outputs);
3968}
3969
3971{
3972 if (node->runtime->declaration != nullptr) {
3973 return false;
3974 }
3975 if (node->typeinfo->declare) {
3976 if (node->typeinfo->static_declaration) {
3977 if (!node->typeinfo->static_declaration->is_context_dependent) {
3978 node->runtime->declaration = node->typeinfo->static_declaration;
3979 return true;
3980 }
3981 }
3982 }
3983 if (node->typeinfo->declare) {
3984 BLI_assert(ntree != nullptr);
3985 BLI_assert(node != nullptr);
3987 return true;
3988 }
3989 return false;
3990}
3991
3993{
3996 return true;
3997 }
3998 return false;
3999}
4000
4001void node_dimensions_get(const bNode *node, float *r_width, float *r_height)
4002{
4003 *r_width = node->runtime->totr.xmax - node->runtime->totr.xmin;
4004 *r_height = node->runtime->totr.ymax - node->runtime->totr.ymin;
4005}
4006
4008{
4009 node->runtime->update |= NODE_UPDATE_ID;
4010}
4011
4012void node_internal_links(bNode *node, bNodeLink **r_links, int *r_len)
4013{
4014 *r_links = node->runtime->internal_links.data();
4015 *r_len = node->runtime->internal_links.size();
4016}
4017
4018/* Node Instance Hash */
4019
4022
4023/* Generate a hash key from ntree and node names
4024 * Uses the djb2 algorithm with xor by Bernstein:
4025 * http://www.cse.yorku.ca/~oz/hash.html
4026 */
4028{
4029 char c;
4030
4031 while ((c = *str++)) {
4032 hash.value = ((hash.value << 5) + hash.value) ^ c; /* (hash * 33) ^ c */
4033 }
4034
4035 /* separator '\0' character, to avoid ambiguity from concatenated strings */
4036 hash.value = (hash.value << 5) + hash.value; /* hash * 33 */
4037
4038 return hash;
4039}
4040
4042 const bNodeTree *ntree,
4043 const bNode *node)
4044{
4045 bNodeInstanceKey key = node_hash_int_str(parent_key, ntree->id.name + 2);
4046
4047 if (node) {
4048 key = node_hash_int_str(key, node->name);
4049 }
4050
4051 return key;
4052}
4053
4054static uint node_instance_hash_key(const void *key)
4055{
4056 return static_cast<const bNodeInstanceKey *>(key)->value;
4057}
4058
4059static bool node_instance_hash_key_cmp(const void *a, const void *b)
4060{
4061 uint value_a = static_cast<const bNodeInstanceKey *>(a)->value;
4062 uint value_b = static_cast<const bNodeInstanceKey *>(b)->value;
4063
4064 return (value_a != value_b);
4065}
4066
4068{
4069 bNodeInstanceHash *hash = static_cast<bNodeInstanceHash *>(
4070 MEM_mallocN(sizeof(bNodeInstanceHash), info));
4072 node_instance_hash_key, node_instance_hash_key_cmp, "node instance hash ghash");
4073 return hash;
4074}
4075
4077{
4078 BLI_ghash_free(hash->ghash, nullptr, reinterpret_cast<GHashValFreeFP>(valfreefp));
4079 MEM_freeN(hash);
4080}
4081
4083{
4084 bNodeInstanceHashEntry *entry = static_cast<bNodeInstanceHashEntry *>(value);
4085 entry->key = key;
4086 entry->tag = 0;
4087 BLI_ghash_insert(hash->ghash, &entry->key, value);
4088}
4089
4091{
4092 return BLI_ghash_lookup(hash->ghash, &key);
4093}
4094
4096 bNodeInstanceKey key,
4097 bNodeInstanceValueFP valfreefp)
4098{
4099 return BLI_ghash_remove(hash->ghash, &key, nullptr, reinterpret_cast<GHashValFreeFP>(valfreefp));
4100}
4101
4103{
4104 BLI_ghash_clear(hash->ghash, nullptr, reinterpret_cast<GHashValFreeFP>(valfreefp));
4105}
4106
4108{
4109 return BLI_ghash_popkey(hash->ghash, &key, nullptr);
4110}
4111
4116
4118{
4119 return BLI_ghash_len(hash->ghash);
4120}
4121
4123{
4125
4127 bNodeInstanceHashEntry *value = static_cast<bNodeInstanceHashEntry *>(
4129
4130 value->tag = 0;
4131 }
4132}
4133
4134void node_instance_hash_tag(bNodeInstanceHash * /*hash*/, void *value)
4135{
4136 bNodeInstanceHashEntry *entry = static_cast<bNodeInstanceHashEntry *>(value);
4137 entry->tag = 1;
4138}
4139
4141{
4142 bNodeInstanceHashEntry *entry = static_cast<bNodeInstanceHashEntry *>(
4144
4145 if (entry) {
4146 entry->tag = 1;
4147 return true;
4148 }
4149
4150 return false;
4151}
4152
4154{
4155 /* NOTE: Hash must not be mutated during iterating!
4156 * Store tagged entries in a separate list and remove items afterward.
4157 */
4158 bNodeInstanceKey *untagged = static_cast<bNodeInstanceKey *>(
4160 "temporary node instance key list"));
4162 int num_untagged = 0;
4164 bNodeInstanceHashEntry *value = static_cast<bNodeInstanceHashEntry *>(
4166
4167 if (!value->tag) {
4168 untagged[num_untagged++] = node_instance_hash_iterator_get_key(&iter);
4169 }
4170 }
4171
4172 for (int i = 0; i < num_untagged; i++) {
4173 node_instance_hash_remove(hash, untagged[i], valfreefp);
4174 }
4175
4176 MEM_freeN(untagged);
4177}
4178
4179/* Build a set of built-in node types to check for known types. */
4181{
4183 NODE_TYPES_BEGIN (ntype) {
4184 result.add(ntype->type);
4185 }
4187 return result;
4188}
4189
4190static bool can_read_node_type(const int type)
4191{
4192 /* Can always read custom node types. */
4193 if (ELEM(type, NODE_CUSTOM, NODE_CUSTOM_GROUP)) {
4194 return true;
4195 }
4196
4197 /* Check known built-in types. */
4198 static Set<int> known_types = get_known_node_types_set();
4199 return known_types.contains(type);
4200}
4201
4203{
4204 /* If the integer type is unknown then this node cannot be read. */
4205 if (!can_read_node_type(node->type)) {
4206 node->type = NODE_CUSTOM;
4207 /* This type name is arbitrary, it just has to be unique enough to not match a future node
4208 * idname. Includes the old type identifier for debugging purposes. */
4209 const std::string old_idname = node->idname;
4210 SNPRINTF(node->idname, "Undefined[%s]", old_idname.c_str());
4211 node->typeinfo = &NodeTypeUndefined;
4212 }
4213}
4214
4216{
4217 /* Replace unknown node types with "Undefined".
4218 * This happens when loading files from newer Blender versions. Such nodes cannot be read
4219 * reliably so replace the idname with an undefined type. This keeps links and socket names but
4220 * discards storage and other type-specific data.
4221 *
4222 * Replacement has to happen after after-liblink-versioning, since some node types still get
4223 * replaced in those late versioning steps. */
4224 FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
4225 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
4227 }
4228 }
4230 /* Update all new node trees on file read or append, to add/remove sockets
4231 * in groups nodes if the group changed, and handle any update flags that
4232 * might have been set in file reading or versioning. */
4233 FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
4234 if (owner_id->tag & ID_TAG_NEW) {
4236 }
4237 }
4239 BKE_ntree_update_main(main, nullptr);
4240}
4241
4243{
4244 if (id == nullptr) {
4245 return;
4246 }
4247
4248 bool need_update = false;
4249
4250 /* Update all users of ngroup, to add/remove sockets as needed. */
4251 FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
4252 for (bNode *node : ntree->all_nodes()) {
4253 if (node->id == id) {
4255 need_update = true;
4256 }
4257 }
4258 }
4260 if (need_update) {
4261 BKE_ntree_update_main(main, nullptr);
4262 }
4263}
4264
4265/* ************* node type access ********** */
4266
4267void nodeLabel(const bNodeTree *ntree, const bNode *node, char *label, const int label_maxncpy)
4268{
4269 label[0] = '\0';
4270
4271 if (node->label[0] != '\0') {
4272 BLI_strncpy(label, node->label, label_maxncpy);
4273 }
4274 else if (node->typeinfo->labelfunc) {
4275 node->typeinfo->labelfunc(ntree, node, label, label_maxncpy);
4276 }
4277 if (label[0] != '\0') {
4278 /* The previous methods (labelfunc) could not provide an adequate label for the node. */
4279 return;
4280 }
4281
4282 BLI_strncpy(label, IFACE_(node->typeinfo->ui_name), label_maxncpy);
4283}
4284
4285const char *nodeSocketShortLabel(const bNodeSocket *sock)
4286{
4287 if (sock->runtime->declaration != nullptr) {
4288 StringRefNull short_label = sock->runtime->declaration->short_label;
4289 if (!short_label.is_empty()) {
4290 return sock->runtime->declaration->short_label.data();
4291 }
4292 }
4293 return nullptr;
4294}
4295
4296const char *nodeSocketLabel(const bNodeSocket *sock)
4297{
4298 return (sock->label[0] != '\0') ? sock->label : sock->name;
4299}
4300
4302{
4303 /* default size values */
4305 ntype->height = 100;
4306 ntype->minheight = 30;
4307 ntype->maxheight = FLT_MAX;
4308}
4309
4310/* allow this node for any tree type */
4311static bool node_poll_default(const bNodeType * /*ntype*/,
4312 const bNodeTree * /*ntree*/,
4313 const char ** /*r_disabled_hint*/)
4314{
4315 return true;
4316}
4317
4318static bool node_poll_instance_default(const bNode *node,
4319 const bNodeTree *ntree,
4320 const char **r_disabled_hint)
4321{
4322 return node->typeinfo->poll(node->typeinfo, ntree, r_disabled_hint);
4323}
4324
4325void node_type_base(bNodeType *ntype, const int type, const char *name, const short nclass)
4326{
4327 /* Use static type info header to map static int type to identifier string and RNA struct type.
4328 * Associate the RNA struct type with the bNodeType.
4329 * Dynamically registered nodes will create an RNA type at runtime
4330 * and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types
4331 * created in makesrna, which can not be associated to a bNodeType immediately,
4332 * since bNodeTypes are registered afterward ...
4333 */
4334#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
4335 case ID: { \
4336 STRNCPY(ntype->idname, #Category #StructName); \
4337 StructRNA *srna = RNA_struct_find(#Category #StructName); \
4338 BLI_assert(srna != nullptr); \
4339 ntype->rna_ext.srna = srna; \
4340 RNA_struct_blender_type_set(srna, ntype); \
4341 RNA_def_struct_ui_text(srna, UIName, UIDesc); \
4342 ntype->enum_name_legacy = EnumName; \
4343 STRNCPY(ntype->ui_description, UIDesc); \
4344 break; \
4345 }
4346
4347 switch (type) {
4348#include "NOD_static_types.h"
4349 }
4350
4351 /* make sure we have a valid type (everything registered) */
4352 BLI_assert(ntype->idname[0] != '\0');
4353
4354 ntype->type = type;
4355 STRNCPY(ntype->ui_name, name);
4356 ntype->nclass = nclass;
4357
4359
4360 ntype->poll = node_poll_default;
4362}
4363
4365 const char *idname,
4366 const char *name,
4367 const char *enum_name,
4368 const short nclass)
4369{
4370 STRNCPY(ntype->idname, idname);
4371 ntype->type = NODE_CUSTOM;
4372 STRNCPY(ntype->ui_name, name);
4373 ntype->nclass = nclass;
4374 ntype->enum_name_legacy = enum_name;
4375
4377}
4378
4379std::optional<eCustomDataType> socket_type_to_custom_data_type(eNodeSocketDatatype type)
4380{
4381 switch (type) {
4382 case SOCK_FLOAT:
4383 return CD_PROP_FLOAT;
4384 case SOCK_VECTOR:
4385 return CD_PROP_FLOAT3;
4386 case SOCK_RGBA:
4387 return CD_PROP_COLOR;
4388 case SOCK_BOOLEAN:
4389 return CD_PROP_BOOL;
4390 case SOCK_ROTATION:
4391 return CD_PROP_QUATERNION;
4392 case SOCK_MATRIX:
4393 return CD_PROP_FLOAT4X4;
4394 case SOCK_INT:
4395 return CD_PROP_INT32;
4396 case SOCK_STRING:
4397 return CD_PROP_STRING;
4398 default:
4399 return std::nullopt;
4400 }
4401}
4402
4403std::optional<eNodeSocketDatatype> custom_data_type_to_socket_type(eCustomDataType type)
4404{
4405 switch (type) {
4406 case CD_PROP_FLOAT:
4407 return SOCK_FLOAT;
4408 case CD_PROP_INT8:
4409 return SOCK_INT;
4410 case CD_PROP_INT32:
4411 return SOCK_INT;
4412 case CD_PROP_FLOAT3:
4413 return SOCK_VECTOR;
4414 case CD_PROP_FLOAT2:
4415 return SOCK_VECTOR;
4416 case CD_PROP_BOOL:
4417 return SOCK_BOOLEAN;
4418 case CD_PROP_COLOR:
4419 return SOCK_RGBA;
4420 case CD_PROP_BYTE_COLOR:
4421 return SOCK_RGBA;
4422 case CD_PROP_QUATERNION:
4423 return SOCK_ROTATION;
4424 case CD_PROP_FLOAT4X4:
4425 return SOCK_MATRIX;
4426 default:
4427 return std::nullopt;
4428 }
4429}
4430
4432{
4433 const char *socket_idname = node_static_socket_type(type, 0);
4434 const bNodeSocketType *typeinfo = node_socket_type_find(socket_idname);
4435 return typeinfo->base_cpp_type;
4436}
4437
4439{
4440 const CPPType *cpp_type;
4441 switch (type) {
4442 case SOCK_FLOAT:
4443 cpp_type = &CPPType::get<float>();
4444 break;
4445 case SOCK_INT:
4446 cpp_type = &CPPType::get<int>();
4447 break;
4448 case SOCK_RGBA:
4449 cpp_type = &CPPType::get<ColorGeometry4f>();
4450 break;
4451 case SOCK_BOOLEAN:
4452 cpp_type = &CPPType::get<bool>();
4453 break;
4454 case SOCK_VECTOR:
4455 cpp_type = &CPPType::get<float3>();
4456 break;
4457 case SOCK_ROTATION:
4458 cpp_type = &CPPType::get<math::Quaternion>();
4459 break;
4460 case SOCK_MATRIX:
4461 cpp_type = &CPPType::get<float4x4>();
4462 break;
4463 default:
4465 break;
4466 }
4468 return cpp_type;
4469}
4470
4471std::optional<eNodeSocketDatatype> geo_nodes_base_cpp_type_to_socket_type(const CPPType &type)
4472{
4473 if (type.is<float>()) {
4474 return SOCK_FLOAT;
4475 }
4476 if (type.is<int>()) {
4477 return SOCK_INT;
4478 }
4479 if (type.is<float3>()) {
4480 return SOCK_VECTOR;
4481 }
4482 if (type.is<ColorGeometry4f>()) {
4483 return SOCK_RGBA;
4484 }
4485 if (type.is<bool>()) {
4486 return SOCK_BOOLEAN;
4487 }
4488 if (type.is<math::Quaternion>()) {
4489 return SOCK_ROTATION;
4490 }
4491 if (type.is<float4x4>()) {
4492 return SOCK_MATRIX;
4493 }
4494 if (type.is<std::string>()) {
4495 return SOCK_STRING;
4496 }
4497 return std::nullopt;
4498}
4499
4500std::optional<VolumeGridType> socket_type_to_grid_type(const eNodeSocketDatatype type)
4501{
4502 switch (type) {
4503 case SOCK_BOOLEAN:
4504 return VOLUME_GRID_BOOLEAN;
4505 case SOCK_FLOAT:
4506 return VOLUME_GRID_FLOAT;
4507 case SOCK_INT:
4508 return VOLUME_GRID_INT;
4509 case SOCK_VECTOR:
4511 default:
4512 return std::nullopt;
4513 }
4514}
4515
4516std::optional<eNodeSocketDatatype> grid_type_to_socket_type(const VolumeGridType type)
4517{
4518 switch (type) {
4520 return SOCK_BOOLEAN;
4521 case VOLUME_GRID_FLOAT:
4522 return SOCK_FLOAT;
4523 case VOLUME_GRID_INT:
4524 return SOCK_INT;
4526 return SOCK_VECTOR;
4527 default:
4528 return std::nullopt;
4529 }
4530}
4531
4536
4537static bool unique_socket_template_identifier_check(void *arg, const char *name)
4538{
4540 static_cast<const SocketTemplateIdentifierCallbackData *>(arg);
4541
4542 for (bNodeSocketTemplate *ntemp = data->list; ntemp->type >= 0; ntemp++) {
4543 if (ntemp != data->ntemp) {
4544 if (STREQ(ntemp->identifier, name)) {
4545 return true;
4546 }
4547 }
4548 }
4549
4550 return false;
4551}
4552
4554 bNodeSocketTemplate *ntemp,
4555 const char defname[],
4556 const char delim)
4557{
4559 data.list = list;
4560 data.ntemp = ntemp;
4561
4563 &data,
4564 defname,
4565 delim,
4566 ntemp->identifier,
4567 sizeof(ntemp->identifier));
4568}
4569
4571 bNodeSocketTemplate *inputs,
4572 bNodeSocketTemplate *outputs)
4573{
4574 ntype->inputs = inputs;
4575 ntype->outputs = outputs;
4576
4577 /* automatically generate unique identifiers */
4578 if (inputs) {
4579 /* clear identifier strings (uninitialized memory) */
4580 for (bNodeSocketTemplate *ntemp = inputs; ntemp->type >= 0; ntemp++) {
4581 ntemp->identifier[0] = '\0';
4582 }
4583
4584 for (bNodeSocketTemplate *ntemp = inputs; ntemp->type >= 0; ntemp++) {
4585 STRNCPY(ntemp->identifier, ntemp->name);
4586 unique_socket_template_identifier(inputs, ntemp, ntemp->identifier, '_');
4587 }
4588 }
4589 if (outputs) {
4590 /* clear identifier strings (uninitialized memory) */
4591 for (bNodeSocketTemplate *ntemp = outputs; ntemp->type >= 0; ntemp++) {
4592 ntemp->identifier[0] = '\0';
4593 }
4594
4595 for (bNodeSocketTemplate *ntemp = outputs; ntemp->type >= 0; ntemp++) {
4596 STRNCPY(ntemp->identifier, ntemp->name);
4597 unique_socket_template_identifier(outputs, ntemp, ntemp->identifier, '_');
4598 }
4599 }
4600}
4601
4602void node_type_size(bNodeType *ntype, const int width, const int minwidth, const int maxwidth)
4603{
4604 ntype->width = width;
4605 ntype->minwidth = minwidth;
4606 if (maxwidth <= minwidth) {
4607 ntype->maxwidth = FLT_MAX;
4608 }
4609 else {
4610 ntype->maxwidth = maxwidth;
4611 }
4612}
4613
4615{
4616 switch (size) {
4618 node_type_size(ntype, 140, 100, NODE_DEFAULT_MAX_WIDTH);
4619 break;
4621 node_type_size(ntype, 100, 80, NODE_DEFAULT_MAX_WIDTH);
4622 break;
4624 node_type_size(ntype, 150, 120, NODE_DEFAULT_MAX_WIDTH);
4625 break;
4627 node_type_size(ntype, 240, 140, NODE_DEFAULT_MAX_WIDTH);
4628 break;
4629 }
4630}
4631
4633 const char *storagename,
4634 void (*freefunc)(bNode *node),
4635 void (*copyfunc)(bNodeTree *dest_ntree,
4636 bNode *dest_node,
4637 const bNode *src_node))
4638{
4639 if (storagename) {
4640 STRNCPY(ntype->storagename, storagename);
4641 }
4642 else {
4643 ntype->storagename[0] = '\0';
4644 }
4645 ntype->copyfunc = copyfunc;
4646 ntype->freefunc = freefunc;
4647}
4648
4650{
4651 nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh");
4652 nodetypes_hash = BLI_ghash_str_new("nodetypes_hash gh");
4653 nodetypes_alias_hash = BLI_ghash_str_new("nodetypes_alias_hash gh");
4654 nodesockettypes_hash = BLI_ghash_str_new("nodesockettypes_hash gh");
4655
4657}
4658
4660{
4663 nodetypes_alias_hash = nullptr;
4664 }
4665
4666 if (nodetypes_hash) {
4667 NODE_TYPES_BEGIN (nt) {
4668 if (nt->rna_ext.free) {
4669 nt->rna_ext.free(nt->rna_ext.data);
4670 }
4671 }
4673
4675 nodetypes_hash = nullptr;
4676 }
4677
4680 if (st->ext_socket.free) {
4681 st->ext_socket.free(st->ext_socket.data);
4682 }
4683 if (st->ext_interface.free) {
4684 st->ext_interface.free(st->ext_interface.data);
4685 }
4686 }
4688
4690 nodesockettypes_hash = nullptr;
4691 }
4692
4693 if (nodetreetypes_hash) {
4695 if (nt->rna_ext.free) {
4696 nt->rna_ext.free(nt->rna_ext.data);
4697 }
4698 }
4700
4702 nodetreetypes_hash = nullptr;
4703 }
4704}
4705
4706/* -------------------------------------------------------------------- */
4707/* NodeTree Iterator Helpers (FOREACH_NODETREE_BEGIN) */
4708
4710{
4711 ntreeiter->ngroup = (bNodeTree *)bmain->nodetrees.first;
4712 ntreeiter->scene = (Scene *)bmain->scenes.first;
4713 ntreeiter->mat = (Material *)bmain->materials.first;
4714 ntreeiter->tex = (Tex *)bmain->textures.first;
4715 ntreeiter->light = (Light *)bmain->lights.first;
4716 ntreeiter->world = (World *)bmain->worlds.first;
4717 ntreeiter->linestyle = (FreestyleLineStyle *)bmain->linestyles.first;
4718}
4719bool node_tree_iterator_step(NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, ID **r_id)
4720{
4721 if (ntreeiter->ngroup) {
4722 bNodeTree &node_tree = *reinterpret_cast<bNodeTree *>(ntreeiter->ngroup);
4723 *r_nodetree = &node_tree;
4724 *r_id = &node_tree.id;
4725 ntreeiter->ngroup = reinterpret_cast<bNodeTree *>(node_tree.id.next);
4726 }
4727 else if (ntreeiter->scene) {
4728 *r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->scene->nodetree);
4729 *r_id = &ntreeiter->scene->id;
4730 ntreeiter->scene = reinterpret_cast<Scene *>(ntreeiter->scene->id.next);
4731 }
4732 else if (ntreeiter->mat) {
4733 *r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->mat->nodetree);
4734 *r_id = &ntreeiter->mat->id;
4735 ntreeiter->mat = reinterpret_cast<Material *>(ntreeiter->mat->id.next);
4736 }
4737 else if (ntreeiter->tex) {
4738 *r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->tex->nodetree);
4739 *r_id = &ntreeiter->tex->id;
4740 ntreeiter->tex = reinterpret_cast<Tex *>(ntreeiter->tex->id.next);
4741 }
4742 else if (ntreeiter->light) {
4743 *r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->light->nodetree);
4744 *r_id = &ntreeiter->light->id;
4745 ntreeiter->light = reinterpret_cast<Light *>(ntreeiter->light->id.next);
4746 }
4747 else if (ntreeiter->world) {
4748 *r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->world->nodetree);
4749 *r_id = &ntreeiter->world->id;
4750 ntreeiter->world = reinterpret_cast<World *>(ntreeiter->world->id.next);
4751 }
4752 else if (ntreeiter->linestyle) {
4753 *r_nodetree = reinterpret_cast<bNodeTree *>(ntreeiter->linestyle->nodetree);
4754 *r_id = &ntreeiter->linestyle->id;
4755 ntreeiter->linestyle = reinterpret_cast<FreestyleLineStyle *>(ntreeiter->linestyle->id.next);
4756 }
4757 else {
4758 return false;
4759 }
4760
4761 return true;
4762}
4763
4764void node_tree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
4765{
4766 BLI_assert(layer_index != -1);
4767 BLI_assert(scene != nullptr);
4768 for (bNode *node : ntree->all_nodes()) {
4769 if (node->type == CMP_NODE_R_LAYERS && node->id == &scene->id) {
4770 if (node->custom1 == layer_index) {
4771 node->custom1 = 0;
4772 }
4773 else if (node->custom1 > layer_index) {
4774 node->custom1--;
4775 }
4776 }
4777 }
4778}
4779
4780} // namespace blender::bke
void BKE_animdata_free(ID *id, bool do_id_user)
Definition anim_data.cc:263
bool BKE_animdata_fix_paths_remove(struct ID *id, const char *prefix)
void BKE_asset_metadata_idprop_ensure(AssetMetaData *asset_data, IDProperty *prop)
Definition asset.cc:175
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:123
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap)
Main * CTX_data_main(const bContext *C)
#define G_MAIN
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
#define IDP_BlendDataRead(reader, prop)
void IDP_FreePropertyContent_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1189
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:722
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:843
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:861
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1437
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1221
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:39
void(*)(ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data) IDTypeForeachCacheFunctionCallback
Definition BKE_idtype.hh:98
void BKE_image_format_blend_write(BlendWriter *writer, ImageFormatData *imf)
void BKE_image_format_blend_read_data(BlendDataReader *reader, ImageFormatData *imf)
void BKE_libblock_free_data_py(ID *id)
@ LIB_ID_COPY_NO_PREVIEW
@ LIB_ID_COPY_LOCALIZE
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_COPY_NO_ANIMDATA
@ LIB_ID_CREATE_NO_MAIN
void id_us_plus(ID *id)
Definition lib_id.cc:351
void BKE_libblock_free_data(ID *id, bool do_id_user) ATTR_NONNULL()
void BKE_libblock_init_empty(ID *id) ATTR_NONNULL(1)
Definition lib_id.cc:1420
struct ID * BKE_id_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, const ID *new_owner_id, ID **new_id_p, int flag)
Definition lib_id.cc:656
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:760
void id_us_min(ID *id)
Definition lib_id.cc:359
void * BKE_libblock_alloc_in_lib(Main *bmain, std::optional< Library * > owner_library, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1321
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_NEVER_SELF
@ IDWALK_CB_USER
@ IDWALK_CB_READFILE_IGNORE
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
#define NODE_TYPES_BEGIN(ntype)
Definition BKE_node.hh:597
#define NODE_CLASS_OUTPUT
Definition BKE_node.hh:405
#define SH_NODE_CURVE_FLOAT
Definition BKE_node.hh:992
#define NODE_REROUTE
Definition BKE_node.hh:804
#define CMP_NODE_TIME
Definition BKE_node.hh:1025
#define GEO_NODE_MENU_SWITCH
Definition BKE_node.hh:1354
#define CMP_NODE_VIEWER
Definition BKE_node.hh:1012
constexpr int GROUP_NODE_DEFAULT_WIDTH
Definition BKE_node.hh:1810
#define SH_NODE_TEX_IMAGE
Definition BKE_node.hh:930
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:807
#define CMP_NODE_CRYPTOMATTE
Definition BKE_node.hh:1111
#define FN_NODE_INPUT_COLOR
Definition BKE_node.hh:1401
#define FN_NODE_INPUT_VECTOR
Definition BKE_node.hh:1391
#define SH_NODE_TEX_ENVIRONMENT
Definition BKE_node.hh:940
#define SH_NODE_VALUE
Definition BKE_node.hh:892
#define SH_NODE_CURVE_VEC
Definition BKE_node.hh:901
#define NODE_CUSTOM
Definition BKE_node.hh:799
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT
Definition BKE_node.hh:1379
#define CMP_NODE_HUECORRECT
Definition BKE_node.hh:1073
#define SH_NODE_TEX_IES
Definition BKE_node.hh:977
#define FN_NODE_INPUT_STRING
Definition BKE_node.hh:1392
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define GEO_NODE_SIMULATION_OUTPUT
Definition BKE_node.hh:1331
#define FN_NODE_INPUT_INT
Definition BKE_node.hh:1404
#define FN_NODE_INPUT_BOOL
Definition BKE_node.hh:1403
#define CMP_NODE_CRYPTOMATTE_LEGACY
Definition BKE_node.hh:1108
#define TEX_NODE_IMAGE
Definition BKE_node.hh:1143
constexpr int NODE_DEFAULT_MAX_WIDTH
Definition BKE_node.hh:1809
#define CMP_NODE_OUTPUT_FILE
Definition BKE_node.hh:1034
#define FOREACH_NODETREE_END
Definition BKE_node.hh:870
#define NODE_TREE_TYPES_BEGIN(ntype)
Definition BKE_node.hh:499
#define CMP_NODE_CURVE_RGB
Definition BKE_node.hh:1020
#define NODE_SOCKET_TYPES_BEGIN(stype)
Definition BKE_node.hh:623
#define SH_NODE_TEX_POINTDENSITY
Definition BKE_node.hh:975
#define GEO_NODE_BAKE
Definition BKE_node.hh:1350
#define SH_NODE_CURVE_RGB
Definition BKE_node.hh:902
#define GEO_NODE_IMAGE
Definition BKE_node.hh:1320
#define GEO_NODE_CAPTURE_ATTRIBUTE
Definition BKE_node.hh:1210
#define NODE_INSTANCE_HASH_ITER(iter_, hash_)
Definition BKE_node.hh:1677
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition BKE_node.hh:860
#define TEX_NODE_CURVE_TIME
Definition BKE_node.hh:1147
#define NODE_TREE_TYPES_END
Definition BKE_node.hh:508
#define GEO_NODE_REPEAT_OUTPUT
Definition BKE_node.hh:1338
#define NODE_FRAME
Definition BKE_node.hh:803
#define CMP_NODE_R_LAYERS
Definition BKE_node.hh:1032
#define NODE_SOCKET_TYPES_END
Definition BKE_node.hh:632
#define CMP_NODE_CURVE_VEC
Definition BKE_node.hh:1019
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#define NODE_TYPES_END
Definition BKE_node.hh:605
#define CMP_NODE_IMAGE
Definition BKE_node.hh:1031
#define SH_NODE_SCRIPT
Definition BKE_node.hh:954
#define TEX_NODE_CURVE_RGB
Definition BKE_node.hh:1144
#define GEO_NODE_INDEX_SWITCH
Definition BKE_node.hh:1348
void BKE_ntree_update_tag_node_new(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_socket_type(bNodeTree *ntree, bNodeSocket *socket)
void BKE_ntree_update_tag_node_internal_link(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_all(bNodeTree *ntree)
void BKE_ntree_update_tag_link_changed(bNodeTree *ntree)
void BKE_ntree_update_tag_socket_new(bNodeTree *ntree, bNodeSocket *socket)
void BKE_ntree_update_tag_socket_removed(bNodeTree *ntree)
void BKE_ntree_update_main(Main *bmain, NodeTreeUpdateExtraParams *params)
void BKE_ntree_update_tag_missing_runtime_data(bNodeTree *ntree)
void BKE_ntree_update_tag_link_removed(bNodeTree *ntree)
void BKE_ntree_update_tag_socket_availability(bNodeTree *ntree, bNodeSocket *socket)
void BKE_ntree_update_tag_node_removed(bNodeTree *ntree)
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_link_added(bNodeTree *ntree, bNodeLink *link)
void BKE_ntree_update_tag_link_mute(bNodeTree *ntree, bNodeLink *link)
void BKE_ntree_update_tag_parent_change(bNodeTree *ntree, bNode *node)
void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv)
void BKE_previewimg_free(PreviewImage **prv)
void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
VolumeGridType
@ VOLUME_GRID_VECTOR_FLOAT
@ VOLUME_GRID_BOOLEAN
@ VOLUME_GRID_INT
@ VOLUME_GRID_FLOAT
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:819
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:855
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:686
GHashIterator * BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:888
GHash * BLI_ghash_str_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void(* GHashValFreeFP)(void *val)
Definition BLI_ghash.h:39
void * BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:802
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:702
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:787
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.c:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
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
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
Definition string.c:45
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
size_t void BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(1
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
#define UNUSED_VARS_NDEBUG(...)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define STREQ(a, b)
#define BLO_read_data_address(reader, ptr_p)
int BLO_read_fileversion_get(BlendDataReader *reader)
Definition readfile.cc:4898
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
bool BLO_read_lib_is_undo(BlendLibReader *reader)
Definition readfile.cc:5155
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
Definition readfile.cc:4992
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLT_I18NCONTEXT_ID_NODETREE
#define IFACE_(msgid)
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_relations_tag_update(Main *bmain)
#define FILTER_ID_ALL
Definition DNA_ID.h:1206
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
@ ID_FLAG_EMBEDDED_DATA
Definition DNA_ID.h:725
#define MAX_IDPROP_NAME
Definition DNA_ID.h:185
@ ID_TAG_NEW
Definition DNA_ID.h:865
@ ID_TAG_LOCALIZED
Definition DNA_ID.h:954
@ ID_TAG_MISSING
Definition DNA_ID.h:813
@ INDEX_ID_NT
Definition DNA_ID.h:1264
#define FILTER_ID_NT
Definition DNA_ID.h:1180
@ ID_TE
@ ID_NT
@ ID_LA
@ ID_SCE
@ ID_LS
@ ID_WO
@ ID_MA
@ IDP_TYPE_FILTER_ID
Object groups, one object can be in many groups at once.
@ CD_PROP_BYTE_COLOR
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_COLOR
@ CD_PROP_QUATERNION
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_PROP_STRING
@ CD_PROP_FLOAT4X4
#define MAX_NAME
Definition DNA_defs.h:50
@ NODE_INTERFACE_SOCKET_HIDE_IN_MODIFIER
@ NODE_INTERFACE_SOCKET_HIDE_VALUE
@ NTREE_TEXTURE
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
@ NODE_OPTIONS
@ NODE_DO_OUTPUT
@ NODE_ACTIVE
@ NODE_ACTIVE_TEXTURE
@ NODE_INIT
@ NODE_ACTIVE_PAINT_CANVAS
@ NODE_SELECT
@ NODE_PREVIEW
@ NODE_LINK_MUTED
@ NODE_LINK_VALID
@ NODE_UPDATE_ID
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
@ SOCK_HIDE_VALUE
@ SOCK_HIDE_IN_MODIFIER
@ SOCK_COLLAPSED
@ SOCK_UNAVAIL
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
struct bNodeTree bNodeTree
@ CMP_NODE_GLARE_STREAKS
@ CMP_NODE_GLARE_SIMPLE_STAR
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
bool imb_addrectImBuf(ImBuf *ibuf, bool initialize_pixels=true)
void IMB_rect_size_set(ImBuf *ibuf, const uint size[2])
Definition rectop.cc:287
@ IB_rect
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void ntreeShaderEndExecTree(struct bNodeTreeExec *exec)
void ntreeTexEndExecTree(struct bNodeTreeExec *exec)
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
unsigned int U
Definition btGjkEpa3.h:78
static const CPPType & get()
void destruct(void *ptr) const
void value_initialize(void *ptr) const
const Value & lookup(const Key &key) const
Definition BLI_map.hh:506
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:241
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr bool is_empty() const
constexpr const char * data() const
void reserve(const int64_t n)
void add_new(const Key &key)
const Key & lookup_key_as(const ForwardKey &key) const
void append_non_duplicates(const T &value)
std::unique_ptr< anonymous_attribute_inferencing::AnonymousAttributeInferencingResult > anonymous_attribute_inferencing
std::unique_ptr< nodes::FieldInferencingInterface > field_inferencing_interface
local_group_size(16, 16) .push_constant(Type b
OperationNode * node
double time
const char * label
DEGForeachIDComponentCallback callback
#define offsetof(t, d)
KDTree_3d * tree
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
#define str(s)
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
void IMB_freeImBuf(ImBuf *)
int count
#define GS(x)
Definition iris.cc:202
#define LOG(severity)
Definition log.h:33
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
int main()
static void construct_interface_as_legacy_sockets(bNodeTree *ntree)
Definition node.cc:590
static bNodeSocket * make_socket(bNodeTree *ntree, const eNodeSocketInOut in_out, const StringRef idname, const StringRef name, const StringRef identifier)
Definition node.cc:495
static void legacy_socket_interface_free(bNodeSocket *sock)
Definition node.cc:655
static void write_legacy_sockets(BlendWriter *writer, bNodeTree *ntree)
Definition node.cc:644
static void cleanup_legacy_sockets(bNodeTree *ntree)
Definition node.cc:670
static StringRef get_legacy_socket_subtype_idname(StringRef idname, const void *socket_data)
Definition node.cc:525
static void write_node_socket_interface(BlendWriter *writer, const bNodeSocket *sock)
Definition node.cc:481
T & get_item_as(bNodeTreeInterfaceItem &item)
int node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
Definition node.cc:4112
void node_tree_set_output(bNodeTree *ntree)
Definition node.cc:3650
bNodeSocket * node_find_enabled_input_socket(bNode &node, StringRef name)
Definition node.cc:1863
void node_instance_hash_tag(bNodeInstanceHash *hash, void *value)
Definition node.cc:4134
bool node_is_parent_and_child(const bNode *parent, const bNode *child)
Definition node.cc:2491
bNodePreview * node_preview_copy(bNodePreview *preview)
Definition node.cc:3307
int node_instance_hash_size(bNodeInstanceHash *hash)
Definition node.cc:4117
bNodeTree * node_tree_copy_tree_ex(const bNodeTree *ntree, Main *bmain, bool do_id_user)
Definition node.cc:3247
static void node_free_type(void *nodetype_v)
Definition node.cc:1691
static bNodeSocket * make_socket(bNodeTree *ntree, bNode *, const int in_out, ListBase *lb, const char *idname, const char *identifier, const char *name)
Definition node.cc:1884
void node_socket_declarations_update(bNode *node)
Definition node.cc:3958
static bool socket_id_user_decrement(bNodeSocket *sock)
Definition node.cc:1972
void node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value)
Definition node.cc:4082
static ID ** node_owner_pointer_get(ID *id, const bool debug_relationship_assert)
Definition node.cc:462
void node_modify_socket_type_static(bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype)
Definition node.cc:2082
bNodeSocketType NodeSocketTypeUndefined
Definition node.cc:136
std::optional< eNodeSocketDatatype > geo_nodes_base_cpp_type_to_socket_type(const CPPType &type)
Definition node.cc:4471
float2 node_to_view(const bNode *node, float2 loc)
Definition node.cc:3089
void node_tree_remove_layer_n(bNodeTree *ntree, Scene *scene, int layer_index)
Definition node.cc:4764
void node_attach_node(bNodeTree *ntree, bNode *node, bNode *parent)
Definition node.cc:3107
void node_unlink_node(bNodeTree *ntree, bNode *node)
Definition node.cc:3428
bool node_supports_active_flag(const bNode *node, int sub_active)
Does the given node supports the sub active flag.
void node_register_alias(bNodeType *nt, const char *alias)
Definition node.cc:1731
void node_tree_blend_read_data(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
Definition node.cc:1042
bool node_type_is_undefined(const bNode *node)
Definition node.cc:1736
void node_set_active(bNodeTree *ntree, bNode *node)
Definition node.cc:3896
static bool node_poll_default(const bNodeType *, const bNodeTree *, const char **)
Definition node.cc:4311
void node_detach_node(bNodeTree *ntree, bNode *node)
Definition node.cc:3122
static GHash * nodesockettypes_hash
Definition node.cc:1619
const char * node_type_find_alias(const char *idname)
Definition node.cc:1679
bool node_declaration_ensure_on_outdated_node(bNodeTree *ntree, bNode *node)
Definition node.cc:3970
void node_tree_free_local_tree(bNodeTree *ntree)
Definition node.cc:3639
bool node_socket_is_registered(const bNodeSocket *sock)
Definition node.cc:1801
static void node_init(const bContext *C, bNodeTree *ntree, bNode *node)
Definition node.cc:1432
bool node_link_is_hidden(const bNodeLink *link)
Definition node.cc:2993
int node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp)
Definition node.cc:4095
static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
Definition node.cc:1495
void * node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key)
Definition node.cc:4090
const char * node_socket_sub_type_label(int subtype)
Definition node.cc:1820
static void update_typeinfo(Main *bmain, const bContext *C, bNodeTreeType *treetype, bNodeType *nodetype, bNodeSocketType *socktype, const bool unregister)
Definition node.cc:1560
static void socket_id_user_increment(bNodeSocket *sock)
Definition node.cc:1924
void node_remove_socket_links(bNodeTree *ntree, bNodeSocket *sock)
Definition node.cc:2984
void node_unregister_socket_type(bNodeSocketType *stype)
Definition node.cc:1796
std::optional< VolumeGridType > socket_type_to_grid_type(eNodeSocketDatatype type)
Definition node.cc:4500
bNodeTree * node_tree_copy_tree(Main *bmain, const bNodeTree *ntree)
Definition node.cc:3255
bNodeTree * node_tree_add_in_lib(Main *bmain, Library *owner_library, const char *name, const char *idname)
Definition node.cc:3231
static void node_preview_tag_used_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition node.cc:3358
static bool ntree_contains_tree_exec(const bNodeTree *tree_to_search_in, const bNodeTree *tree_to_search_for, Set< const bNodeTree * > &already_passed)
Definition node.cc:3802
static GHash * nodetypes_alias_hash
Definition node.cc:1618
bool node_tree_iterator_step(NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, ID **r_id)
Definition node.cc:4719
static void update_socket_declarations(ListBase *sockets, Span< nodes::SocketDeclaration * > declarations)
Definition node.cc:3941
static Set< int > get_known_node_types_set()
Definition node.cc:4180
static void remove_unsupported_sockets(ListBase *sockets, ListBase *links)
Definition node.cc:1016
bNodeTree * node_tree_localize(bNodeTree *ntree, ID *new_owner_id)
Definition node.cc:3750
void node_tree_blend_write(BlendWriter *writer, bNodeTree *ntree)
Definition node.cc:760
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
Definition node.cc:2642
static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition node.cc:439
static const CPPType * slow_socket_type_to_geo_nodes_base_cpp_type(const eNodeSocketDatatype type)
Definition node.cc:4431
void node_remove_node(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
Definition node.cc:3545
void node_update_asset_metadata(bNodeTree &node_tree)
Definition node.cc:1305
static bool is_node_socket_supported(const bNodeSocket *sock)
Definition node.cc:962
const DataTypeConversions & get_implicit_type_conversions()
bool node_preview_used(const bNode *node)
Definition node.cc:3267
static bool unique_identifier_check(void *arg, const char *identifier)
Definition node.cc:1873
void node_preview_free(bNodePreview *preview)
Definition node.cc:3314
static void ntree_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int flag)
Definition node.cc:155
void node_internal_relink(bNodeTree *ntree, bNode *node)
Definition node.cc:3019
GHashIterator * node_type_get_iterator()
Definition node.cc:1758
void node_position_relative(bNode *from_node, const bNode *to_node, const bNodeSocket *from_sock, const bNodeSocket *to_sock)
Definition node.cc:3136
bNode * node_copy_with_mapping(bNodeTree *dst_tree, const bNode &node_src, int flag, bool use_unique, Map< const bNodeSocket *, bNodeSocket * > &new_socket_map)
Definition node.cc:2696
void node_tree_set_type(const bContext *C, bNodeTree *ntree)
Definition node.cc:1598
void node_link_set_mute(bNodeTree *ntree, bNodeLink *link, const bool muted)
Definition node.cc:2975
bNode * node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool use_unique)
Definition node.cc:2895
void node_tree_update_all_new(Main *main)
Definition node.cc:4215
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
void node_type_size_preset(bNodeType *ntype, eNodeSizePreset size)
Definition node.cc:4614
void nodeLabel(const bNodeTree *ntree, const bNode *node, char *label, int maxlen)
Definition node.cc:4267
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
static void ntree_free_data(ID *id)
Definition node.cc:273
bool node_find_node_try(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
Definition node.cc:2459
bNode * node_find_root_parent(bNode *node)
Definition node.cc:2479
void node_tree_node_flag_set(const bNodeTree *ntree, int flag, bool enable)
Definition node.cc:3738
static void adjust_multi_input_indices_after_removed_link(bNodeTree *ntree, const bNodeSocket *sock, const int deleted_index)
Definition node.cc:3005
static void ntree_blend_read_after_liblink(BlendLibReader *reader, ID *id)
Definition node.cc:1282
void node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
Definition node.cc:4153
void node_chain_iterator_backwards(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *), void *userdata, int recursion_lvl)
Definition node.cc:2561
void node_chain_iterator(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *, const bool), void *userdata, bool reversed)
Definition node.cc:2501
void node_tree_type_free_link(const bNodeTreeType *nt)
Definition node.cc:1652
static void ntree_init_data(ID *id)
Definition node.cc:146
void node_tree_local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
Definition node.cc:3793
bNodeTree * node_tree_add_tree(Main *bmain, const char *name, const char *idname)
Definition node.cc:3226
static void node_unlink_attached(bNodeTree *ntree, const bNode *parent)
Definition node.cc:3455
BLI_INLINE void * node_instance_hash_iterator_get_value(bNodeInstanceHashIterator *iter)
Definition BKE_node.hh:1662
bool node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key)
Definition node.cc:4140
bNode * node_get_active(bNodeTree *ntree)
Definition node.cc:3849
bool node_is_static_socket_type(const bNodeSocketType *stype)
Definition node.cc:2117
void node_tree_iterator_init(NodeTreeIterStore *ntreeiter, Main *bmain)
Definition node.cc:4709
static bNodeInstanceKey node_hash_int_str(bNodeInstanceKey hash, const char *str)
Definition node.cc:4027
const char * nodeSocketShortLabel(const bNodeSocket *sock)
Definition node.cc:4285
void node_instance_hash_clear_tags(bNodeInstanceHash *hash)
Definition node.cc:4122
std::optional< eNodeSocketDatatype > grid_type_to_socket_type(VolumeGridType type)
Definition node.cc:4516
bNodeType * node_type_find(const char *idname)
Definition node.cc:1667
void node_node_foreach_id(bNode *node, LibraryForeachIDData *data)
Definition node.cc:378
bNodeTreeType NodeTreeTypeUndefined
Definition node.cc:134
static bool can_read_node_type(const int type)
Definition node.cc:4190
static void node_set_typeinfo(const bContext *C, bNodeTree *ntree, bNode *node, bNodeType *typeinfo)
Definition node.cc:1509
static void node_tree_asset_on_clear_asset(void *asset_ptr, AssetMetaData *asset_data)
Definition node.cc:1351
bNode * node_add_node(const bContext *C, bNodeTree *ntree, const char *idname)
Definition node.cc:2617
bNodeTree ** node_tree_ptr_from_id(ID *id)
Definition node.cc:3712
void node_parents_iterator(bNode *node, bool(*callback)(bNode *, void *), void *userdata)
Definition node.cc:2583
bool node_link_is_selected(const bNodeLink *link)
Definition node.cc:2998
bNodeSocketType * node_socket_type_find(const char *idname)
Definition node.cc:1763
void node_rebuild_id_vector(bNodeTree *node_tree)
Definition node.cc:3464
void node_position_propagate(bNode *node)
Definition node.cc:3178
const char * node_socket_type_label(const bNodeSocketType *stype)
Definition node.cc:1811
static void reset_socket_declarations(ListBase *sockets)
Definition node.cc:3951
void node_tree_type_add(bNodeTreeType *nt)
Definition node.cc:1633
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
Definition node.cc:4020
std::optional< eNodeSocketDatatype > custom_data_type_to_socket_type(eCustomDataType type)
Definition node.cc:4403
void node_system_exit()
Definition node.cc:4659
bNodeTree * node_tree_add_tree_embedded(Main *bmain, ID *owner_id, const char *name, const char *idname)
Definition node.cc:3239
void node_preview_remove_unused(bNodeTree *ntree)
Definition node.cc:3376
void node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
Definition node.cc:4102
bNodeType NodeTypeUndefined
Definition node.cc:135
static void node_foreach_id(ID *id, LibraryForeachIDData *data)
Definition node.cc:397
void node_type_socket_templates(bNodeType *ntype, bNodeSocketTemplate *inputs, bNodeSocketTemplate *outputs)
Definition node.cc:4570
bNodeInstanceKey node_instance_key(bNodeInstanceKey parent_key, const bNodeTree *ntree, const bNode *node)
Definition node.cc:4041
void node_remove_socket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
Definition node.cc:2405
void node_find_node(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
Definition node.cc:2442
static void ntree_blend_read_data(BlendDataReader *reader, ID *id)
Definition node.cc:1276
void node_register_socket_type(bNodeSocketType *stype)
Definition node.cc:1787
void node_remove_link(bNodeTree *ntree, bNodeLink *link)
Definition node.cc:2958
static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag)
Definition node.cc:2667
const char * node_static_socket_type(int type, int subtype)
Definition node.cc:2126
void node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool remove_old)
Definition node.cc:3390
void node_tree_free_tree(bNodeTree *ntree)
Definition node.cc:3626
void node_set_socket_availability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
Definition node.cc:3911
void node_type_size(bNodeType *ntype, int width, int minwidth, int maxwidth)
Definition node.cc:4602
static bool node_poll_instance_default(const bNode *node, const bNodeTree *ntree, const char **r_disabled_hint)
Definition node.cc:4318
GHashIterator * node_tree_type_get_iterator()
Definition node.cc:1662
bNodeSocket * node_find_enabled_output_socket(bNode &node, StringRef name)
Definition node.cc:1868
bNodeSocket * node_add_socket(bNodeTree *ntree, bNode *node, eNodeSocketInOut in_out, const char *idname, const char *identifier, const char *name)
Definition node.cc:2095
const CPPType * socket_type_to_geo_nodes_base_cpp_type(eNodeSocketDatatype type)
Definition node.cc:4438
static bNodeTree * node_tree_add_tree_do(Main *bmain, std::optional< Library * > owner_library, ID *owner_id, const bool is_embedded, const char *name, const char *idname)
Definition node.cc:3189
static void node_tree_asset_pre_save(void *asset_ptr, AssetMetaData *)
Definition node.cc:1333
static void iter_backwards_ex(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *), void *userdata, const char recursion_mask)
Definition node.cc:2533
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
static GHash * nodetypes_hash
Definition node.cc:1617
void node_tree_free_local_node(bNodeTree *ntree, bNode *node)
Definition node.cc:3531
BLI_INLINE bNodeInstanceKey node_instance_hash_iterator_get_key(bNodeInstanceHashIterator *iter)
Definition BKE_node.hh:1657
bool node_set_selected(bNode *node, bool select)
Definition node.cc:3863
void node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize)
Definition node.cc:3345
static void node_free_socket_type(void *socktype_v)
Definition node.cc:1776
static uint node_instance_hash_key(const void *key)
Definition node.cc:4054
void node_internal_links(bNode *node, bNodeLink **r_links, int *r_len)
Definition node.cc:4012
void node_clear_active(bNodeTree *ntree)
Definition node.cc:3885
static void node_replace_undefined_types(bNode *node)
Definition node.cc:4202
bNodeSocket * node_find_enabled_socket(bNode &node, eNodeSocketInOut in_out, StringRef name)
Definition node.cc:1850
const char * node_static_socket_label(int type, int subtype)
Definition node.cc:2318
void node_unregister_type(bNodeType *ntype)
Definition node.cc:1726
static void node_type_base_defaults(bNodeType *ntype)
Definition node.cc:4301
void node_tag_update_id(bNode *node)
Definition node.cc:4007
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
static void node_preview_init_tree_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key, const int xsize, const int ysize)
Definition node.cc:3322
void * node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key)
Definition node.cc:4107
static void free_localized_node_groups(bNodeTree *ntree)
Definition node.cc:3607
bool node_tree_contains_tree(const bNodeTree *tree_to_search_in, const bNodeTree *tree_to_search_for)
Definition node.cc:3827
int node_socket_link_limit(const bNodeSocket *sock)
Definition node.cc:3925
void node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
Definition node.cc:4076
const char * nodeSocketLabel(const bNodeSocket *sock)
Definition node.cc:4296
static void library_foreach_node_socket(bNodeSocket *sock, LibraryForeachIDData *data)
Definition node.cc:326
static void * socket_value_storage(bNodeSocket &socket)
Definition node.cc:2803
bNodePreview * node_preview_verify(bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create)
Definition node.cc:3273
void(*)(void *value) bNodeInstanceValueFP
Definition BKE_node.hh:739
static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition node.cc:933
GHashIterator * node_socket_type_get_iterator()
Definition node.cc:1806
bool node_declaration_ensure(bNodeTree *ntree, bNode *node)
Definition node.cc:3992
bNodeTreeType * node_tree_type_find(const char *idname)
Definition node.cc:1621
void node_unique_id(bNodeTree *ntree, bNode *node)
Definition node.cc:2599
void node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
Definition node.cc:4325
int node_count_socket_links(const bNodeTree *ntree, const bNodeSocket *sock)
Definition node.cc:3838
static void * node_static_value_storage_for(bNode &node, const bNodeSocket &socket)
Definition node.cc:2774
void node_free_node(bNodeTree *tree, bNode *node)
Definition node.cc:3475
void node_type_base_custom(bNodeType *ntype, const char *idname, const char *name, const char *enum_name, short nclass)
Definition node.cc:4364
void node_system_init()
Definition node.cc:4649
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
Definition node.cc:1404
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE
Definition node.cc:4021
static bool unique_socket_template_identifier_check(void *arg, const char *name)
Definition node.cc:4537
static void ntree_free_type(void *treetype_v)
Definition node.cc:1642
bNodeInstanceHash * node_instance_hash_new(const char *info)
Definition node.cc:4067
static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket)
Definition node.cc:2901
static void unique_socket_template_identifier(bNodeSocketTemplate *list, bNodeSocketTemplate *ntemp, const char defname[], const char delim)
Definition node.cc:4553
static void write_node_socket_default_value(BlendWriter *writer, const bNodeSocket *sock)
Definition node.cc:687
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
static void node_foreach_cache(ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
Definition node.cc:415
static void node_tree_asset_on_mark_asset(void *asset_ptr, AssetMetaData *asset_data)
Definition node.cc:1339
void node_socket_move_default_value(Main &bmain, bNodeTree &tree, bNodeSocket &src, bNodeSocket &dst)
Definition node.cc:2846
bNodeTree * node_tree_from_id(ID *id)
Definition node.cc:3732
void node_tree_update_all_users(Main *main, ID *id)
Definition node.cc:4242
static bool node_instance_hash_key_cmp(const void *a, const void *b)
Definition node.cc:4059
float2 node_from_view(const bNode *node, float2 view_loc)
Definition node.cc:3098
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
static void node_socket_free(bNodeSocket *sock, const bool do_id_user)
Definition node.cc:2379
void node_dimensions_get(const bNode *node, float *r_width, float *r_height)
Definition node.cc:4001
static void node_socket_set_typeinfo(bNodeTree *ntree, bNodeSocket *sock, bNodeSocketType *typeinfo)
Definition node.cc:1538
bNode * node_find_node_by_name(bNodeTree *ntree, const char *name)
Definition node.cc:2437
void node_tree_free_embedded_tree(bNodeTree *ntree)
Definition node.cc:3632
static void write_node_socket(BlendWriter *writer, const bNodeSocket *sock)
Definition node.cc:746
bool node_tree_is_registered(const bNodeTree *ntree)
Definition node.cc:1657
std::optional< eCustomDataType > socket_type_to_custom_data_type(eNodeSocketDatatype type)
Definition node.cc:4379
void node_modify_socket_type(bNodeTree *ntree, bNode *node, bNodeSocket *sock, const char *idname)
Definition node.cc:2020
static GHash * nodetreetypes_hash
Definition node.cc:1616
void node_unique_name(bNodeTree *ntree, bNode *node)
Definition node.cc:2593
static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
Definition node.cc:987
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)
VecBase< float, 2 > float2
void uninitialized_copy_n(const T *src, int64_t n, T *dst)
static AssetTypeInfo AssetType_NT
Definition node.cc:1365
IDTypeInfo IDType_ID_NT
Definition node.cc:1371
static CLG_LogRef LOG
Definition node.cc:126
void register_nodes()
void node_socket_init_default_value(bNodeSocket *sock)
bNodeSocket * node_add_socket_from_template(bNodeTree *ntree, bNode *node, bke::bNodeSocketTemplate *stemp, eNodeSocketInOut in_out)
void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
void node_socket_copy_default_value_data(eNodeSocketDatatype datatype, void *to, const void *from)
static blender::bke::bNodeSocketTemplate outputs[]
static blender::bke::bNodeSocketTemplate inputs[]
#define hash
Definition noise.c:154
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
const char * RNA_struct_ui_name(const StructRNA *type)
bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
const EnumPropertyItem rna_enum_property_subtype_items[]
Definition rna_rna.cc:127
#define FLT_MAX
Definition stdcycles.h:14
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
signed int int32_t
Definition stdint.h:77
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
StructRNA * srna
Definition RNA_types.hh:780
struct bNodeTree * nodetree
unsigned int id_session_uid
Definition BKE_idtype.hh:69
size_t identifier
Definition BKE_idtype.hh:72
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
struct Library * lib
Definition DNA_ID.h:419
short flag
Definition DNA_ID.h:430
void * next
Definition DNA_ID.h:416
char name[66]
Definition DNA_ID.h:425
ImBufByteBuffer byte_buffer
struct Scene * scene
struct bNodeTree * nodetree
void * first
ListBase scenes
Definition BKE_main.hh:210
ListBase textures
Definition BKE_main.hh:217
ListBase lights
Definition BKE_main.hh:220
ListBase nodetrees
Definition BKE_main.hh:234
ListBase materials
Definition BKE_main.hh:216
ListBase linestyles
Definition BKE_main.hh:244
ListBase worlds
Definition BKE_main.hh:224
struct bNodeTree * nodetree
NodeCryptomatte_Runtime runtime
char angle streaks
char angle star_45
ImageFormatData format
struct bNodeTree * nodetree
struct ImageUser iuser
struct bNodeTree * nodetree
struct bNodeTree * nodetree
unsigned int value
struct ImBuf * ibuf
struct Collection * value
struct Material * value
const RuntimeNodeEnumItemsHandle * enum_items
IDProperty * prop
bNodeSocketRuntimeHandle * runtime
struct bNodeLink * link
char description[64]
bNodeSocketTypeHandle * typeinfo
char * default_attribute_name
void * default_value
char identifier[64]
char idname[64]
bNodeTreeRuntimeHandle * runtime
char idname[64]
struct GeometryNodeAssetTraits * geometry_node_asset_traits
int nested_node_refs_num
struct PreviewImage * preview
bNestedNodeRef * nested_node_refs
NodeInstanceHashHandle * previews
struct bGPdata * gpd
int default_group_node_width
bNodeTreeTypeHandle * typeinfo
char * description
bNodeTreeInterface tree_interface
ListBase nodes
ListBase links
bNodeTypeHandle * typeinfo
float locy
IDProperty * prop
ListBase inputs
struct ID * id
struct bNode * parent
float locx
bNodePanelState * panel_states_array
struct bNode * next
bNodeRuntimeHandle * runtime
char idname[64]
ListBase outputs
int16_t type
FreestyleLineStyle * linestyle
Definition BKE_node.hh:854
Compact definition of a node socket.
Definition BKE_node.hh:103
Defines a socket type.
Definition BKE_node.hh:151
void(* free_self)(bNodeSocketType *stype)
Definition BKE_node.hh:188
const blender::CPPType * base_cpp_type
Definition BKE_node.hh:191
Defines a node type.
Definition BKE_node.hh:218
blender::nodes::NodeDeclaration * static_declaration
Definition BKE_node.hh:356
void(* copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
Definition BKE_node.hh:277
void(* freefunc)(bNode *node)
Definition BKE_node.hh:275
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
bool(* poll_instance)(const bNode *node, const bNodeTree *nodetree, const char **r_disabled_hint)
Definition BKE_node.hh:304
bNodeSocketTemplate * inputs
Definition BKE_node.hh:233
bNodeSocketTemplate * outputs
Definition BKE_node.hh:233
const char * enum_name_legacy
Definition BKE_node.hh:226
bool(* poll)(const bNodeType *ntype, const bNodeTree *nodetree, const char **r_disabled_hint)
Definition BKE_node.hh:299
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* free_self)(bNodeType *ntype)
Definition BKE_node.hh:311
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:280
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138