| 
									
										
										
										
											2011-10-23 17:52:20 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							| 
									
										
										
										
											2012-10-15 23:11:59 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2007 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file blender/nodes/texture/node_texture_tree.c
 | 
					
						
							|  |  |  |  *  \ingroup nodes | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_texture_types.h"
 | 
					
						
							|  |  |  | #include "DNA_node_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_threads.h"
 | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-09 15:00:11 +00:00
										 |  |  | #include "BLF_translation.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_main.h"
 | 
					
						
							|  |  |  | #include "BKE_node.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 18:49:28 +00:00
										 |  |  | #include "node_common.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | #include "node_exec.h"
 | 
					
						
							|  |  |  | #include "node_util.h"
 | 
					
						
							|  |  |  | #include "NOD_texture.h"
 | 
					
						
							|  |  |  | #include "node_texture_util.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "RE_pipeline.h"
 | 
					
						
							|  |  |  | #include "RE_shader_ext.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Tex *tx; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	for (tx = main->tex.first; tx; tx = tx->id.next) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (tx->nodetree) { | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 			func(calldata, &tx->id, tx->nodetree); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-07 22:14:48 +00:00
										 |  |  | static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-16 15:01:46 +00:00
										 |  |  | 	func(calldata, NODE_CLASS_INPUT, N_("Input")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_OUTPUT, N_("Output")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_OP_COLOR, N_("Color")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_PATTERN, N_("Patterns")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_TEXTURE, N_("Textures")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_DISTORT, N_("Distort")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_GROUP, N_("Group")); | 
					
						
							|  |  |  | 	func(calldata, NODE_CLASS_LAYOUT, N_("Layout")); | 
					
						
							| 
									
										
										
										
											2011-11-07 22:14:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-27 17:38:16 +00:00
										 |  |  | static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bNode *node, *node_next; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-06-01 12:38:03 +00:00
										 |  |  | 	/* replace muted nodes and reroute nodes by internal links */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	for (node = localtree->nodes.first; node; node = node_next) { | 
					
						
							| 
									
										
										
										
											2012-02-27 17:38:16 +00:00
										 |  |  | 		node_next = node->next; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-06-01 12:38:03 +00:00
										 |  |  | 		if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { | 
					
						
							| 
									
										
										
										
											2012-02-27 17:38:16 +00:00
										 |  |  | 			nodeInternalRelink(localtree, node); | 
					
						
							|  |  |  | 			nodeFreeNode(localtree, node); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | static void local_sync(bNodeTree *localtree, bNodeTree *ntree) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bNode *lnode; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* copy over contents of previews */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (ntreeNodeExists(ntree, lnode->new_node)) { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 			bNode *node = lnode->new_node; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (node->preview && node->preview->rect) { | 
					
						
							|  |  |  | 				if (lnode->preview && lnode->preview->rect) { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 					int xsize = node->preview->xsize; | 
					
						
							|  |  |  | 					int ysize = node->preview->ysize; | 
					
						
							|  |  |  | 					memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4); | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 18:49:28 +00:00
										 |  |  | static void update(bNodeTree *ntree) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ntree_update_reroute_nodes(ntree); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | bNodeTreeType ntreeType_Texture = { | 
					
						
							|  |  |  | 	/* type */				NTREE_TEXTURE, | 
					
						
							|  |  |  | 	/* id_name */			"NTTexture Nodetree", | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* node_types */		{ NULL, NULL }, | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* free_cache */			NULL, | 
					
						
							|  |  |  | 	/* free_node_cache */		NULL, | 
					
						
							|  |  |  | 	/* foreach_nodetree */	foreach_nodetree, | 
					
						
							| 
									
										
										
										
											2011-11-07 22:14:48 +00:00
										 |  |  | 	/* foreach_nodeclass */	foreach_nodeclass, | 
					
						
							| 
									
										
										
										
											2012-02-27 17:38:16 +00:00
										 |  |  | 	/* localize */			localize, | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	/* local_sync */		local_sync, | 
					
						
							|  |  |  | 	/* local_merge */		NULL, | 
					
						
							| 
									
										
										
										
											2012-08-06 18:49:28 +00:00
										 |  |  | 	/* update */			update, | 
					
						
							| 
									
										
										
										
											2011-11-20 16:38:23 +00:00
										 |  |  | 	/* update_node */		NULL, | 
					
						
							|  |  |  | 	/* validate_link */		NULL, | 
					
						
							| 
									
										
										
										
											2012-10-25 16:49:06 +00:00
										 |  |  | 	/* update_internal_links */	node_update_internal_links_default | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ntreeTexTagAnimated(bNodeTree *ntree) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bNode *node; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (ntree == NULL) return 0; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	for (node = ntree->nodes.first; node; node = node->next) { | 
					
						
							|  |  |  | 		if (node->type == TEX_NODE_CURVE_TIME) { | 
					
						
							| 
									
										
										
										
											2011-10-19 17:08:35 +00:00
										 |  |  | 			nodeUpdate(ntree, node); | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		else if (node->type == NODE_GROUP) { | 
					
						
							|  |  |  | 			if (ntreeTexTagAnimated((bNodeTree *)node->id) ) { | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 				return 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-06 16:32:51 +00:00
										 |  |  | /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
 | 
					
						
							|  |  |  |  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data) | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bNodeTreeExec *exec; | 
					
						
							|  |  |  | 	bNode *node; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-09-06 16:32:51 +00:00
										 |  |  | 	if (use_tree_data) { | 
					
						
							|  |  |  | 		/* XXX hack: prevent exec data from being generated twice.
 | 
					
						
							|  |  |  | 		 * this should be handled by the renderer! | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if (ntree->execdata) | 
					
						
							|  |  |  | 			return ntree->execdata; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* common base initialization */ | 
					
						
							|  |  |  | 	exec = ntree_exec_begin(ntree); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* allocate the thread stack listbase array */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	for (node = exec->nodetree->nodes.first; node; node = node->next) | 
					
						
							|  |  |  | 		node->need_exec = 1; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-09-06 16:32:51 +00:00
										 |  |  | 	if (use_tree_data) { | 
					
						
							|  |  |  | 		/* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
 | 
					
						
							|  |  |  | 		 * which only store the ntree pointer. Should be fixed at some point! | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		ntree->execdata = exec; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return exec; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* free texture delegates */ | 
					
						
							|  |  |  | static void tex_free_delegates(bNodeTreeExec *exec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bNodeThreadStack *nts; | 
					
						
							|  |  |  | 	bNodeStack *ns; | 
					
						
							|  |  |  | 	int th, a; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	for (th = 0; th < BLENDER_MAX_THREADS; th++) | 
					
						
							|  |  |  | 		for (nts = exec->threadstack[th].first; nts; nts = nts->next) | 
					
						
							|  |  |  | 			for (ns = nts->stack, a = 0; a < exec->stacksize; a++, ns++) | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 				if (ns->data && !ns->is_copy) | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 					MEM_freeN(ns->data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-06 16:32:51 +00:00
										 |  |  | /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
 | 
					
						
							|  |  |  |  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data) | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (exec) { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		bNodeTree *ntree = exec->nodetree; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 		bNodeThreadStack *nts; | 
					
						
							|  |  |  | 		int a; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (exec->threadstack) { | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 			tex_free_delegates(exec); | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 			for (a = 0; a < BLENDER_MAX_THREADS; a++) { | 
					
						
							|  |  |  | 				for (nts = exec->threadstack[a].first; nts; nts = nts->next) | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 					if (nts->stack) MEM_freeN(nts->stack); | 
					
						
							|  |  |  | 				BLI_freelistN(&exec->threadstack[a]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			MEM_freeN(exec->threadstack); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 			exec->threadstack = NULL; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		ntree_exec_end(exec); | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2011-09-06 16:32:51 +00:00
										 |  |  | 		if (use_tree_data) { | 
					
						
							|  |  |  | 			/* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ | 
					
						
							|  |  |  | 			ntree->execdata = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ntreeTexExecTree( | 
					
						
							| 
									
										
										
										
											2012-10-15 23:11:59 +00:00
										 |  |  |         bNodeTree *nodes, | 
					
						
							|  |  |  |         TexResult *texres, | 
					
						
							|  |  |  |         float co[3], | 
					
						
							|  |  |  |         float dxt[3], float dyt[3], | 
					
						
							|  |  |  |         int osatex, | 
					
						
							|  |  |  |         const short thread, | 
					
						
							|  |  |  |         Tex *UNUSED(tex), | 
					
						
							|  |  |  |         short which_output, | 
					
						
							|  |  |  |         int cfra, | 
					
						
							|  |  |  |         int preview, | 
					
						
							|  |  |  |         ShadeInput *shi, | 
					
						
							|  |  |  |         MTex *mtex) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	TexCallData data; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	float *nor = texres->nor; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	int retval = TEX_INT; | 
					
						
							|  |  |  | 	bNodeThreadStack *nts = NULL; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	bNodeTreeExec *exec = nodes->execdata; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	data.co = co; | 
					
						
							|  |  |  | 	data.dxt = dxt; | 
					
						
							|  |  |  | 	data.dyt = dyt; | 
					
						
							|  |  |  | 	data.osatex = osatex; | 
					
						
							|  |  |  | 	data.target = texres; | 
					
						
							|  |  |  | 	data.do_preview = preview; | 
					
						
							|  |  |  | 	data.thread = thread; | 
					
						
							|  |  |  | 	data.which_output = which_output; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	data.cfra = cfra; | 
					
						
							|  |  |  | 	data.mtex = mtex; | 
					
						
							|  |  |  | 	data.shi = shi; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-10-31 17:00:59 +00:00
										 |  |  | 	/* ensure execdata is only initialized once */ | 
					
						
							|  |  |  | 	if (!exec) { | 
					
						
							|  |  |  | 		BLI_lock_thread(LOCK_NODES); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 		if (!nodes->execdata) | 
					
						
							| 
									
										
										
										
											2011-10-31 17:00:59 +00:00
										 |  |  | 			ntreeTexBeginExecTree(nodes, 1); | 
					
						
							|  |  |  | 		BLI_unlock_thread(LOCK_NODES); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		exec = nodes->execdata; | 
					
						
							| 
									
										
										
										
											2011-10-31 17:00:59 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	nts = ntreeGetThreadStack(exec, thread); | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	ntreeExecThreadNodes(exec, nts, &data, thread); | 
					
						
							|  |  |  | 	ntreeReleaseThreadStack(nts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (texres->nor) retval |= TEX_NOR; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 	retval |= TEX_RGB; | 
					
						
							|  |  |  | 	/* confusing stuff; the texture output node sets this to NULL to indicate no normal socket was set
 | 
					
						
							| 
									
										
										
										
											2012-06-30 22:49:33 +00:00
										 |  |  | 	 * however, the texture code checks this for other reasons (namely, a normal is required for material) */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	texres->nor = nor; | 
					
						
							| 
									
										
										
										
											2011-09-05 21:01:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return retval; | 
					
						
							|  |  |  | } |