608 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			608 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * ***** 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
 | |
|  * of the License, or (at your option) any later version. 
 | |
|  *
 | |
|  * 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): Lukas Toennne
 | |
|  *
 | |
|  * ***** END GPL LICENSE BLOCK *****
 | |
|  */
 | |
| 
 | |
| /** \file blender/nodes/intern/node_socket.c
 | |
|  *  \ingroup nodes
 | |
|  */
 | |
| 
 | |
| #include <limits.h>
 | |
| 
 | |
| #include "DNA_node_types.h"
 | |
| 
 | |
| #include "DNA_mesh_types.h"
 | |
| #include "DNA_meshdata_types.h"
 | |
| #include "DNA_object_types.h"
 | |
| #include "DNA_scene_types.h"
 | |
| 
 | |
| #include "BLI_listbase.h"
 | |
| #include "BLI_math.h"
 | |
| #include "BLI_utildefines.h"
 | |
| 
 | |
| #include "BKE_DerivedMesh.h"
 | |
| #include "BKE_node.h"
 | |
| 
 | |
| #include "RNA_access.h"
 | |
| #include "RNA_types.h"
 | |
| 
 | |
| #include "MEM_guardedalloc.h"
 | |
| 
 | |
| #include "NOD_socket.h"
 | |
| 
 | |
| /****************** FLOAT ******************/
 | |
| 
 | |
| static bNodeSocketType node_socket_type_float = {
 | |
| 	/* type */				SOCK_FLOAT,
 | |
| 	/* ui_name */			"Float",
 | |
| 	/* ui_description */	"Floating Point",
 | |
| 	/* ui_icon */			0,
 | |
| 	/* ui_color */			{160,160,160,255},
 | |
| 
 | |
| 	/* value_structname */	"bNodeSocketValueFloat",
 | |
| 	/* value_structsize */	sizeof(bNodeSocketValueFloat),
 | |
| 
 | |
| 	/* buttonfunc */		NULL,
 | |
| };
 | |
| 
 | |
| /****************** VECTOR ******************/
 | |
| 
 | |
| static bNodeSocketType node_socket_type_vector = {
 | |
| 	/* type */				SOCK_VECTOR,
 | |
| 	/* ui_name */			"Vector",
 | |
| 	/* ui_description */	"3-dimensional floating point vector",
 | |
| 	/* ui_icon */			0,
 | |
| 	/* ui_color */			{100,100,200,255},
 | |
| 
 | |
| 	/* value_structname */	"bNodeSocketValueVector",
 | |
| 	/* value_structsize */	sizeof(bNodeSocketValueVector),
 | |
| 
 | |
| 	/* buttonfunc */		NULL,
 | |
| };
 | |
| 
 | |
| /****************** RGBA ******************/
 | |
| 
 | |
| static bNodeSocketType node_socket_type_rgba = {
 | |
| 	/* type */				SOCK_RGBA,
 | |
| 	/* ui_name */			"RGBA",
 | |
| 	/* ui_description */	"RGBA color",
 | |
| 	/* ui_icon */			0,
 | |
| 	/* ui_color */			{200,200,40,255},
 | |
| 
 | |
| 	/* value_structname */	"bNodeSocketValueRGBA",
 | |
| 	/* value_structsize */	sizeof(bNodeSocketValueRGBA),
 | |
| 
 | |
| 	/* buttonfunc */		NULL,
 | |
| };
 | |
| 
 | |
| /****************** INT ******************/
 | |
| 
 | |
| static bNodeSocketType node_socket_type_int = {
 | |
| 	/* type */				SOCK_INT,
 | |
| 	/* ui_name */			"Int",
 | |
| 	/* ui_description */	"Integer",
 | |
| 	/* ui_icon */			0,
 | |
| 	/* ui_color */			{17,133,37,255},
 | |
| 
 | |
| 	/* value_structname */	"bNodeSocketValueInt",
 | |
| 	/* value_structsize */	sizeof(bNodeSocketValueInt),
 | |
| 
 | |
| 	/* buttonfunc */		NULL,
 | |
| };
 | |
| 
 | |
| /****************** BOOLEAN ******************/
 | |
| 
 | |
| static bNodeSocketType node_socket_type_boolean = {
 | |
| 	/* type */				SOCK_BOOLEAN,
 | |
| 	/* ui_name */			"Boolean",
 | |
| 	/* ui_description */	"Boolean",
 | |
| 	/* ui_icon */			0,
 | |
| 	/* ui_color */			{158,139,63,255},
 | |
| 
 | |
| 	/* value_structname */	"bNodeSocketValueBoolean",
 | |
| 	/* value_structsize */	sizeof(bNodeSocketValueBoolean),
 | |
| 
 | |
| 	/* buttonfunc */		NULL,
 | |
| };
 | |
| 
 | |
| /****************** SHADER ******************/
 | |
| 
 | |
| static bNodeSocketType node_socket_type_shader = {
 | |
| 	/* type */				SOCK_SHADER,
 | |
| 	/* ui_name */			"Shader",
 | |
| 	/* ui_description */	"Shader",
 | |
| 	/* ui_icon */			0,
 | |
| 	/* ui_color */			{100,200,100,255},
 | |
| 
 | |
| 	/* value_structname */	NULL,
 | |
| 	/* value_structsize */	0,
 | |
| 
 | |
| 	/* buttonfunc */		NULL,
 | |
| };
 | |
| 
 | |
| /****************** MESH ******************/
 | |
| 
 | |
| static bNodeSocketType node_socket_type_mesh = {
 | |
| 	/* type */				SOCK_MESH,
 | |
| 	/* ui_name */			"Mesh",
 | |
| 	/* ui_description */	"Mesh geometry data",
 | |
| 	/* ui_icon */			0,
 | |
| 	/* ui_color */			{255,133,7,255},
 | |
| 
 | |
| 	/* value_structname */	NULL,
 | |
| 	/* value_structsize */	0,
 | |
| 
 | |
| 	/* buttonfunc */		NULL,
 | |
| };
 | |
| 
 | |
| 
 | |
| void node_socket_type_init(bNodeSocketType *types[])
 | |
| {
 | |
| 	#define INIT_TYPE(name)		types[node_socket_type_##name.type] = &node_socket_type_##name;
 | |
| 	
 | |
| 	INIT_TYPE(float);
 | |
| 	INIT_TYPE(vector);
 | |
| 	INIT_TYPE(rgba);
 | |
| 	INIT_TYPE(int);
 | |
| 	INIT_TYPE(boolean);
 | |
| 	INIT_TYPE(shader);
 | |
| 	INIT_TYPE(mesh);
 | |
| 	
 | |
| 	#undef INIT_TYPE
 | |
| }
 | |
| 
 | |
| void *node_socket_make_default_value(int type)
 | |
| {
 | |
| 	/* XXX currently just allocates from stype->structsize.
 | |
| 	 * it might become necessary to do more complex allocations for later types.
 | |
| 	 */
 | |
| 	bNodeSocketType *stype = ntreeGetSocketType(type);
 | |
| 	if (stype->value_structsize > 0) {
 | |
| 		void *default_value = MEM_callocN(stype->value_structsize, "default socket value");
 | |
| 		return default_value;
 | |
| 	}
 | |
| 	else
 | |
| 		return NULL;
 | |
| }
 | |
| 
 | |
| void node_socket_free_default_value(int UNUSED(type), void *default_value)
 | |
| {
 | |
| 	/* XXX can just free the pointee for all current socket types. */
 | |
| 	if (default_value)
 | |
| 		MEM_freeN(default_value);
 | |
| }
 | |
| 
 | |
| void node_socket_init_default_value(int type, void *default_value)
 | |
| {
 | |
| 	switch (type) {
 | |
| 	case SOCK_FLOAT:
 | |
| 		node_socket_set_default_value_float(default_value, PROP_NONE, 0.0f, -FLT_MAX, FLT_MAX);
 | |
| 		break;
 | |
| 	case SOCK_INT:
 | |
| 		node_socket_set_default_value_int(default_value, PROP_NONE, 0, INT_MIN, INT_MAX);
 | |
| 		break;
 | |
| 	case SOCK_BOOLEAN:
 | |
| 		node_socket_set_default_value_boolean(default_value, FALSE);
 | |
| 		break;
 | |
| 	case SOCK_VECTOR:
 | |
| 		node_socket_set_default_value_vector(default_value, PROP_NONE, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX);
 | |
| 		break;
 | |
| 	case SOCK_RGBA:
 | |
| 		node_socket_set_default_value_rgba(default_value, 0.0f, 0.0f, 0.0f, 1.0f);
 | |
| 		break;
 | |
| 	case SOCK_SHADER:
 | |
| 		node_socket_set_default_value_shader(default_value);
 | |
| 		break;
 | |
| 	case SOCK_MESH:
 | |
| 		node_socket_set_default_value_mesh(default_value);
 | |
| 		break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max)
 | |
| {
 | |
| 	bNodeSocketValueInt *val = default_value;
 | |
| 	val->subtype = subtype;
 | |
| 	val->value = value;
 | |
| 	val->min = min;
 | |
| 	val->max = max;
 | |
| }
 | |
| 
 | |
| void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max)
 | |
| {
 | |
| 	bNodeSocketValueFloat *val = default_value;
 | |
| 	val->subtype = subtype;
 | |
| 	val->value = value;
 | |
| 	val->min = min;
 | |
| 	val->max = max;
 | |
| }
 | |
| 
 | |
| void node_socket_set_default_value_boolean(void *default_value, char value)
 | |
| {
 | |
| 	bNodeSocketValueBoolean *val = default_value;
 | |
| 	val->value = value;
 | |
| }
 | |
| 
 | |
| void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max)
 | |
| {
 | |
| 	bNodeSocketValueVector *val = default_value;
 | |
| 	val->subtype = subtype;
 | |
| 	val->value[0] = x;
 | |
| 	val->value[1] = y;
 | |
| 	val->value[2] = z;
 | |
| 	val->min = min;
 | |
| 	val->max = max;
 | |
| }
 | |
| 
 | |
| void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a)
 | |
| {
 | |
| 	bNodeSocketValueRGBA *val = default_value;
 | |
| 	val->value[0] = r;
 | |
| 	val->value[1] = g;
 | |
| 	val->value[2] = b;
 | |
| 	val->value[3] = a;
 | |
| }
 | |
| 
 | |
| void node_socket_set_default_value_shader(void *UNUSED(default_value))
 | |
| {
 | |
| }
 | |
| 
 | |
| void node_socket_set_default_value_mesh(void *UNUSED(default_value))
 | |
| {
 | |
| }
 | |
| 
 | |
| 
 | |
| void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value)
 | |
| {
 | |
| 	/* XXX only one of these pointers is valid! just putting them here for convenience */
 | |
| 	bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value;
 | |
| 	bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value;
 | |
| 	bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value;
 | |
| 	bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value;
 | |
| 	bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value;
 | |
| 
 | |
| 	bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value;
 | |
| 	bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value;
 | |
| 	bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value;
 | |
| 	bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value;
 | |
| 	bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value;
 | |
| 
 | |
| 	switch (type) {
 | |
| 	case SOCK_FLOAT:
 | |
| 		*tofloat = *fromfloat;
 | |
| 		break;
 | |
| 	case SOCK_INT:
 | |
| 		*toint = *fromint;
 | |
| 		break;
 | |
| 	case SOCK_BOOLEAN:
 | |
| 		*tobool = *frombool;
 | |
| 		break;
 | |
| 	case SOCK_VECTOR:
 | |
| 		*tovector = *fromvector;
 | |
| 		break;
 | |
| 	case SOCK_RGBA:
 | |
| 		*torgba = *fromrgba;
 | |
| 		break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* XXX This is a makeshift function to have useful initial group socket values.
 | |
|  * In the end this should be implemented by a flexible socket data conversion system,
 | |
|  * which is yet to be implemented. The idea is that beside default standard conversions,
 | |
|  * such as int-to-float, it should be possible to quickly select a conversion method or
 | |
|  * a chain of conversions for each input, whenever there is more than one option.
 | |
|  * E.g. a vector-to-float conversion could use either of the x/y/z components or
 | |
|  * the vector length.
 | |
|  *
 | |
|  * In the interface this could be implemented by a pseudo-script textbox on linked inputs,
 | |
|  * with quick selection from a predefined list of conversion options. Some Examples:
 | |
|  * - vector component 'z' (vector->float):						"z"
 | |
|  * - greyscale color (float->color):							"grey"
 | |
|  * - color luminance (color->float):							"lum"
 | |
|  * - matrix column 2 length (matrix->vector->float):			"col[1].len"
 | |
|  * - mesh vertex coordinate 'y' (mesh->vertex->vector->float):	"vertex.co.y"
 | |
|  *
 | |
|  * The actual conversion is then done by a series of conversion functions,
 | |
|  * which are defined in the socket type structs.
 | |
|  */
 | |
| void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value)
 | |
| {
 | |
| 	/* XXX only one of these pointers is valid! just putting them here for convenience */
 | |
| 	bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value;
 | |
| 	bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value;
 | |
| 	bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value;
 | |
| 	bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value;
 | |
| 	bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value;
 | |
| 
 | |
| 	bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value;
 | |
| 	bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value;
 | |
| 	bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value;
 | |
| 	bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value;
 | |
| 	bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value;
 | |
| 
 | |
| 	switch (from_type) {
 | |
| 	case SOCK_FLOAT:
 | |
| 		switch (to_type) {
 | |
| 		case SOCK_FLOAT:
 | |
| 			tofloat->value = fromfloat->value;
 | |
| 			break;
 | |
| 		case SOCK_INT:
 | |
| 			toint->value = (int)fromfloat->value;
 | |
| 			break;
 | |
| 		case SOCK_BOOLEAN:
 | |
| 			tobool->value = (fromfloat->value > 0.0f);
 | |
| 			break;
 | |
| 		case SOCK_VECTOR:
 | |
| 			tovector->value[0] = tovector->value[1] = tovector->value[2] = fromfloat->value;
 | |
| 			break;
 | |
| 		case SOCK_RGBA:
 | |
| 			torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = fromfloat->value;
 | |
| 			break;
 | |
| 		}
 | |
| 		break;
 | |
| 	case SOCK_INT:
 | |
| 		switch (to_type) {
 | |
| 		case SOCK_FLOAT:
 | |
| 			tofloat->value = (float)fromint->value;
 | |
| 			break;
 | |
| 		case SOCK_INT:
 | |
| 			toint->value = fromint->value;
 | |
| 			break;
 | |
| 		case SOCK_BOOLEAN:
 | |
| 			tobool->value = (fromint->value > 0);
 | |
| 			break;
 | |
| 		case SOCK_VECTOR:
 | |
| 			tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)fromint->value;
 | |
| 			break;
 | |
| 		case SOCK_RGBA:
 | |
| 			torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)fromint->value;
 | |
| 			break;
 | |
| 		}
 | |
| 		break;
 | |
| 	case SOCK_BOOLEAN:
 | |
| 		switch (to_type) {
 | |
| 		case SOCK_FLOAT:
 | |
| 			tofloat->value = (float)frombool->value;
 | |
| 			break;
 | |
| 		case SOCK_INT:
 | |
| 			toint->value = (int)frombool->value;
 | |
| 			break;
 | |
| 		case SOCK_BOOLEAN:
 | |
| 			tobool->value = frombool->value;
 | |
| 			break;
 | |
| 		case SOCK_VECTOR:
 | |
| 			tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)frombool->value;
 | |
| 			break;
 | |
| 		case SOCK_RGBA:
 | |
| 			torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)frombool->value;
 | |
| 			break;
 | |
| 		}
 | |
| 		break;
 | |
| 	case SOCK_VECTOR:
 | |
| 		switch (to_type) {
 | |
| 		case SOCK_FLOAT:
 | |
| 			tofloat->value = fromvector->value[0];
 | |
| 			break;
 | |
| 		case SOCK_INT:
 | |
| 			toint->value = (int)fromvector->value[0];
 | |
| 			break;
 | |
| 		case SOCK_BOOLEAN:
 | |
| 			tobool->value = (fromvector->value[0] > 0.0f);
 | |
| 			break;
 | |
| 		case SOCK_VECTOR:
 | |
| 			copy_v3_v3(tovector->value, fromvector->value);
 | |
| 			break;
 | |
| 		case SOCK_RGBA:
 | |
| 			copy_v3_v3(torgba->value, fromvector->value);
 | |
| 			torgba->value[3] = 1.0f;
 | |
| 			break;
 | |
| 		}
 | |
| 		break;
 | |
| 	case SOCK_RGBA:
 | |
| 		switch (to_type) {
 | |
| 		case SOCK_FLOAT:
 | |
| 			tofloat->value = fromrgba->value[0];
 | |
| 			break;
 | |
| 		case SOCK_INT:
 | |
| 			toint->value = (int)fromrgba->value[0];
 | |
| 			break;
 | |
| 		case SOCK_BOOLEAN:
 | |
| 			tobool->value = (fromrgba->value[0] > 0.0f);
 | |
| 			break;
 | |
| 		case SOCK_VECTOR:
 | |
| 			copy_v3_v3(tovector->value, fromrgba->value);
 | |
| 			break;
 | |
| 		case SOCK_RGBA:
 | |
| 			copy_v4_v4(torgba->value, fromrgba->value);
 | |
| 			break;
 | |
| 		}
 | |
| 		break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp)
 | |
| {
 | |
| 	bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, stemp->name, stemp->type);
 | |
| 	sock->flag |= stemp->flag;
 | |
| 	
 | |
| 	switch (stemp->type) {
 | |
| 	case SOCK_INT:
 | |
| 		node_socket_set_default_value_int(sock->default_value, stemp->subtype, (int)stemp->val1, (int)stemp->min, (int)stemp->max);
 | |
| 		break;
 | |
| 	case SOCK_FLOAT:
 | |
| 		node_socket_set_default_value_float(sock->default_value, stemp->subtype, stemp->val1, stemp->min, stemp->max);
 | |
| 		break;
 | |
| 	case SOCK_BOOLEAN:
 | |
| 		node_socket_set_default_value_boolean(sock->default_value, (char)stemp->val1);
 | |
| 		break;
 | |
| 	case SOCK_VECTOR:
 | |
| 		node_socket_set_default_value_vector(sock->default_value, stemp->subtype, stemp->val1, stemp->val2, stemp->val3, stemp->min, stemp->max);
 | |
| 		break;
 | |
| 	case SOCK_RGBA:
 | |
| 		node_socket_set_default_value_rgba(sock->default_value, stemp->val1, stemp->val2, stemp->val3, stemp->val4);
 | |
| 		break;
 | |
| 	case SOCK_SHADER:
 | |
| 		node_socket_set_default_value_shader(sock->default_value);
 | |
| 		break;
 | |
| 	case SOCK_MESH:
 | |
| 		node_socket_set_default_value_mesh(sock->default_value);
 | |
| 		break;
 | |
| 	}
 | |
| 	
 | |
| 	return sock;
 | |
| }
 | |
| 
 | |
| struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp)
 | |
| {
 | |
| 	bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type);
 | |
| 	return sock;
 | |
| }
 | |
| 
 | |
| static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp)
 | |
| {
 | |
| 	bNodeSocket *sock;
 | |
| 	
 | |
| 	for(sock= socklist->first; sock; sock= sock->next) {
 | |
| 		if(!(sock->flag & SOCK_DYNAMIC) && strncmp(sock->name, stemp->name, NODE_MAXSTR)==0)
 | |
| 			break;
 | |
| 	}
 | |
| 	if(sock) {
 | |
| 		sock->type= stemp->type;		/* in future, read this from tydefs! */
 | |
| 		if(stemp->limit==0) sock->limit= 0xFFF;
 | |
| 		else sock->limit= stemp->limit;
 | |
| 		sock->flag |= stemp->flag;
 | |
| 		
 | |
| 		/* Copy the property range and subtype parameters in case the template changed.
 | |
| 		 * NOT copying the actual value here, only button behavior changes!
 | |
| 		 */
 | |
| 		switch (sock->type) {
 | |
| 		case SOCK_FLOAT:
 | |
| 			{
 | |
| 				bNodeSocketValueFloat *dval= sock->default_value;
 | |
| 				dval->min = stemp->min;
 | |
| 				dval->max = stemp->max;
 | |
| 				dval->subtype = stemp->subtype;
 | |
| 			}
 | |
| 			break;
 | |
| 		case SOCK_INT:
 | |
| 			{
 | |
| 				bNodeSocketValueInt *dval= sock->default_value;
 | |
| 				dval->min = stemp->min;
 | |
| 				dval->max = stemp->max;
 | |
| 				dval->subtype = stemp->subtype;
 | |
| 			}
 | |
| 			break;
 | |
| 		case SOCK_VECTOR:
 | |
| 			{
 | |
| 				bNodeSocketValueVector *dval= sock->default_value;
 | |
| 				dval->min = stemp->min;
 | |
| 				dval->max = stemp->max;
 | |
| 				dval->subtype = stemp->subtype;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 		
 | |
| 		BLI_remlink(socklist, sock);
 | |
| 		
 | |
| 		return sock;
 | |
| 	}
 | |
| 	else {
 | |
| 		/* no socket for this template found, make a new one */
 | |
| 		if (in_out==SOCK_IN)
 | |
| 			sock = node_add_input_from_template(ntree, node, stemp);
 | |
| 		else
 | |
| 			sock = node_add_output_from_template(ntree, node, stemp);
 | |
| 		/* remove the new socket from the node socket list first,
 | |
| 		 * will be added back after verification.
 | |
| 		 */
 | |
| 		BLI_remlink(socklist, sock);
 | |
| 	}
 | |
| 	
 | |
| 	return sock;
 | |
| }
 | |
| 
 | |
| static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp_first)
 | |
| {
 | |
| 	bNodeSocket *sock, *nextsock;
 | |
| 	bNodeSocketTemplate *stemp;
 | |
| 	
 | |
| 	/* no inputs anymore? */
 | |
| 	if(stemp_first==NULL) {
 | |
| 		for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) {
 | |
| 			nextsock = sock->next;
 | |
| 			if (!(sock->flag & SOCK_DYNAMIC))
 | |
| 				nodeRemoveSocket(ntree, node, sock);
 | |
| 		}
 | |
| 	}
 | |
| 	else {
 | |
| 		/* step by step compare */
 | |
| 		stemp= stemp_first;
 | |
| 		while(stemp->type != -1) {
 | |
| 			stemp->sock= verify_socket_template(ntree, node, in_out, socklist, stemp);
 | |
| 			stemp++;
 | |
| 		}
 | |
| 		/* leftovers are removed */
 | |
| 		for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) {
 | |
| 			nextsock = sock->next;
 | |
| 			if (!(sock->flag & SOCK_DYNAMIC))
 | |
| 				nodeRemoveSocket(ntree, node, sock);
 | |
| 		}
 | |
| 		
 | |
| 		/* and we put back the verified sockets */
 | |
| 		stemp= stemp_first;
 | |
| 		if (socklist->first) {
 | |
| 			/* some dynamic sockets left, store the list start
 | |
| 			 * so we can add static sockets infront of it.
 | |
| 			 */
 | |
| 			sock = socklist->first;
 | |
| 			while(stemp->type != -1) {
 | |
| 				/* put static sockets infront of dynamic */
 | |
| 				BLI_insertlinkbefore(socklist, sock, stemp->sock);
 | |
| 				stemp++;
 | |
| 			}
 | |
| 		}
 | |
| 		else {
 | |
| 			while(stemp->type != -1) {
 | |
| 				BLI_addtail(socklist, stemp->sock);
 | |
| 				stemp++;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void node_verify_socket_templates(bNodeTree *ntree, bNode *node)
 | |
| {
 | |
| 	bNodeType *ntype= node->typeinfo;
 | |
| 	/* XXX Small trick: don't try to match socket lists when there are no templates.
 | |
| 	 * This also prevents group node sockets from being removed, without the need to explicitly
 | |
| 	 * check the node type here.
 | |
| 	 */
 | |
| 	if(ntype && ((ntype->inputs && ntype->inputs[0].type>=0) || (ntype->outputs && ntype->outputs[0].type>=0))) {
 | |
| 		verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
 | |
| 		verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
 | |
| 	}
 | |
| }
 | 
