diff options
Diffstat (limited to 'source/blender/blenkernel/intern/node.c')
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 152 |
1 files changed, 105 insertions, 47 deletions
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 757571b9cf6..788b185c6eb 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -74,6 +74,11 @@ #include "NOD_shader.h" #include "NOD_texture.h" +/* Fallback types for undefined tree, nodes, sockets */ +bNodeTreeType NodeTreeTypeUndefined; +bNodeType NodeTypeUndefined; +bNodeSocketType NodeSocketTypeUndefined; + static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) { @@ -101,12 +106,11 @@ static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType /* Note: This function is called to initialize node data based on the type. * The bNodeType may not be registered at creation time of the node, * so this can be delayed until the node type gets registered. - * The node->typeinfo must not be used in that case until it is defined! */ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node) { bNodeType *ntype = node->typeinfo; - if (!ntype) + if (ntype == &NodeTypeUndefined) return; /* only do this once */ @@ -151,22 +155,24 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node) static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo) { - ntree->typeinfo = typeinfo; - if (typeinfo) { + ntree->typeinfo = typeinfo; + /* deprecated integer type */ ntree->type = typeinfo->type; } else { + ntree->typeinfo = &NodeTreeTypeUndefined; + ntree->init &= ~NTREE_TYPE_INIT; } } static void node_set_typeinfo(const struct bContext *C, bNodeTree *ntree, bNode *node, bNodeType *typeinfo) { - node->typeinfo = typeinfo; - if (typeinfo) { + node->typeinfo = typeinfo; + /* deprecated integer type */ node->type = typeinfo->type; @@ -174,21 +180,25 @@ static void node_set_typeinfo(const struct bContext *C, bNodeTree *ntree, bNode node_init(C, ntree, node); } else { + node->typeinfo = &NodeTypeUndefined; + ntree->init &= ~NTREE_TYPE_INIT; } } static void node_socket_set_typeinfo(bNodeTree *ntree, bNodeSocket *sock, bNodeSocketType *typeinfo) { - sock->typeinfo = typeinfo; - if (typeinfo) { + sock->typeinfo = typeinfo; + if (sock->default_value == NULL) { /* initialize the default_value pointer used by standard socket types */ node_socket_init_default_value(sock); } } else { + sock->typeinfo = &NodeSocketTypeUndefined; + ntree->init &= ~NTREE_TYPE_INIT; } } @@ -301,14 +311,14 @@ void ntreeTypeFreeLink(bNodeTreeType *nt) BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type); } -GHashIterator *ntreeTypeGetIterator(void) +bool ntreeIsRegistered(bNodeTree *ntree) { - return BLI_ghashIterator_new(nodetreetypes_hash); + return (ntree->typeinfo != &NodeTreeTypeUndefined); } -int ntreeIsValid(bNodeTree *ntree) +GHashIterator *ntreeTypeGetIterator(void) { - return (ntree && (ntree->init & NTREE_TYPE_INIT)); + return BLI_ghashIterator_new(nodetreetypes_hash); } bNodeType *nodeTypeFind(const char *idname) @@ -370,6 +380,11 @@ void nodeUnregisterType(bNodeType *nt) BLI_ghash_remove(nodetypes_hash, nt->idname, NULL, node_free_type); } +bool nodeIsRegistered(bNode *node) +{ + return (node->typeinfo != &NodeTypeUndefined); +} + GHashIterator *nodeTypeGetIterator(void) { return BLI_ghashIterator_new(nodetypes_hash); @@ -410,6 +425,11 @@ void nodeUnregisterSocketType(bNodeSocketType *st) BLI_ghash_remove(nodesockettypes_hash, st->idname, NULL, node_free_socket_type); } +bool nodeSocketIsRegistered(bNodeSocket *sock) +{ + return (sock->typeinfo != &NodeSocketTypeUndefined); +} + GHashIterator *nodeSocketTypeGetIterator(void) { return BLI_ghashIterator_new(nodesockettypes_hash); @@ -1329,7 +1349,7 @@ static void node_preview_init_tree_recursive(bNodeInstanceHash *previews, bNodeT BKE_node_preview_verify(previews, key, xsize, ysize, create); } - if (node->type == NODE_GROUP) + if (node->type == NODE_GROUP && node->id) node_preview_init_tree_recursive(previews, (bNodeTree *)node->id, key, xsize, ysize, create); } } @@ -1354,7 +1374,7 @@ static void node_preview_tag_used_recursive(bNodeInstanceHash *previews, bNodeTr if (BKE_node_preview_used(node)) BKE_node_instance_hash_tag_key(previews, key); - if (node->type == NODE_GROUP) + if (node->type == NODE_GROUP && node->id) node_preview_tag_used_recursive(previews, (bNodeTree *)node->id, key); } } @@ -1433,18 +1453,38 @@ void BKE_node_preview_sync_tree(bNodeTree *to_ntree, bNodeTree *from_ntree) } } -void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree) +void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool remove_old) { - /* free old previews */ - if (to_ntree->previews) - BKE_node_instance_hash_free(to_ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free); - - /* transfer previews */ - to_ntree->previews = from_ntree->previews; - from_ntree->previews = NULL; - - /* clean up, in case any to_ntree nodes have been removed */ - BKE_node_preview_remove_unused(to_ntree); + if (remove_old || !to_ntree->previews) { + /* free old previews */ + if (to_ntree->previews) + BKE_node_instance_hash_free(to_ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free); + + /* transfer previews */ + to_ntree->previews = from_ntree->previews; + from_ntree->previews = NULL; + + /* clean up, in case any to_ntree nodes have been removed */ + BKE_node_preview_remove_unused(to_ntree); + } + else { + bNodeInstanceHashIterator iter; + + if (from_ntree->previews) { + NODE_INSTANCE_HASH_ITER(iter, from_ntree->previews) { + bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); + bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + + /* replace existing previews */ + BKE_node_instance_hash_remove(to_ntree->previews, key, (bNodeInstanceValueFP)BKE_node_preview_free); + BKE_node_instance_hash_insert(to_ntree->previews, key, preview); + } + + /* Note: NULL free function here, because pointers have already been moved over to to_ntree->previews! */ + BKE_node_instance_hash_free(from_ntree->previews, NULL); + from_ntree->previews = NULL; + } + } } /* hack warning! this function is only used for shader previews, and @@ -1887,7 +1927,7 @@ int ntreeOutputExists(bNode *node, bNodeSocket *testsock) /* returns localized tree for execution in threads */ bNodeTree *ntreeLocalize(bNodeTree *ntree) { - if (ntreeIsValid(ntree)) { + if (ntree) { bNodeTree *ltree; bNode *node; @@ -1944,13 +1984,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) /* is called by jobs manager, outside threads, so it doesnt happen during draw */ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) { - if (localtree && ntreeIsValid(ntree)) { - /* XXX syncing was disabled for compositor nodes. - * It has to be ensured that there is no concurrent read/write access! - * Possibly needs a mutex lock or a flag to disable for certain tree types ... - */ - BKE_node_preview_sync_tree(ntree, localtree); - + if (localtree && ntree) { if (ntree->typeinfo->local_sync) ntree->typeinfo->local_sync(localtree, ntree); } @@ -1960,9 +1994,7 @@ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) /* we have to assume the editor already changed completely */ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) { - if (localtree && ntreeIsValid(ntree)) { - BKE_node_preview_merge_tree(ntree, localtree); - + if (localtree && ntree) { if (ntree->typeinfo->local_merge) ntree->typeinfo->local_merge(localtree, ntree); @@ -2006,14 +2038,14 @@ static bNodeSocket *make_socket_template(bNodeTree *ntree, int in_out, * but reconstructing own_index in writefile.c would require parsing the identifier string. */ -#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) || defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif sock->own_index = own_index; -#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) || defined(__clang__) # pragma GCC diagnostic pop #endif @@ -2425,7 +2457,7 @@ typedef struct bNodeClipboard { int type; } bNodeClipboard; -bNodeClipboard node_clipboard = {{0}}; +static bNodeClipboard node_clipboard = {{NULL}}; void BKE_node_clipboard_init(struct bNodeTree *ntree) { @@ -2831,11 +2863,8 @@ void ntreeVerifyNodes(struct Main *main, struct ID *id) FOREACH_NODETREE(main, ntree, owner_id) { bNode *node; - if (!ntreeIsValid(ntree)) - return; - for (node = ntree->nodes.first; node; node = node->next) - if (node->typeinfo && node->typeinfo->verifyfunc) + if (node->typeinfo->verifyfunc) node->typeinfo->verifyfunc(ntree, node, id); } FOREACH_NODETREE_END } @@ -2844,15 +2873,14 @@ void ntreeUpdateTree(bNodeTree *ntree) { bNode *node; + if (!ntree) + return; + /* avoid reentrant updates, can be caused by RNA update callbacks */ if (ntree->is_updating) return; ntree->is_updating = TRUE; - /* only if types are initialized */ - if (!ntreeIsValid(ntree)) - return; - if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) { /* set the bNodeSocket->link pointers */ ntree_update_link_pointers(ntree); @@ -3239,6 +3267,34 @@ void node_type_compatibility(struct bNodeType *ntype, short compatibility) ntype->compatibility = compatibility; } +/* callbacks for undefined types */ + +static int node_undefined_poll(bNodeType *UNUSED(ntype), bNodeTree *UNUSED(nodetree)) +{ + /* this type can not be added deliberately, it's just a placeholder */ + return false; +} + +/* register fallback types used for undefined tree, nodes, sockets */ +static void register_undefined_types(void) +{ + /* Note: these types are not registered in the type hashes, + * they are just used as placeholders in case the actual types are not registered. + */ + + strcpy(NodeTreeTypeUndefined.idname, "NodeTreeUndefined"); + strcpy(NodeTreeTypeUndefined.ui_name, "Undefined"); + strcpy(NodeTreeTypeUndefined.ui_description, "Undefined Node Tree Type"); + + node_type_base_custom(&NodeTypeUndefined, "NodeUndefined", "Undefined", 0, 0); + NodeTypeUndefined.poll = node_undefined_poll; + + BLI_strncpy(NodeSocketTypeUndefined.idname, "NodeSocketUndefined", sizeof(NodeSocketTypeUndefined.idname)); + /* extra type info for standard socket types */ + NodeSocketTypeUndefined.type = SOCK_CUSTOM; + NodeSocketTypeUndefined.subtype = PROP_NONE; +} + static void registerCompositNodes(void) { register_node_type_cmp_group(); @@ -3464,6 +3520,8 @@ void init_nodesystem(void) nodetypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodetypes_hash gh"); nodesockettypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodesockettypes_hash gh"); + register_undefined_types(); + register_standard_node_socket_types(); register_node_tree_type_cmp(); |