[Bf-blender-cvs] [e0d4047] master: Bake-API: Test for cyclic node connection

Dalai Felinto noreply at git.blender.org
Wed Jul 23 16:47:10 CEST 2014


Commit: e0d40471364aafca967b6ebd5266ae7d7f78dee4
Author: Dalai Felinto
Date:   Wed Jul 23 11:33:29 2014 -0300
Branches: master
https://developer.blender.org/rBe0d40471364aafca967b6ebd5266ae7d7f78dee4

Bake-API: Test for cyclic node connection

If the active image node contributes to the final material shader
(meaning it's either directly or indirectly connected to an Output Node)
the user will receive an alert about circular dependency.

Similar to what we do for Blender internal the baking will still happen,
but the user will receive the alert which should prevent the image
saving to happen if the result was not intentional.

Core function to check for node output written by Lukas Toenne.

Reviewers: lukastoenne, campbellbarton

Differential Revision: https://developer.blender.org/D673

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

M	source/blender/blenkernel/BKE_node.h
M	source/blender/editors/include/ED_uvedit.h
M	source/blender/editors/object/object_bake_api.c
M	source/blender/editors/space_view3d/drawmesh.c
M	source/blender/editors/uvedit/uvedit_draw.c
M	source/blender/editors/uvedit/uvedit_ops.c
M	source/blender/editors/uvedit/uvedit_unwrap_ops.c
M	source/blender/nodes/intern/node_common.c

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

diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index c81133a..15e7efe 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -585,6 +585,9 @@ void            node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufu
 void            node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
 void            node_type_compatibility(struct bNodeType *ntype, short compatibility);
 
+/* ************** GENERIC NODE FUNCTIONS *************** */
+bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node);
+
 /* ************** COMMON NODES *************** */
 
 #define NODE_UNDEFINED	-2		/* node type is not registered */
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 04eb829..4b82fa4 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -54,7 +54,7 @@ void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Obje
 bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
 
 bool ED_object_get_active_image(struct Object *ob, int mat_nr,
-                                struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node);
+                                struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree);
 void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int mat_nr, struct Image *ima);
 
 bool ED_uvedit_test(struct Object *obedit);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index f264259..b3f3a56 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -51,6 +51,7 @@
 #include "BKE_image.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_modifier.h"
 #include "BKE_mesh.h"
@@ -367,10 +368,22 @@ static bool bake_object_check(Object *ob, ReportList *reports)
 	}
 
 	for (i = 0; i < ob->totcol; i++) {
-		ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
+		bNodeTree *ntree = NULL;
+		bNode *node = NULL;
+		ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);
 
 		if (image) {
-			ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+			ImBuf *ibuf;
+
+			if (node) {
+				if (BKE_node_is_connected_to_output(ntree, node)) {
+					BKE_reportf(reports, RPT_ERROR,
+					            "Circular dependency for image \"%s\" from object \"%s\"",
+					            image->id.name + 2, ob->id.name + 2);
+				}
+			}
+
+			ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
 
 			if (ibuf) {
 				BKE_image_release_ibuf(image, ibuf, lock);
@@ -477,7 +490,7 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
 
 	for (i = 0; i < tot_mat; i++) {
 		Image *image;
-		ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
+		ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
 
 		if ((image->id.flag & LIB_DOIT)) {
 			for (j = 0; j < i; j++) {
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 348e6e5..89babf9 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -941,7 +941,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
 	int texture_set = 0;
 
 	/* draw image texture if we find one */
-	if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
+	if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) {
 		/* get openl texture */
 		int mipmap = 1;
 		int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, false) : 0;
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 6eb8e52..0f60542 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -424,7 +424,7 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage)
 		
 		/* if no materials, assume a default material with no image */
 		if (ob->totcol)
-			ED_object_get_active_image(ob, a + 1, &image, NULL, NULL);
+			ED_object_get_active_image(ob, a + 1, &image, NULL, NULL, NULL);
 		else
 			image = NULL;
 
@@ -577,7 +577,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
 
 		if (new_shading_nodes) {
 			if (efa_act) {
-				ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL);
+				ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL, NULL);
 			}
 			else {
 				curimage = ima;
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index ed88c72..0d8b5a5 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -137,21 +137,24 @@ static bool is_image_texture_node(bNode *node)
 }
 
 bool ED_object_get_active_image(Object *ob, int mat_nr,
-                                Image **r_ima, ImageUser **r_iuser, bNode **r_node)
+                                Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree)
 {
 	Material *ma = give_current_material(ob, mat_nr);
-	bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
+	bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
+	bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
 
 	if (node && is_image_texture_node(node)) {
 		if (r_ima) *r_ima = (Image *)node->id;
 		if (r_iuser) *r_iuser = NULL;
 		if (r_node) *r_node = node;
+		if (r_ntree) *r_ntree = ntree;
 		return true;
 	}
 	
 	if (r_ima) *r_ima = NULL;
 	if (r_iuser) *r_iuser = NULL;
 	if (r_node) *r_node = node;
+	if (r_ntree) *r_ntree = ntree;
 
 	return false;
 }
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 7442e7b..335d8e6 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -201,7 +201,7 @@ void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, fl
 
 	if (efa) {
 		if (BKE_scene_use_new_shading_nodes(scene)) {
-			ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL);
+			ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
 		}
 		else {
 			MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index ae834f9..c58c9c9 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -336,6 +336,40 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
 			node_reroute_inherit_type_recursive(ntree, node);
 }
 
+static bool node_is_connected_to_output_recursive(bNodeTree *ntree, bNode *node)
+{
+	bNodeLink *link;
+
+	/* avoid redundant checks, and infinite loops in case of cyclic node links */
+	if (node->done)
+		return false;
+	node->done = 1;
+
+	/* main test, done before child loop so it catches output nodes themselves as well */
+	if (node->typeinfo->nclass == NODE_CLASS_OUTPUT && node->flag & NODE_DO_OUTPUT)
+		return true;
+
+	/* test all connected nodes, first positive find is sufficient to return true */
+	for (link = ntree->links.first; link; link = link->next) {
+		if (link->fromnode == node) {
+			if (node_is_connected_to_output_recursive(ntree, link->tonode))
+				return true;
+		}
+	}
+	return false;
+}
+
+bool BKE_node_is_connected_to_output(bNodeTree *ntree, bNode *node)
+{
+	bNode *tnode;
+
+	/* clear flags */
+	for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
+		tnode->done = 0;
+
+	return node_is_connected_to_output_recursive(ntree, node);
+}
+
 void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
 {
 	bNode *node;




More information about the Bf-blender-cvs mailing list