diff options
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.cc | 28 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 30 | ||||
-rw-r--r-- | source/blender/nodes/NOD_node_declaration.hh | 2 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_socket.cc | 8 |
5 files changed, 61 insertions, 9 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 9df3d7c544d..d4bc0245a61 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -731,6 +731,8 @@ void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available); int nodeSocketLinkLimit(const struct bNodeSocket *sock); +void nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node); + /* Node Clipboard */ void BKE_node_clipboard_init(const struct bNodeTree *ntree); void BKE_node_clipboard_clear(void); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index e6af587cbd7..61b90b44b03 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -653,6 +653,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) BLO_read_list(reader, &ntree->nodes); LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { node->typeinfo = nullptr; + node->declaration = nullptr; BLO_read_list(reader, &node->inputs); BLO_read_list(reader, &node->outputs); @@ -1014,10 +1015,8 @@ IDTypeInfo IDType_ID_NT = { static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) { if (ntype->declare != nullptr) { - blender::nodes::NodeDeclaration node_decl; - blender::nodes::NodeDeclarationBuilder builder{node_decl}; - ntype->declare(builder); - node_decl.build(*ntree, *node); + nodeDeclarationEnsure(ntree, node); + node->declaration->build(*ntree, *node); return; } bNodeSocketTemplate *sockdef; @@ -2216,6 +2215,10 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, bNodeLink *link_dst, *link_src; *node_dst = *node_src; + + /* Reset the declaration of the new node. */ + node_dst->declaration = nullptr; + /* can be called for nodes outside a node tree (e.g. clipboard) */ if (ntree) { if (unique_name) { @@ -3103,6 +3106,8 @@ static void node_free_node(bNodeTree *ntree, bNode *node) MEM_freeN(node->prop); } + delete node->declaration; + MEM_freeN(node); if (ntree) { @@ -3933,6 +3938,21 @@ int nodeSocketLinkLimit(const bNodeSocket *sock) return sock->limit; } +/** + * If the node implements a `declare` function, this function makes sure that `node->declaration` + * is up to date. + */ +void nodeDeclarationEnsure(bNodeTree *UNUSED(ntree), bNode *node) +{ + if (node->typeinfo->declare == nullptr) { + return; + } + + node->declaration = new blender::nodes::NodeDeclaration(); + blender::nodes::NodeDeclarationBuilder builder{*node->declaration}; + node->typeinfo->declare(builder); +} + /* ************** Node Clipboard *********** */ #define USE_NODE_CB_VALIDATE diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 82eabf6995c..c4cbc71762c 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -216,6 +216,16 @@ typedef enum eNodeSocketFlag { SOCK_HIDE_LABEL = (1 << 12), } eNodeSocketFlag; +/** Workaround to forward-declare C++ type in C header. */ +#ifdef __cplusplus +namespace blender::nodes { +class NodeDeclaration; +} +using NodeDeclarationHandle = blender::nodes::NodeDeclaration; +#else +typedef struct NodeDeclarationHandle NodeDeclarationHandle; +#endif + /* TODO: Limit data in bNode to what we want to see saved. */ typedef struct bNode { struct bNode *next, *prev, *new_node; @@ -315,6 +325,26 @@ typedef struct bNode { * needs to be a float to feed GPU_uniform. */ float sss_id; + + /** + * Describes the desired interface of the node. This is run-time data only. + * The actual interface of the node may deviate from the declaration temporarily. + * It's possible to sync the actual state of the node to the desired state. Currently, this is + * only done when a node is created or loaded. + * + * In the future, we may want to keep more data only in the declaration, so that it does not have + * to be synced to other places that are stored in files. That especially applies to data that + * can't be edited by users directly (e.g. min/max values of sockets, tooltips, ...). + * + * The declaration of a node can be recreated at any time when it is used. Caching it here is + * just a bit more efficient when it is used a lot. To make sure that the cache is up-to-date, + * call #nodeDeclarationEnsure before using it. + * + * Currently, the declaration is the same for every node of the same type. Going forward, that is + * intended to change though. Especially when nodes become more dynamic with respect to how many + * sockets they have. + */ + NodeDeclarationHandle *declaration; } bNode; /* node->flag */ diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index 52f4ac291d2..7ba4ac52b86 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -60,6 +60,8 @@ class NodeDeclaration { Span<SocketDeclarationPtr> inputs() const; Span<SocketDeclarationPtr> outputs() const; + + MEM_CXX_CLASS_ALLOC_FUNCS("NodeDeclaration") }; class NodeDeclarationBuilder { diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 8efd6c55459..31260f95242 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -269,11 +269,9 @@ void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user) return; } if (ntype->declare != nullptr) { - blender::nodes::NodeDeclaration node_decl; - blender::nodes::NodeDeclarationBuilder builder{node_decl}; - ntype->declare(builder); - if (!node_decl.matches(*node)) { - refresh_node(*ntree, *node, node_decl, do_id_user); + nodeDeclarationEnsure(ntree, node); + if (!node->declaration->matches(*node)) { + refresh_node(*ntree, *node, *node->declaration, do_id_user); } return; } |