Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-12-22 17:47:46 +0300
committerHans Goudey <h.goudey@me.com>2021-12-22 17:47:46 +0300
commitfdc4a1a590d8befb1ff9ab1de3f02d82aa46d539 (patch)
tree32f92586f0de79d5f7762999b18fa03f036f9648 /source/blender
parentd6224db8f17f7035d8240bb5b9d28ce709cd3cb4 (diff)
Nodes: Refactor to remove node and socket "new" pointers
These pointers point to the new nodes when duplicating, and their even used to point to "original" nodes for "localized" trees. They're just a bad design decision that make code confusing and buggy. Instead, node copy functions now optionally add to a map of old to new socket pointers. The case where the compositor abused these pointers as "original" pointers are handled by looking up the string node names. Differential Revision: https://developer.blender.org/D13518
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h41
-rw-r--r--source/blender/blenkernel/intern/node.cc251
-rw-r--r--source/blender/blenloader/intern/versioning_250.c1
-rw-r--r--source/blender/editors/space_node/node_edit.cc115
-rw-r--r--source/blender/editors/space_node/node_group.cc29
-rw-r--r--source/blender/makesdna/DNA_node_types.h4
-rw-r--r--source/blender/nodes/composite/node_composite_tree.cc30
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c2
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. */