diff options
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 41 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.cc | 251 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_250.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.cc | 115 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_group.cc | 29 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 4 | ||||
-rw-r--r-- | source/blender/nodes/composite/node_composite_tree.cc | 30 | ||||
-rw-r--r-- | source/blender/nodes/shader/node_shader_tree.c | 2 |
8 files changed, 189 insertions, 284 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 500d8e2e0ac..1e0a75bfc57 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -34,6 +34,7 @@ #include "RNA_types.h" #ifdef __cplusplus +# include "BLI_map.hh" # include "BLI_string_ref.hh" #endif @@ -518,8 +519,6 @@ void ntreeSetOutput(struct bNodeTree *ntree); void ntreeFreeCache(struct bNodeTree *ntree); -bool ntreeNodeExists(const struct bNodeTree *ntree, const struct bNode *testnode); -bool ntreeOutputExists(const struct bNode *node, const struct bNodeSocket *testsock); void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable); /** * Returns localized tree for execution in threads. @@ -697,31 +696,27 @@ void nodeRemoveNode(struct Main *bmain, struct bNode *node, bool do_id_user); +#ifdef __cplusplus + +namespace blender::bke { + /** - * \param ntree: is the target tree. - * - * \note keep socket list order identical, for copying links. + * \note keeps socket list order identical, for copying links. * \note `unique_name` needs to be true. It's only disabled for speed when doing GPUnodetrees. */ -struct bNode *BKE_node_copy_ex(struct bNodeTree *ntree, - const struct bNode *node_src, - const int flag, - const bool unique_name); +bNode *node_copy_with_mapping(bNodeTree *dst_tree, + const bNode &node_src, + int flag, + bool unique_name, + Map<const bNodeSocket *, bNodeSocket *> &new_socket_map); -/** - * Same as #BKE_node_copy_ex but stores pointers to a new node and its sockets in the source node. - * - * NOTE: DANGER ZONE! - * - * TODO(sergey): Maybe it's better to make BKE_node_copy_ex() return a mapping from old node and - * sockets to new one. - */ -struct bNode *BKE_node_copy_store_new_pointers(struct bNodeTree *ntree, - struct bNode *node_src, - const int flag); -struct bNodeTree *ntreeCopyTree_ex_new_pointers(const struct bNodeTree *ntree, - struct Main *bmain, - const bool do_id_user); +bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool unique_name); + +} // namespace blender::bke + +#endif + +bNode *BKE_node_copy(bNodeTree *dst_tree, const bNode *src_node, int flag, bool unique_name); /** * Also used via RNA API, so we check for proper input output direction. diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 7121ef20207..05096ae63c1 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -99,6 +99,7 @@ #define NODE_DEFAULT_MAX_WIDTH 700 using blender::Array; +using blender::Map; using blender::MutableSpan; using blender::Set; using blender::Span; @@ -152,62 +153,41 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c BLI_listbase_clear(&ntree_dst->nodes); BLI_listbase_clear(&ntree_dst->links); - /* Since source nodes and sockets are unique pointers we can put everything in a single map. */ - GHash *new_pointers = BLI_ghash_ptr_new(__func__); + Map<const bNode *, bNode *> node_map; + Map<const bNodeSocket *, bNodeSocket *> socket_map; - LISTBASE_FOREACH (const bNode *, node_src, &ntree_src->nodes) { - bNode *new_node = BKE_node_copy_ex(ntree_dst, node_src, flag_subdata, true); - BLI_ghash_insert(new_pointers, (void *)node_src, new_node); - /* Store mapping to inputs. */ - bNodeSocket *new_input_sock = (bNodeSocket *)new_node->inputs.first; - const bNodeSocket *input_sock_src = (const bNodeSocket *)node_src->inputs.first; - while (new_input_sock != nullptr) { - BLI_ghash_insert(new_pointers, (void *)input_sock_src, new_input_sock); - new_input_sock = new_input_sock->next; - input_sock_src = input_sock_src->next; - } - /* Store mapping to outputs. */ - bNodeSocket *new_output_sock = (bNodeSocket *)new_node->outputs.first; - const bNodeSocket *output_sock_src = (const bNodeSocket *)node_src->outputs.first; - while (new_output_sock != nullptr) { - BLI_ghash_insert(new_pointers, (void *)output_sock_src, new_output_sock); - new_output_sock = new_output_sock->next; - output_sock_src = output_sock_src->next; - } + BLI_listbase_clear(&ntree_dst->nodes); + LISTBASE_FOREACH (const bNode *, src_node, &ntree_src->nodes) { + bNode *new_node = blender::bke::node_copy_with_mapping( + ntree_dst, *src_node, flag_subdata, true, socket_map); + node_map.add(src_node, new_node); } /* copy links */ - BLI_duplicatelist(&ntree_dst->links, &ntree_src->links); - LISTBASE_FOREACH (bNodeLink *, link_dst, &ntree_dst->links) { - link_dst->fromnode = (bNode *)BLI_ghash_lookup_default( - new_pointers, link_dst->fromnode, nullptr); - link_dst->fromsock = (bNodeSocket *)BLI_ghash_lookup_default( - new_pointers, link_dst->fromsock, nullptr); - link_dst->tonode = (bNode *)BLI_ghash_lookup_default(new_pointers, link_dst->tonode, nullptr); - link_dst->tosock = (bNodeSocket *)BLI_ghash_lookup_default( - new_pointers, link_dst->tosock, nullptr); - /* update the link socket's pointer */ - if (link_dst->tosock) { - link_dst->tosock->link = link_dst; - } + BLI_listbase_clear(&ntree_dst->links); + LISTBASE_FOREACH (const bNodeLink *, src_link, &ntree_src->links) { + bNodeLink *dst_link = (bNodeLink *)MEM_dupallocN(src_link); + dst_link->fromnode = node_map.lookup(src_link->fromnode); + dst_link->fromsock = socket_map.lookup(src_link->fromsock); + dst_link->tonode = node_map.lookup(src_link->tonode); + dst_link->tosock = socket_map.lookup(src_link->tosock); + BLI_assert(dst_link->tosock); + dst_link->tosock->link = dst_link; + BLI_addtail(&ntree_dst->links, dst_link); } /* copy interface sockets */ - BLI_duplicatelist(&ntree_dst->inputs, &ntree_src->inputs); - bNodeSocket *sock_dst, *sock_src; - for (sock_dst = (bNodeSocket *)ntree_dst->inputs.first, - sock_src = (bNodeSocket *)ntree_src->inputs.first; - sock_dst != nullptr; - sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { - node_socket_copy(sock_dst, sock_src, flag_subdata); + BLI_listbase_clear(&ntree_dst->inputs); + LISTBASE_FOREACH (const bNodeSocket *, src_socket, &ntree_src->inputs) { + bNodeSocket *dst_socket = (bNodeSocket *)MEM_dupallocN(src_socket); + node_socket_copy(dst_socket, src_socket, flag_subdata); + BLI_addtail(&ntree_dst->inputs, dst_socket); } - - BLI_duplicatelist(&ntree_dst->outputs, &ntree_src->outputs); - for (sock_dst = (bNodeSocket *)ntree_dst->outputs.first, - sock_src = (bNodeSocket *)ntree_src->outputs.first; - sock_dst != nullptr; - sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { - node_socket_copy(sock_dst, sock_src, flag_subdata); + BLI_listbase_clear(&ntree_dst->outputs); + LISTBASE_FOREACH (const bNodeSocket *, src_socket, &ntree_src->outputs) { + bNodeSocket *dst_socket = (bNodeSocket *)MEM_dupallocN(src_socket); + node_socket_copy(dst_socket, src_socket, flag_subdata); + BLI_addtail(&ntree_dst->outputs, dst_socket); } /* copy preview hash */ @@ -227,18 +207,11 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c } /* update node->parent pointers */ - for (bNode *node_dst = (bNode *)ntree_dst->nodes.first, - *node_src = (bNode *)ntree_src->nodes.first; - node_dst; - node_dst = (bNode *)node_dst->next, node_src = (bNode *)node_src->next) { - if (node_dst->parent) { - node_dst->parent = (bNode *)BLI_ghash_lookup_default( - new_pointers, node_dst->parent, nullptr); + LISTBASE_FOREACH (bNode *, new_node, &ntree_dst->nodes) { + if (new_node->parent) { + new_node->parent = node_map.lookup(new_node->parent); } } - - BLI_ghash_free(new_pointers, nullptr, nullptr); - /* node tree will generate its own interface type */ ntree_dst->interface_type = nullptr; @@ -2238,136 +2211,100 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, sock_dst->cache = nullptr; } -bNode *BKE_node_copy_ex(bNodeTree *ntree, - const bNode *node_src, - const int flag, - const bool unique_name) -{ - bNode *node_dst = (bNode *)MEM_callocN(sizeof(bNode), "dupli node"); - bNodeSocket *sock_dst, *sock_src; - bNodeLink *link_dst, *link_src; +namespace blender::bke { - *node_dst = *node_src; +bNode *node_copy_with_mapping(bNodeTree *dst_tree, + const bNode &node_src, + const int flag, + const bool unique_name, + Map<const bNodeSocket *, bNodeSocket *> &socket_map) +{ + bNode *node_dst = (bNode *)MEM_mallocN(sizeof(bNode), __func__); + *node_dst = node_src; /* Can be called for nodes outside a node tree (e.g. clipboard). */ - if (ntree) { + if (dst_tree) { if (unique_name) { - nodeUniqueName(ntree, node_dst); + nodeUniqueName(dst_tree, node_dst); } - - BLI_addtail(&ntree->nodes, node_dst); + BLI_addtail(&dst_tree->nodes, node_dst); } - BLI_duplicatelist(&node_dst->inputs, &node_src->inputs); - for (sock_dst = (bNodeSocket *)node_dst->inputs.first, - sock_src = (bNodeSocket *)node_src->inputs.first; - sock_dst != nullptr; - sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { - node_socket_copy(sock_dst, sock_src, flag); + BLI_listbase_clear(&node_dst->inputs); + LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.inputs) { + bNodeSocket *dst_socket = (bNodeSocket *)MEM_dupallocN(src_socket); + node_socket_copy(dst_socket, src_socket, flag); + BLI_addtail(&node_dst->inputs, dst_socket); + socket_map.add_new(src_socket, dst_socket); } - BLI_duplicatelist(&node_dst->outputs, &node_src->outputs); - for (sock_dst = (bNodeSocket *)node_dst->outputs.first, - sock_src = (bNodeSocket *)node_src->outputs.first; - sock_dst != nullptr; - sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { - node_socket_copy(sock_dst, sock_src, flag); + BLI_listbase_clear(&node_dst->outputs); + LISTBASE_FOREACH (const bNodeSocket *, src_socket, &node_src.outputs) { + bNodeSocket *dst_socket = (bNodeSocket *)MEM_dupallocN(src_socket); + node_socket_copy(dst_socket, src_socket, flag); + BLI_addtail(&node_dst->outputs, dst_socket); + socket_map.add_new(src_socket, dst_socket); } - if (node_src->prop) { - node_dst->prop = IDP_CopyProperty_ex(node_src->prop, flag); + if (node_src.prop) { + node_dst->prop = IDP_CopyProperty_ex(node_src.prop, flag); } - BLI_duplicatelist(&node_dst->internal_links, &node_src->internal_links); - for (link_dst = (bNodeLink *)node_dst->internal_links.first, - link_src = (bNodeLink *)node_src->internal_links.first; - link_dst != nullptr; - link_dst = (bNodeLink *)link_dst->next, link_src = (bNodeLink *)link_src->next) { - /* This is a bit annoying to do index lookups in a list, but is likely to be faster than - * trying to create a hash-map. At least for usual nodes, which only have so much sockets - * and internal links. */ - const int from_sock_index = BLI_findindex(&node_src->inputs, link_src->fromsock); - const int to_sock_index = BLI_findindex(&node_src->outputs, link_src->tosock); - BLI_assert(from_sock_index != -1); - BLI_assert(to_sock_index != -1); - link_dst->fromnode = node_dst; - link_dst->tonode = node_dst; - link_dst->fromsock = (bNodeSocket *)BLI_findlink(&node_dst->inputs, from_sock_index); - link_dst->tosock = (bNodeSocket *)BLI_findlink(&node_dst->outputs, to_sock_index); + BLI_listbase_clear(&node_dst->internal_links); + LISTBASE_FOREACH (const bNodeLink *, src_link, &node_src.internal_links) { + bNodeLink *dst_link = (bNodeLink *)MEM_dupallocN(src_link); + dst_link->fromnode = node_dst; + dst_link->tonode = node_dst; + dst_link->fromsock = socket_map.lookup(src_link->fromsock); + dst_link->tosock = socket_map.lookup(src_link->tosock); + BLI_addtail(&node_dst->internal_links, dst_link); } if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus(node_dst->id); } - if (node_src->typeinfo->copyfunc) { - node_src->typeinfo->copyfunc(ntree, node_dst, node_src); + if (node_src.typeinfo->copyfunc) { + node_src.typeinfo->copyfunc(dst_tree, node_dst, &node_src); } - node_dst->new_node = nullptr; - /* Only call copy function when a copy is made for the main database, not * for cases like the dependency graph and localization. */ if (node_dst->typeinfo->copyfunc_api && !(flag & LIB_ID_CREATE_NO_MAIN)) { PointerRNA ptr; - RNA_pointer_create((ID *)ntree, &RNA_Node, node_dst, &ptr); + RNA_pointer_create((ID *)dst_tree, &RNA_Node, node_dst, &ptr); - node_dst->typeinfo->copyfunc_api(&ptr, node_src); + node_dst->typeinfo->copyfunc_api(&ptr, &node_src); } - if (ntree) { - BKE_ntree_update_tag_node_new(ntree, node_dst); + if (dst_tree) { + BKE_ntree_update_tag_node_new(dst_tree, node_dst); } /* Reset the declaration of the new node. */ node_dst->declaration = nullptr; - nodeDeclarationEnsure(ntree, node_dst); + nodeDeclarationEnsure(dst_tree, node_dst); return node_dst; } -static void node_set_new_pointers(bNode *node_src, bNode *new_node) +bNode *node_copy(bNodeTree *dst_tree, + const bNode &src_node, + const int flag, + const bool unique_name) { - /* Store mapping to the node itself. */ - node_src->new_node = new_node; - /* Store mapping to inputs. */ - bNodeSocket *new_input_sock = (bNodeSocket *)new_node->inputs.first; - bNodeSocket *input_sock_src = (bNodeSocket *)node_src->inputs.first; - while (new_input_sock != nullptr) { - input_sock_src->new_sock = new_input_sock; - new_input_sock = new_input_sock->next; - input_sock_src = input_sock_src->next; - } - /* Store mapping to outputs. */ - bNodeSocket *new_output_sock = (bNodeSocket *)new_node->outputs.first; - bNodeSocket *output_sock_src = (bNodeSocket *)node_src->outputs.first; - while (new_output_sock != nullptr) { - output_sock_src->new_sock = new_output_sock; - new_output_sock = new_output_sock->next; - output_sock_src = output_sock_src->next; - } + Map<const bNodeSocket *, bNodeSocket *> socket_map; + return node_copy_with_mapping(dst_tree, src_node, flag, unique_name, socket_map); } -bNode *BKE_node_copy_store_new_pointers(bNodeTree *ntree, bNode *node_src, const int flag) -{ - bNode *new_node = BKE_node_copy_ex(ntree, node_src, flag, true); - node_set_new_pointers(node_src, new_node); - return new_node; -} +} // namespace blender::bke -bNodeTree *ntreeCopyTree_ex_new_pointers(const bNodeTree *ntree, - Main *bmain, - const bool do_id_user) +bNode *BKE_node_copy(bNodeTree *dst_tree, + const bNode *src_node, + const int flag, + const bool unique_name) { - bNodeTree *new_ntree = ntreeCopyTree_ex(ntree, bmain, do_id_user); - bNode *new_node = (bNode *)new_ntree->nodes.first; - bNode *node_src = (bNode *)ntree->nodes.first; - while (new_node != nullptr) { - node_set_new_pointers(node_src, new_node); - new_node = new_node->next; - node_src = node_src->next; - } - return new_ntree; + return blender::bke::node_copy(dst_tree, *src_node, flag, unique_name); } static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket) @@ -3354,26 +3291,6 @@ bNodeTree *ntreeFromID(ID *id) return (nodetree != nullptr) ? *nodetree : nullptr; } -bool ntreeNodeExists(const bNodeTree *ntree, const bNode *testnode) -{ - LISTBASE_FOREACH (const bNode *, node, &ntree->nodes) { - if (node == testnode) { - return true; - } - } - return false; -} - -bool ntreeOutputExists(const bNode *node, const bNodeSocket *testsock) -{ - LISTBASE_FOREACH (const bNodeSocket *, sock, &node->outputs) { - if (sock == testsock) { - return true; - } - } - return false; -} - void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable) { LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 8bcb99e41e4..202a2a95a7c 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -580,7 +580,6 @@ static bNodeSocket *do_versions_node_group_add_socket_2_56_2(bNodeTree *ngroup, gsock->type = type; gsock->next = gsock->prev = NULL; - gsock->new_sock = NULL; gsock->link = NULL; /* assign new unique index */ gsock->own_index = ngroup->cur_index++; diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index ba2327c742b..b9b843c5a4a 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -79,6 +79,7 @@ #define USE_ESC_COMPO using blender::float2; +using blender::Map; /* ***************** composite job manager ********************** */ @@ -1249,7 +1250,8 @@ bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link) /* ****************** Duplicate *********************** */ -static void node_duplicate_reparent_recursive(bNode *node) +static void node_duplicate_reparent_recursive(const Map<const bNode *, bNode *> &node_map, + bNode *node) { bNode *parent; @@ -1259,15 +1261,15 @@ static void node_duplicate_reparent_recursive(bNode *node) for (parent = node->parent; parent; parent = parent->parent) { if (parent->flag & SELECT) { if (!(parent->flag & NODE_TEST)) { - node_duplicate_reparent_recursive(parent); + node_duplicate_reparent_recursive(node_map, parent); } break; } } /* reparent node copy to parent copy */ if (parent) { - nodeDetachNode(node->new_node); - nodeAttachNode(node->new_node, parent->new_node); + nodeDetachNode(node_map.lookup(node)); + nodeAttachNode(node_map.lookup(node), node_map.lookup(parent)); } } @@ -1280,10 +1282,15 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), bmain); + Map<const bNode *, bNode *> node_map; + Map<const bNodeSocket *, bNodeSocket *> socket_map; + bNode *lastnode = (bNode *)ntree->nodes.last; LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { - BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); + bNode *new_node = blender::bke::node_copy_with_mapping( + ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map); + node_map.add_new(node, new_node); } /* make sure we don't copy new nodes again! */ @@ -1292,8 +1299,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) } } - /* Copy links between selected nodes. - * NOTE: this depends on correct node->new_node and sock->new_sock pointers from above copy! */ + /* Copy links between selected nodes. */ bNodeLink *lastlink = (bNodeLink *)ntree->links.last; LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { /* This creates new links between copied nodes. @@ -1303,11 +1309,11 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT)))) { bNodeLink *newlink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "bNodeLink"); newlink->flag = link->flag; - newlink->tonode = link->tonode->new_node; - newlink->tosock = link->tosock->new_sock; + newlink->tonode = node_map.lookup(link->tonode); + newlink->tosock = socket_map.lookup(link->tosock); if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) { - newlink->fromnode = link->fromnode->new_node; - newlink->fromsock = link->fromsock->new_sock; + newlink->fromnode = node_map.lookup(link->fromnode); + newlink->fromsock = socket_map.lookup(link->fromsock); } else { /* input node not copied, this keeps the original input linked */ @@ -1331,7 +1337,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) /* reparent copied nodes */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if ((node->flag & SELECT) && !(node->flag & NODE_TEST)) { - node_duplicate_reparent_recursive(node); + node_duplicate_reparent_recursive(node_map, node); } /* only has to check old nodes */ @@ -1344,7 +1350,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { /* has been set during copy above */ - bNode *newnode = node->new_node; + bNode *newnode = node_map.lookup(node); nodeSetSelected(node, false); node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE); @@ -2094,47 +2100,48 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) BKE_node_clipboard_clear(); BKE_node_clipboard_init(ntree); + Map<const bNode *, bNode *> node_map; + Map<const bNodeSocket *, bNodeSocket *> socket_map; + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { /* No ID refcounting, this node is virtual, * detached from any actual Blender data currently. */ - bNode *new_node = BKE_node_copy_store_new_pointers( - nullptr, node, LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN); - BKE_node_clipboard_add_node(new_node); + bNode *new_node = blender::bke::node_copy_with_mapping(nullptr, + *node, + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_MAIN, + false, + socket_map); + node_map.add_new(node, new_node); } } - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->flag & SELECT) { - bNode *new_node = node->new_node; - - /* ensure valid pointers */ - if (new_node->parent) { - /* parent pointer must be redirected to new node or detached if parent is - * not copied */ - if (new_node->parent->flag & NODE_SELECT) { - new_node->parent = new_node->parent->new_node; - } - else { - nodeDetachNode(new_node); - } + for (bNode *new_node : node_map.values()) { + BKE_node_clipboard_add_node(new_node); + + /* Parent pointer must be redirected to new node or detached if parent is not copied. */ + if (new_node->parent) { + if (node_map.contains(new_node->parent)) { + new_node->parent = node_map.lookup(new_node->parent); + } + else { + nodeDetachNode(new_node); } } } - /* Copy links between selected nodes. - * NOTE: this depends on correct node->new_node and sock->new_sock pointers from above copy! */ - + /* Copy links between selected nodes. */ LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { - /* This creates new links between copied nodes. */ - if (link->tonode && (link->tonode->flag & NODE_SELECT) && link->fromnode && - (link->fromnode->flag & NODE_SELECT)) { - bNodeLink *newlink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "bNodeLink"); + BLI_assert(link->tonode); + BLI_assert(link->fromnode); + if (link->tonode->flag & NODE_SELECT && link->fromnode->flag & NODE_SELECT) { + bNodeLink *newlink = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), __func__); newlink->flag = link->flag; - newlink->tonode = link->tonode->new_node; - newlink->tosock = link->tosock->new_sock; - newlink->fromnode = link->fromnode->new_node; - newlink->fromsock = link->fromsock->new_sock; + newlink->tonode = node_map.lookup(link->tonode); + newlink->tosock = socket_map.lookup(link->tosock); + newlink->fromnode = node_map.lookup(link->fromnode); + newlink->fromsock = socket_map.lookup(link->fromsock); BKE_node_clipboard_add_link(newlink); } @@ -2229,28 +2236,34 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) } mul_v2_fl(center, 1.0 / num_nodes); + Map<const bNode *, bNode *> node_map; + Map<const bNodeSocket *, bNodeSocket *> socket_map; + /* copy nodes from clipboard */ LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) { - bNode *new_node = BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); + bNode *new_node = blender::bke::node_copy_with_mapping( + ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map); + node_map.add_new(node, new_node); + } + for (bNode *new_node : node_map.values()) { /* pasted nodes are selected */ nodeSetSelected(new_node, true); - } - /* reparent copied nodes */ - LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) { - bNode *new_node = node->new_node; + /* The parent pointer must be redirected to new node. */ if (new_node->parent) { - new_node->parent = new_node->parent->new_node; + if (node_map.contains(new_node->parent)) { + new_node->parent = node_map.lookup(new_node->parent); + } } } LISTBASE_FOREACH (bNodeLink *, link, clipboard_links_lb) { nodeAddLink(ntree, - link->fromnode->new_node, - link->fromsock->new_sock, - link->tonode->new_node, - link->tosock->new_sock); + node_map.lookup(link->fromnode), + socket_map.lookup(link->fromsock), + node_map.lookup(link->tonode), + socket_map.lookup(link->tosock)); } Main *bmain = CTX_data_main(C); diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index 290ed172a48..ceeb42832ea 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -62,6 +62,7 @@ #include "node_intern.hh" /* own include */ using blender::float2; +using blender::Map; /* -------------------------------------------------------------------- */ /** \name Local Utilities @@ -220,21 +221,15 @@ static void animation_basepath_change_free(AnimationBasePathChange *basepath_cha /* returns 1 if its OK */ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) { - /* Clear new pointers, set in #ntreeCopyTree_ex_new_pointers. */ - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - node->new_node = nullptr; - } - ListBase anim_basepaths = {nullptr, nullptr}; LinkNode *nodes_delayed_free = nullptr; - bNodeTree *ngroup = (bNodeTree *)gnode->id; /* wgroup is a temporary copy of the NodeTree we're merging in * - all of wgroup's nodes are copied across to their new home * - ngroup (i.e. the source NodeTree) is left unscathed * - temp copy. do change ID usercount for the copies */ - bNodeTree *wgroup = ntreeCopyTree_ex_new_pointers(ngroup, bmain, true); + bNodeTree *wgroup = ntreeCopyTree(bmain, ntree); /* Add the nodes into the ntree */ LISTBASE_FOREACH_MUTABLE (bNode *, node, &wgroup->nodes) { @@ -455,13 +450,11 @@ static bool node_group_separate_selected( nodeSetSelected(node, false); } - /* clear new pointers, set in BKE_node_copy_ex(). */ - LISTBASE_FOREACH (bNode *, node, &ngroup.nodes) { - node->new_node = nullptr; - } - ListBase anim_basepaths = {nullptr, nullptr}; + Map<const bNode *, bNode *> node_map; + Map<const bNodeSocket *, bNodeSocket *> socket_map; + /* add selected nodes into the ntree */ LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup.nodes) { if (!(node->flag & NODE_SELECT)) { @@ -477,7 +470,9 @@ static bool node_group_separate_selected( bNode *newnode; if (make_copy) { /* make a copy */ - newnode = BKE_node_copy_store_new_pointers(&ngroup, node, LIB_ID_COPY_DEFAULT); + newnode = blender::bke::node_copy_with_mapping( + &ngroup, *node, LIB_ID_COPY_DEFAULT, true, socket_map); + node_map.add_new(node, newnode); } else { /* use the existing node */ @@ -526,10 +521,10 @@ static bool node_group_separate_selected( /* make a copy of internal links */ if (fromselect && toselect) { nodeAddLink(&ntree, - link->fromnode->new_node, - link->fromsock->new_sock, - link->tonode->new_node, - link->tosock->new_sock); + node_map.lookup(link->fromnode), + socket_map.lookup(link->fromsock), + node_map.lookup(link->tonode), + socket_map.lookup(link->tosock)); } } else { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5d51d8eb606..0d106c6b9eb 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -95,7 +95,7 @@ typedef struct SocketDeclarationHandle SocketDeclarationHandle; #endif typedef struct bNodeSocket { - struct bNodeSocket *next, *prev, *new_sock; + struct bNodeSocket *next, *prev; /** User-defined properties. */ IDProperty *prop; @@ -245,7 +245,7 @@ typedef enum eNodeSocketFlag { /** TODO: Limit data in #bNode to what we want to see saved. */ typedef struct bNode { - struct bNode *next, *prev, *new_node; + struct bNode *next, *prev; /** User-defined properties. */ IDProperty *prop; diff --git a/source/blender/nodes/composite/node_composite_tree.cc b/source/blender/nodes/composite/node_composite_tree.cc index 54967c82562..d601c426319 100644 --- a/source/blender/nodes/composite/node_composite_tree.cc +++ b/source/blender/nodes/composite/node_composite_tree.cc @@ -118,19 +118,6 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree) } } - bNodeSocket *output_sock = (bNodeSocket *)node->outputs.first; - bNodeSocket *local_output_sock = (bNodeSocket *)local_node->outputs.first; - while (output_sock != nullptr) { - local_output_sock->cache = output_sock->cache; - output_sock->cache = nullptr; - /* This is actually link to original: someone was just lazy enough and tried to save few - * bytes in the cost of readability. */ - local_output_sock->new_sock = output_sock; - - output_sock = output_sock->next; - local_output_sock = local_output_sock->next; - } - node = node->next; local_node = local_node->next; } @@ -150,11 +137,11 @@ static void local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree) BKE_node_preview_merge_tree(ntree, localtree, true); for (lnode = (bNode *)localtree->nodes.first; lnode; lnode = lnode->next) { - if (ntreeNodeExists(ntree, lnode->new_node)) { + if (bNode *orig_node = nodeFindNodebyName(ntree, lnode->name)) { if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { if (lnode->id && (lnode->flag & NODE_DO_OUTPUT)) { /* image_merge does sanity check for pointers */ - BKE_image_merge(bmain, (Image *)lnode->new_node->id, (Image *)lnode->id); + BKE_image_merge(bmain, (Image *)orig_node->id, (Image *)lnode->id); } } else if (lnode->type == CMP_NODE_MOVIEDISTORTION) { @@ -162,20 +149,19 @@ static void local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree) * and to achieve much better performance on further calls this context should be * copied back to original node */ if (lnode->storage) { - if (lnode->new_node->storage) { - BKE_tracking_distortion_free((MovieDistortion *)lnode->new_node->storage); + if (orig_node->storage) { + BKE_tracking_distortion_free((MovieDistortion *)orig_node->storage); } - lnode->new_node->storage = BKE_tracking_distortion_copy( - (MovieDistortion *)lnode->storage); + orig_node->storage = BKE_tracking_distortion_copy((MovieDistortion *)lnode->storage); } } for (lsock = (bNodeSocket *)lnode->outputs.first; lsock; lsock = lsock->next) { - if (ntreeOutputExists(lnode->new_node, lsock->new_sock)) { - lsock->new_sock->cache = lsock->cache; + if (bNodeSocket *orig_socket = nodeFindSocket(orig_node, SOCK_OUT, lsock->identifier)) { + orig_socket->cache = lsock->cache; lsock->cache = nullptr; - lsock->new_sock = nullptr; + orig_socket = nullptr; } } } diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index b19835fae19..8f4bffe5b30 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -659,7 +659,7 @@ static bNode *ntree_shader_copy_branch(bNodeTree *ntree, LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->tmp_flag >= 0) { int id = node->tmp_flag; - nodes_copy[id] = BKE_node_copy_ex( + nodes_copy[id] = BKE_node_copy( ntree, node, LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN, false); nodes_copy[id]->tmp_flag = -2; /* Copy */ /* Make sure to clear all sockets links as they are invalid. */ |