diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 23 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 88 |
2 files changed, 90 insertions, 21 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b760be29dae..fb6096cd82f 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -225,12 +225,14 @@ typedef struct bNodeType { /// Free the node instance. void (*freefunc)(struct bNode *node); /// Make a copy of the node instance. - void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node); + void (*copyfunc)(struct bNodeTree *dest_ntree, + struct bNode *dest_node, + const struct bNode *src_node); /* Registerable API callback versions, called in addition to C callbacks */ void (*initfunc_api)(const struct bContext *C, struct PointerRNA *ptr); void (*freefunc_api)(struct PointerRNA *ptr); - void (*copyfunc_api)(struct PointerRNA *ptr, struct bNode *src_node); + void (*copyfunc_api)(struct PointerRNA *ptr, const struct bNode *src_node); /* can this node type be added to a node tree */ bool (*poll)(struct bNodeType *ntype, struct bNodeTree *nodetree); @@ -538,7 +540,20 @@ void nodeRemoveNode(struct Main *bmain, struct bNode *node, bool do_id_user); -struct bNode *BKE_node_copy_ex(struct bNodeTree *ntree, struct bNode *node_src, const int flag); +struct bNode *BKE_node_copy_ex(struct bNodeTree *ntree, + const struct bNode *node_src, + const int flag); + +/* 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 bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, @@ -730,7 +745,7 @@ void node_type_storage(struct bNodeType *ntype, void (*freefunc)(struct bNode *node), void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, - struct bNode *src_node)); + const struct bNode *src_node)); void node_type_label( struct bNodeType *ntype, void (*labelfunc)(struct bNodeTree *ntree, struct bNode *, char *label, int maxlen)); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index b7db434e234..d8b63dac99d 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -41,6 +41,7 @@ #include "DNA_linestyle_types.h" #include "BLI_listbase.h" +#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_path_util.h" #include "BLI_string.h" @@ -1008,10 +1009,8 @@ bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type) return nodeAddNode(C, ntree, idname); } -static void node_socket_copy(bNodeSocket *sock_dst, bNodeSocket *sock_src, const int flag) +static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag) { - sock_src->new_sock = sock_dst; - if (sock_src->prop) { sock_dst->prop = IDP_CopyProperty_ex(sock_src->prop, flag); } @@ -1029,7 +1028,7 @@ static void node_socket_copy(bNodeSocket *sock_dst, bNodeSocket *sock_src, const /* keep socket listorder identical, for copying links */ /* ntree is the target tree */ -bNode *BKE_node_copy_ex(bNodeTree *ntree, bNode *node_src, const int flag) +bNode *BKE_node_copy_ex(bNodeTree *ntree, const bNode *node_src, const int flag) { bNode *node_dst = MEM_callocN(sizeof(bNode), "dupli node"); bNodeSocket *sock_dst, *sock_src; @@ -1063,10 +1062,17 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, bNode *node_src, const int flag) for (link_dst = node_dst->internal_links.first, link_src = node_src->internal_links.first; link_dst != NULL; link_dst = link_dst->next, link_src = 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 = link_dst->fromsock->new_sock; - link_dst->tosock = link_dst->tosock->new_sock; + link_dst->fromsock = BLI_findlink(&node_dst->inputs, from_sock_index); + link_dst->tosock = BLI_findlink(&node_dst->outputs, to_sock_index); } if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { @@ -1077,7 +1083,6 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, bNode *node_src, const int flag) node_src->typeinfo->copyfunc(ntree, node_dst, node_src); } - node_src->new_node = node_dst; node_dst->new_node = NULL; bool do_copy_api = !((flag & LIB_ID_CREATE_NO_MAIN) || (flag & LIB_ID_COPY_LOCALIZE)); @@ -1095,6 +1100,30 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, bNode *node_src, const int flag) return node_dst; } +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); + /* Store mapping to the node itself. */ + node_src->new_node = new_node; + /* Store mapping to inputs. */ + bNodeSocket *new_input_sock = new_node->inputs.first; + bNodeSocket *input_sock_src = node_src->inputs.first; + while (new_input_sock != NULL) { + 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 = new_node->outputs.first; + bNodeSocket *output_sock_src = node_src->outputs.first; + while (new_output_sock != NULL) { + output_sock_src->new_sock = new_output_sock; + new_output_sock = new_output_sock->next; + output_sock_src = output_sock_src->next; + } + return new_node; +} + /* also used via rna api, so we check for proper input output direction */ bNodeLink *nodeAddLink( bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock) @@ -1402,23 +1431,45 @@ void BKE_node_tree_copy_data(Main *UNUSED(bmain), BLI_listbase_clear(&ntree_dst->nodes); BLI_listbase_clear(&ntree_dst->links); - for (bNode *node_src = ntree_src->nodes.first; node_src; node_src = node_src->next) { - BKE_node_copy_ex(ntree_dst, node_src, flag_subdata); + /* Since source nodes and sockets are unique pointers we can put everything in a single map. */ + GHash *new_pointers = BLI_ghash_ptr_new("BKE_node_tree_copy_data"); + + for (const bNode *node_src = ntree_src->nodes.first; node_src; node_src = node_src->next) { + bNode *new_node = BKE_node_copy_ex(ntree_dst, node_src, flag_subdata); + BLI_ghash_insert(new_pointers, (void *)node_src, new_node); + /* Store mapping to inputs. */ + bNodeSocket *new_input_sock = new_node->inputs.first; + const bNodeSocket *input_sock_src = node_src->inputs.first; + while (new_input_sock != NULL) { + 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 = new_node->outputs.first; + const bNodeSocket *output_sock_src = node_src->outputs.first; + while (new_output_sock != NULL) { + 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; + } } /* copy links */ BLI_duplicatelist(&ntree_dst->links, &ntree_src->links); for (link_dst = ntree_dst->links.first; link_dst; link_dst = link_dst->next) { - link_dst->fromnode = (link_dst->fromnode ? link_dst->fromnode->new_node : NULL); - link_dst->fromsock = (link_dst->fromsock ? link_dst->fromsock->new_sock : NULL); - link_dst->tonode = (link_dst->tonode ? link_dst->tonode->new_node : NULL); - link_dst->tosock = (link_dst->tosock ? link_dst->tosock->new_sock : NULL); + link_dst->fromnode = BLI_ghash_lookup_default(new_pointers, link_dst->fromnode, NULL); + link_dst->fromsock = BLI_ghash_lookup_default(new_pointers, link_dst->fromsock, NULL); + link_dst->tonode = BLI_ghash_lookup_default(new_pointers, link_dst->tonode, NULL); + link_dst->tosock = BLI_ghash_lookup_default(new_pointers, link_dst->tosock, NULL); /* update the link socket's pointer */ if (link_dst->tosock) { link_dst->tosock->link = link_dst; } } + BLI_ghash_free(new_pointers, NULL, NULL); + /* copy interface sockets */ BLI_duplicatelist(&ntree_dst->inputs, &ntree_src->inputs); for (sock_dst = ntree_dst->inputs.first, sock_src = ntree_src->inputs.first; sock_dst != NULL; @@ -2201,9 +2252,12 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) /* ensures only a single output node is enabled */ ntreeSetOutput(ntree); - for (node = ntree->nodes.first; node; node = node->next) { - /* store new_node pointer to original */ - node->new_node->original = node; + bNode *node_src = ntree->nodes.first; + bNode *node_local = ltree->nodes.first; + while (node_src != NULL) { + node_local->original = node_src; + node_src = node_src->next; + node_local = node_local->next; } if (ntree->typeinfo->localize) { @@ -3595,7 +3649,7 @@ void node_type_storage(bNodeType *ntype, void (*freefunc)(struct bNode *node), void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, - struct bNode *src_node)) + const struct bNode *src_node)) { if (storagename) { BLI_strncpy(ntype->storagename, storagename, sizeof(ntype->storagename)); |