[Bf-blender-cvs] [6ec3656] openvdb: Generalized node function for mapping existing inputs/outputs on a dynamically changing socket layout.

Lukas Tönne noreply at git.blender.org
Tue Jun 9 12:13:54 CEST 2015


Commit: 6ec3656e9784695b8a90ea0926fe601ef31fab65
Author: Lukas Tönne
Date:   Tue Jun 9 11:53:51 2015 +0200
Branches: openvdb
https://developer.blender.org/rB6ec3656e9784695b8a90ea0926fe601ef31fab65

Generalized node function for mapping existing inputs/outputs on a
dynamically changing socket layout.

This is used for a couple of nodes which create a custom set of inputs
or outputs based on internal data (e.g. image or cache files with
arbitrary data layers). The task is to take existing connections to the
node and relink them to the new socket layout, usually based on socket
names. This keeps node trees working as much as possible even when the
user changes the node.

Multilayer image nodes were already doing this, now OpenVDB shader nodes
can share the same function. If it can be represented in the RNA, the
OSL script node might use the same method (currently not feasible due
to callbacks).

===================================================================

M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.c
M	source/blender/nodes/composite/nodes/node_composite_image.c
M	source/blender/nodes/shader/nodes/node_shader_openvdb.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 2e59dd7..d19b0c9 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -453,6 +453,14 @@ struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, struct bNode
 void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
 void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
 
+typedef void (*CreateSocketsCB)(void *userdata, struct bNodeTree *ntree, struct bNode *node);
+typedef void (*SyncSocketCB)(void *userdata, struct bNode *node, struct bNodeSocket *newsock, struct bNodeSocket *oldsock);
+/* create_outputs_cb must create new sockets using nodeAddSocket/nodeAddStaticSocket
+ * sync_output_cb is optional, for copying settings from old to new socket if needed
+ */
+void nodeSyncInputs(struct bNodeTree *ntree, struct bNode *node, CreateSocketsCB create_inputs_cb, SyncSocketCB sync_input_cb, void *userdata);
+void nodeSyncOutputs(struct bNodeTree *ntree, struct bNode *node, CreateSocketsCB create_outputs_cb, SyncSocketCB sync_output_cb, void *userdata);
+
 struct bNode	*nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
 struct bNode	*nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
 void            nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 0479930..22d149c 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -739,6 +739,92 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
 	node->update |= NODE_UPDATE;
 }
 
+static bNodeSocket *node_socket_find_match(bNodeSocket *newsock, ListBase *oldsocklist)
+{
+	bNodeSocket *sock;
+	
+	for (sock = oldsocklist->first; sock; sock = sock->next)
+		if (STREQ(sock->name, newsock->name))
+			return sock;
+	return NULL;
+}
+
+static bNodeSocket *node_socket_relink(ListBase *newsocklist, bNodeSocket *oldsock, int oldindex, bool use_index_fallback)
+{
+	bNodeSocket *sock;
+	
+	/* first try to find matching socket name */
+	for (sock = newsocklist->first; sock; sock = sock->next)
+		if (STREQ(sock->name, oldsock->name))
+			return sock;
+	
+	if (use_index_fallback)
+		/* no matching name, simply link to same index */
+		return BLI_findlink(newsocklist, oldindex);
+	else
+		return NULL;
+}
+
+static void node_sync_sockets(bNodeTree *ntree, bNode *node, ListBase *socklist, CreateSocketsCB create_sockets_cb, SyncSocketCB sync_socket_cb, void *userdata)
+{
+	bNodeSocket *newsock, *oldsock, *oldsock_next;
+	ListBase oldsocklist;
+	int oldindex;
+	bNodeLink *link;
+	
+	/* store current nodes in oldsocklist, then clear socket list */
+	oldsocklist = *socklist;
+	BLI_listbase_clear(socklist);
+	
+	/* create new sockets for the node */
+	create_sockets_cb(userdata, ntree, node);
+	
+	/* copy settings from the old to the new socket, if necessary */
+	if (sync_socket_cb) {
+		for (newsock = socklist->first; newsock; newsock = newsock->next) {
+			oldsock = node_socket_find_match(newsock, &oldsocklist);
+			if (oldsock)
+				sync_socket_cb(userdata, node, newsock, oldsock);
+		}
+	}
+	
+	/* move links to new socket */
+	for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) {
+		/* XXX falling back on index mapping does not appear to be very useful
+		 * for dynamically changing sockets, so it's disabled for now
+		 */
+		newsock = node_socket_relink(socklist, oldsock, oldindex, false);
+		if (newsock) {
+			for (link = ntree->links.first; link; link = link->next) {
+				if (link->fromsock == oldsock)
+					link->fromsock = newsock;
+			}
+		}
+	}
+	
+	/* delete old sockets
+	 * XXX oldsock is not actually in the socklist any more,
+	 * but the nodeRemoveSocket function works anyway. In future this
+	 * should become part of the core code, so can take care of this behavior.
+	 */
+	for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) {
+		oldsock_next = oldsock->next;
+		if (oldsock->storage)
+			MEM_freeN(oldsock->storage);
+		nodeRemoveSocket(ntree, node, oldsock);
+	}
+}
+
+void nodeSyncInputs(bNodeTree *ntree, bNode *node, CreateSocketsCB create_inputs_cb, SyncSocketCB sync_input_cb, void *userdata)
+{
+	node_sync_sockets(ntree, node, &node->inputs, create_inputs_cb, sync_input_cb, userdata);
+}
+
+void nodeSyncOutputs(bNodeTree *ntree, bNode *node, CreateSocketsCB create_outputs_cb, SyncSocketCB sync_output_cb, void *userdata)
+{
+	node_sync_sockets(ntree, node, &node->outputs, create_outputs_cb, sync_output_cb, userdata);
+}
+
 /* finds a node based on its name */
 bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
 {
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 19e9344..3a957ce 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -200,7 +200,7 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node,
 	}
 }
 
-static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
+static void cmp_node_image_create_outputs(void *UNUSED(userdata), bNodeTree *ntree, bNode *node)
 {
 	Image *ima = (Image *)node->id;
 	if (ima) {
@@ -244,80 +244,9 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
 		cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA);
 }
 
-static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
-{
-	bNodeSocket *sock;
-	
-	for (sock = oldsocklist->first; sock; sock = sock->next)
-		if (STREQ(sock->name, newsock->name))
-			return sock;
-	return NULL;
-}
-
-static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
-{
-	bNodeSocket *sock;
-	
-	/* first try to find matching socket name */
-	for (sock = node->outputs.first; sock; sock = sock->next)
-		if (STREQ(sock->name, oldsock->name))
-			return sock;
-	
-	/* no matching name, simply link to same index */
-	return BLI_findlink(&node->outputs, oldindex);
-}
-
-static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
-{
-	/* pass */
-}
-
-/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
 static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
 {
-	bNodeSocket *newsock, *oldsock, *oldsock_next;
-	ListBase oldsocklist;
-	int oldindex;
-	bNodeLink *link;
-	
-	/* store current nodes in oldsocklist, then clear socket list */
-	oldsocklist = node->outputs;
-	BLI_listbase_clear(&node->outputs);
-	
-	/* XXX make callback */
-	cmp_node_image_create_outputs(ntree, node);
-	
-	for (newsock = node->outputs.first; newsock; newsock = newsock->next) {
-		/* XXX make callback */
-		oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
-		if (oldsock) {
-			/* XXX make callback */
-			cmp_node_image_sync_output(node, newsock, oldsock);
-		}
-	}
-	
-	/* move links to new socket */
-	for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) {
-		newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
-		
-		if (newsock) {
-			for (link = ntree->links.first; link; link = link->next) {
-				if (link->fromsock == oldsock)
-					link->fromsock = newsock;
-			}
-		}
-	}
-	
-	/* delete old sockets
-	 * XXX oldsock is not actually in the node->outputs list any more,
-	 * but the nodeRemoveSocket function works anyway. In future this
-	 * should become part of the core code, so can take care of this behavior.
-	 */
-	for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) {
-		oldsock_next = oldsock->next;
-		MEM_freeN(oldsock->storage);
-		nodeRemoveSocket(ntree, node, oldsock);
-	}
+	nodeSyncOutputs(ntree, node, cmp_node_image_create_outputs, NULL, NULL);
 }
 
 static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
diff --git a/source/blender/nodes/shader/nodes/node_shader_openvdb.c b/source/blender/nodes/shader/nodes/node_shader_openvdb.c
index 2b2c1f5..ebbb64f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_openvdb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_openvdb.c
@@ -61,19 +61,6 @@ static void node_shader_copy_openvdb(bNodeTree *UNUSED(dest_ntree), bNode *dst_n
 }
 
 #ifdef WITH_OPENVDB
-static bNodeSocket *node_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
-{
-	bNodeSocket *sock;
-
-	/* first try to find matching socket name */
-	for (sock = node->outputs.first; sock; sock = sock->next)
-		if (STREQ(sock->name, oldsock->name))
-			return sock;
-
-	/* no matching name, simply link to same index */
-	return BLI_findlink(&node->outputs, oldindex);
-}
-
 static void node_openvdb_get_info(void *userdata, const char *name, const char *value_type, bool is_color)
 {
 	NodeShaderOpenVDB *vdb = userdata;
@@ -96,8 +83,9 @@ static void node_openvdb_get_info(void *userdata, const char *name, const char *
 	BLI_addtail(&vdb->grid_info, info);
 }
 
-static void node_openvdb_get_sockets(Main *bmain, bNodeTree *ntree, bNode *node)
+static void node_openvdb_create_sockets(void *userdata, bNodeTree *ntree, bNode *node)
 {
+	Main *bmain = userdata;
 	NodeShaderOpenVDB *vdb = node->storage;
 	OpenVDBGridInfo *info;
 	char *filename;
@@ -132,32 +120,7 @@ static void node_openvdb_get_sockets(Main *bmain, bNodeTree *ntree, bNode *node)
 
 void ntreeUpdateOpenVDBNode(Main *bmain, bNodeTree *ntree, bNode *node)
 {
-	bNodeSocket *newsock, *oldsock, *oldsock_next;
-	ListBase oldsocklist;
-	bNodeLink *link;
-	int oldindex;
-
-	oldsocklist = node->outputs;
-	BLI_listbase_clear(&node->outputs);
-
-	node_openvdb_get_sockets(bmain, ntree, node);
-
-	/* move links to new socket */
-	for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) {
-		newsock = node_output_relink(node, oldsock, oldindex);
-
-		if (newsock) {
-			for (l

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list