diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 364b6635b0d..5608ad626b5 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -65,6 +65,7 @@ #include "BKE_node.h" #include "BKE_node_runtime.hh" #include "BKE_node_tree_update.h" +#include "BKE_type_conversions.hh" #include "RNA_access.h" #include "RNA_define.h" @@ -2426,6 +2427,71 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree, return node_dst; } +/** + * Type of value storage related with socket is the same. + * \param socket: Node can have multiple sockets & storages pairs. + */ +static void *node_static_value_storage_for(bNode &node, const bNodeSocket &socket) +{ + if (!socket.is_output()) { + return nullptr; + } + + switch (node.type) { + case FN_NODE_INPUT_BOOL: + return &reinterpret_cast(node.storage)->boolean; + case FN_NODE_INPUT_INT: + return &reinterpret_cast(node.storage)->integer; + case FN_NODE_INPUT_VECTOR: + return &reinterpret_cast(node.storage)->vector; + case FN_NODE_INPUT_COLOR: + return &reinterpret_cast(node.storage)->color; + case GEO_NODE_IMAGE: + return &node.id; + default: + break; + } + + return nullptr; +} + +static void *socket_value_storage(bNodeSocket &socket) +{ + switch (eNodeSocketDatatype(socket.type)) { + case SOCK_BOOLEAN: + return &socket.default_value_typed()->value; + case SOCK_INT: + return &socket.default_value_typed()->value; + case SOCK_FLOAT: + return &socket.default_value_typed()->value; + case SOCK_VECTOR: + return &socket.default_value_typed()->value; + case SOCK_RGBA: + return &socket.default_value_typed()->value; + case SOCK_IMAGE: + return &socket.default_value_typed()->value; + case SOCK_TEXTURE: + return &socket.default_value_typed()->value; + case SOCK_COLLECTION: + return &socket.default_value_typed()->value; + case SOCK_OBJECT: + return &socket.default_value_typed()->value; + case SOCK_MATERIAL: + return &socket.default_value_typed()->value; + case SOCK_STRING: + /* We don't want do this now! */ + return nullptr; + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_GEOMETRY: + /* Unmovable types. */ + break; + } + + return nullptr; +} + void node_socket_move_default_value(Main & /*bmain*/, bNodeTree &tree, bNodeSocket &src, @@ -2436,6 +2502,11 @@ void node_socket_move_default_value(Main & /*bmain*/, bNode &dst_node = dst.owner_node(); bNode &src_node = src.owner_node(); + const CPPType &src_type = *src.typeinfo->base_cpp_type; + const CPPType &dst_type = *dst.typeinfo->base_cpp_type; + + const bke::DataTypeConversions &convert = bke::get_implicit_type_conversions(); + if (src.is_multi_input()) { /* Multi input sockets no have value. */ return; @@ -2444,54 +2515,29 @@ void node_socket_move_default_value(Main & /*bmain*/, /* Reroute node can't have ownership of socket value directly. */ return; } - if (dst.type != src.type) { - /* It could be possible to support conversion in future. */ - return; - } - - ID **src_socket_value = nullptr; - Vector dst_values; - switch (dst.type) { - case SOCK_IMAGE: { - Image **tmp_socket_value = &src.default_value_typed()->value; - src_socket_value = reinterpret_cast(tmp_socket_value); - if (*src_socket_value == nullptr) { - break; - } - - switch (dst_node.type) { - case GEO_NODE_IMAGE: { - dst_values.append(&dst_node.id); - break; - } - default: { - break; - } - } - break; - } - case SOCK_CUSTOM: - case SOCK_SHADER: - case SOCK_GEOMETRY: { - /* Unmovable types. */ + if (&src_type != &dst_type) { + if (!convert.is_convertible(src_type, dst_type)) { return; } - default: { - break; - } } - if (dst_values.is_empty() || src_socket_value == nullptr) { + void *src_value = socket_value_storage(src); + void *dst_value = node_static_value_storage_for(dst_node, dst); + if (!dst_value || !src_value) { return; } - for (ID **dst_value : dst_values) { - *dst_value = *src_socket_value; - id_us_plus(*dst_value); - } + convert.convert_to_uninitialized(src_type, dst_type, src_value, dst_value); - id_us_min(*src_socket_value); - *src_socket_value = nullptr; + src_type.destruct(src_value); + if (ELEM(eNodeSocketDatatype(src.type), + SOCK_COLLECTION, + SOCK_IMAGE, + SOCK_MATERIAL, + SOCK_TEXTURE, + SOCK_OBJECT)) { + src_type.value_initialize(src_value); + } } bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, const int flag, const bool use_unique)