Cleanup of default_value handling in node sockets.
The structs stored in the anonymous void *default_value in bNodeSocket are now handled completely inside node_socket.c. All allocation/freeing/duplicating for this has been replaced by the appropriate calls to generic API functions (declared in NOD_socket.h). This will make the default value handling more reliable for future node socket code. Group socket copying and value conversion has also been moved into the generic socket API file.
This commit is contained in:
@@ -159,7 +159,6 @@ void ntreeInitTypes(bNodeTree *ntree)
|
||||
|
||||
static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char *name, int type)
|
||||
{
|
||||
bNodeSocketType *stype= ntreeGetSocketType(type);
|
||||
bNodeSocket *sock;
|
||||
|
||||
sock= MEM_callocN(sizeof(bNodeSocket), "sock");
|
||||
@@ -169,8 +168,8 @@ static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char
|
||||
sock->type= type;
|
||||
sock->storage = NULL;
|
||||
|
||||
if (stype->value_structsize > 0)
|
||||
sock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
|
||||
sock->default_value = node_socket_make_default_value(type);
|
||||
node_socket_init_default_value(type, sock->default_value);
|
||||
|
||||
return sock;
|
||||
}
|
||||
@@ -216,8 +215,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
|
||||
BLI_remlink(&node->inputs, sock);
|
||||
BLI_remlink(&node->outputs, sock);
|
||||
|
||||
if (sock->default_value)
|
||||
MEM_freeN(sock->default_value);
|
||||
node_socket_free_default_value(sock->type, sock->default_value);
|
||||
MEM_freeN(sock);
|
||||
|
||||
node->update |= NODE_UPDATE;
|
||||
@@ -236,13 +234,10 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
|
||||
}
|
||||
|
||||
for (sock=node->inputs.first; sock; sock=sock->next)
|
||||
if (sock->default_value)
|
||||
MEM_freeN(sock->default_value);
|
||||
node_socket_free_default_value(sock->type, sock->default_value);
|
||||
BLI_freelistN(&node->inputs);
|
||||
for (sock=node->outputs.first; sock; sock=sock->next)
|
||||
if (sock->default_value)
|
||||
MEM_freeN(sock->default_value);
|
||||
|
||||
node_socket_free_default_value(sock->type, sock->default_value);
|
||||
BLI_freelistN(&node->outputs);
|
||||
|
||||
node->update |= NODE_UPDATE;
|
||||
@@ -396,7 +391,8 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
|
||||
oldsock->new_sock= sock;
|
||||
sock->stack_index= 0;
|
||||
|
||||
sock->default_value = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL);
|
||||
sock->default_value = node_socket_make_default_value(oldsock->type);
|
||||
node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value);
|
||||
|
||||
/* XXX some compositor node (e.g. image, render layers) still store
|
||||
* some persistent buffer data here, need to clear this to avoid dangling pointers.
|
||||
@@ -410,7 +406,8 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
|
||||
oldsock->new_sock= sock;
|
||||
sock->stack_index= 0;
|
||||
|
||||
sock->default_value = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL);
|
||||
sock->default_value = node_socket_make_default_value(oldsock->type);
|
||||
node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value);
|
||||
|
||||
/* XXX some compositor node (e.g. image, render layers) still store
|
||||
* some persistent buffer data here, need to clear this to avoid dangling pointers.
|
||||
@@ -658,13 +655,15 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree)
|
||||
for(gsock= newtree->inputs.first, oldgsock= ntree->inputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) {
|
||||
oldgsock->new_sock= gsock;
|
||||
gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
|
||||
gsock->default_value = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL);
|
||||
gsock->default_value = node_socket_make_default_value(oldgsock->type);
|
||||
node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value);
|
||||
}
|
||||
BLI_duplicatelist(&newtree->outputs, &ntree->outputs);
|
||||
for(gsock= newtree->outputs.first, oldgsock= ntree->outputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) {
|
||||
oldgsock->new_sock= gsock;
|
||||
gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
|
||||
gsock->default_value = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL);
|
||||
gsock->default_value = node_socket_make_default_value(oldgsock->type);
|
||||
node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value);
|
||||
}
|
||||
|
||||
/* copy links */
|
||||
@@ -863,14 +862,12 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
|
||||
|
||||
for (sock=node->inputs.first; sock; sock = nextsock) {
|
||||
nextsock = sock->next;
|
||||
if (sock->default_value)
|
||||
MEM_freeN(sock->default_value);
|
||||
node_socket_free_default_value(sock->type, sock->default_value);
|
||||
MEM_freeN(sock);
|
||||
}
|
||||
for (sock=node->outputs.first; sock; sock = nextsock) {
|
||||
nextsock = sock->next;
|
||||
if (sock->default_value)
|
||||
MEM_freeN(sock->default_value);
|
||||
node_socket_free_default_value(sock->type, sock->default_value);
|
||||
MEM_freeN(sock);
|
||||
}
|
||||
|
||||
@@ -924,12 +921,10 @@ void ntreeFreeTree(bNodeTree *ntree)
|
||||
}
|
||||
|
||||
for (sock=ntree->inputs.first; sock; sock=sock->next)
|
||||
if (sock->default_value)
|
||||
MEM_freeN(sock->default_value);
|
||||
node_socket_free_default_value(sock->type, sock->default_value);
|
||||
BLI_freelistN(&ntree->inputs);
|
||||
for (sock=ntree->outputs.first; sock; sock=sock->next)
|
||||
if (sock->default_value)
|
||||
MEM_freeN(sock->default_value);
|
||||
node_socket_free_default_value(sock->type, sock->default_value);
|
||||
BLI_freelistN(&ntree->outputs);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "NOD_socket.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
@@ -205,12 +207,9 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
|
||||
nodeRemLink(ntree, link);
|
||||
}
|
||||
|
||||
if(sock_prev->default_value) {
|
||||
if(sock_from->default_value)
|
||||
MEM_freeN(sock_from->default_value);
|
||||
|
||||
sock_from->default_value = MEM_dupallocN(sock_prev->default_value);
|
||||
}
|
||||
node_socket_free_default_value(sock_from->type, sock_from->default_value);
|
||||
sock_from->default_value = node_socket_make_default_value(sock_from->type);
|
||||
node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,26 +47,19 @@ struct bNodeStack;
|
||||
|
||||
void node_socket_type_init(struct bNodeSocketType *types[]);
|
||||
|
||||
struct bNodeSocket *nodeAddInputInt(struct bNodeTree *ntree, struct bNode *node, const char *name, PropertySubType subtype, int value, int min, int max);
|
||||
struct bNodeSocket *nodeAddOutputInt(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
void *node_socket_make_default_value(int type);
|
||||
void node_socket_free_default_value(int type, void *default_value);
|
||||
void node_socket_init_default_value(int type, void *default_value);
|
||||
void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value);
|
||||
void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value);
|
||||
|
||||
struct bNodeSocket *nodeAddInputFloat(struct bNodeTree *ntree, struct bNode *node, const char *name, PropertySubType subtype, float value, float min, float max);
|
||||
struct bNodeSocket *nodeAddOutputFloat(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
|
||||
struct bNodeSocket *nodeAddInputBoolean(struct bNodeTree *ntree, struct bNode *node, const char *name, char value);
|
||||
struct bNodeSocket *nodeAddOutputBoolean(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
|
||||
struct bNodeSocket *nodeAddInputVector(struct bNodeTree *ntree, struct bNode *node, const char *name, PropertySubType subtype, float x, float y, float z, float min, float max);
|
||||
struct bNodeSocket *nodeAddOutputVector(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
|
||||
struct bNodeSocket *nodeAddInputRGBA(struct bNodeTree *ntree, struct bNode *node, const char *name, float r, float g, float b, float a);
|
||||
struct bNodeSocket *nodeAddOutputRGBA(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
|
||||
struct bNodeSocket *nodeAddInputShader(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
struct bNodeSocket *nodeAddOutputShader(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
|
||||
struct bNodeSocket *nodeAddInputMesh(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
struct bNodeSocket *nodeAddOutputMesh(struct bNodeTree *ntree, struct bNode *node, const char *name);
|
||||
void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max);
|
||||
void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max);
|
||||
void node_socket_set_default_value_boolean(void *default_value, char value);
|
||||
void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max);
|
||||
void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a);
|
||||
void node_socket_set_default_value_shader(void *default_value);
|
||||
void node_socket_set_default_value_mesh(void *default_value);
|
||||
|
||||
struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp);
|
||||
struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp);
|
||||
|
||||
@@ -100,8 +100,8 @@ bNodeSocket *node_group_add_extern_socket(bNodeTree *UNUSED(ntree), ListBase *lb
|
||||
sock->groupsock = gsock;
|
||||
sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
|
||||
|
||||
if (gsock->default_value)
|
||||
sock->default_value = MEM_dupallocN(gsock->default_value);
|
||||
sock->default_value = node_socket_make_default_value(sock->type);
|
||||
node_socket_copy_default_value(sock->type, sock->default_value, gsock->default_value);
|
||||
|
||||
if(lb)
|
||||
BLI_addtail(lb, sock);
|
||||
@@ -247,177 +247,6 @@ bNode *node_group_make_from_selected(bNodeTree *ntree)
|
||||
return gnode;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
static void convert_socket_value(bNodeSocket *from, bNodeSocket *to)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_socket_value(bNodeSocket *from, bNodeSocket *to)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
if (from->type != to->type)
|
||||
return;
|
||||
|
||||
switch (from->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;
|
||||
}
|
||||
}
|
||||
|
||||
/* returns 1 if its OK */
|
||||
int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
|
||||
{
|
||||
@@ -489,7 +318,7 @@ int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
|
||||
}
|
||||
else {
|
||||
/* copy the default input value from the group socket default to the external socket */
|
||||
convert_socket_value(gsock, link->tosock);
|
||||
node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -517,7 +346,7 @@ int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
|
||||
}
|
||||
else {
|
||||
/* copy the default input value from the group node socket default to the internal socket */
|
||||
convert_socket_value(insock, link->tosock);
|
||||
node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
|
||||
nodeRemLink(wgroup, link);
|
||||
}
|
||||
}
|
||||
@@ -600,7 +429,7 @@ bNodeSocket *node_group_expose_socket(bNodeTree *ngroup, bNodeSocket *sock, int
|
||||
bNodeSocket *gsock= node_group_add_socket(ngroup, sock->name, sock->type, in_out);
|
||||
|
||||
/* initialize the default value. */
|
||||
copy_socket_value(sock, gsock);
|
||||
node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
|
||||
|
||||
return gsock;
|
||||
}
|
||||
@@ -616,7 +445,7 @@ void node_group_expose_all_sockets(bNodeTree *ngroup)
|
||||
gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_IN);
|
||||
|
||||
/* initialize the default value. */
|
||||
copy_socket_value(sock, gsock);
|
||||
node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
|
||||
|
||||
sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
|
||||
}
|
||||
@@ -626,7 +455,7 @@ void node_group_expose_all_sockets(bNodeTree *ngroup)
|
||||
gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_OUT);
|
||||
|
||||
/* initialize the default value. */
|
||||
copy_socket_value(sock, gsock);
|
||||
node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
|
||||
|
||||
gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
|
||||
}
|
||||
@@ -832,11 +661,12 @@ bNodeTemplate node_forloop_template(bNode *node)
|
||||
|
||||
void node_forloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
|
||||
{
|
||||
/* bNodeSocket *sock; */ /* UNUSED */
|
||||
bNodeSocket *sock;
|
||||
|
||||
node->id = (ID*)ntemp->ngroup;
|
||||
|
||||
/* sock = */ nodeAddInputFloat(ntree, node, "Iterations", PROP_UNSIGNED, 1, 0, 10000);
|
||||
sock = nodeAddSocket(ntree, node, SOCK_IN, "Iterations", SOCK_FLOAT);
|
||||
node_socket_set_default_value_float(sock->default_value, PROP_UNSIGNED, 1, 0, 10000);
|
||||
|
||||
/* NB: group socket input/output roles are inverted internally!
|
||||
* Group "inputs" work as outputs in links and vice versa.
|
||||
@@ -938,11 +768,12 @@ void node_loop_update_tree(bNodeTree *ngroup)
|
||||
|
||||
void node_whileloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
|
||||
{
|
||||
/* bNodeSocket *sock; */ /* UNUSED */
|
||||
bNodeSocket *sock;
|
||||
|
||||
node->id = (ID*)ntemp->ngroup;
|
||||
|
||||
/* sock = */ nodeAddInputFloat(ntree, node, "Condition", PROP_NONE, 1, 0, 1);
|
||||
sock = nodeAddSocket(ntree, node, SOCK_IN, "Condition", SOCK_FLOAT);
|
||||
node_socket_set_default_value_float(sock->default_value, PROP_NONE, 1, 0, 1);
|
||||
|
||||
/* max iterations */
|
||||
node->custom1 = 10000;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* \ingroup nodes
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
@@ -172,171 +173,310 @@ void node_socket_type_init(bNodeSocketType *types[])
|
||||
#undef INIT_TYPE
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeAddInputInt(struct bNodeTree *ntree, struct bNode *node, const char *name, PropertySubType subtype,
|
||||
int value, int min, int max)
|
||||
void *node_socket_make_default_value(int type)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_INT);
|
||||
bNodeSocketValueInt *dval= (bNodeSocketValueInt*)sock->default_value;
|
||||
dval->subtype = subtype;
|
||||
dval->value = value;
|
||||
dval->min = min;
|
||||
dval->max = max;
|
||||
return sock;
|
||||
}
|
||||
struct bNodeSocket *nodeAddOutputInt(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_OUT, name, SOCK_INT);
|
||||
return sock;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeAddInputFloat(struct bNodeTree *ntree, struct bNode *node, const char *name, PropertySubType subtype,
|
||||
float value, float min, float max)
|
||||
void node_socket_free_default_value(int UNUSED(type), void *default_value)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_FLOAT);
|
||||
bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value;
|
||||
dval->subtype = subtype;
|
||||
dval->value = value;
|
||||
dval->min = min;
|
||||
dval->max = max;
|
||||
return sock;
|
||||
}
|
||||
struct bNodeSocket *nodeAddOutputFloat(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_OUT, name, SOCK_FLOAT);
|
||||
return sock;
|
||||
/* XXX can just free the pointee for all current socket types. */
|
||||
MEM_freeN(default_value);
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeAddInputBoolean(struct bNodeTree *ntree, struct bNode *node, const char *name, char value)
|
||||
void node_socket_init_default_value(int type, void *default_value)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_BOOLEAN);
|
||||
bNodeSocketValueBoolean *dval= (bNodeSocketValueBoolean*)sock->default_value;
|
||||
dval->value = value;
|
||||
return sock;
|
||||
}
|
||||
struct bNodeSocket *nodeAddOutputBoolean(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_OUT, name, SOCK_BOOLEAN);
|
||||
return sock;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeAddInputVector(struct bNodeTree *ntree, struct bNode *node, const char *name, PropertySubType subtype,
|
||||
float x, float y, float z, float min, float max)
|
||||
void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_VECTOR);
|
||||
bNodeSocketValueVector *dval= (bNodeSocketValueVector*)sock->default_value;
|
||||
dval->subtype = subtype;
|
||||
dval->value[0] = x;
|
||||
dval->value[1] = y;
|
||||
dval->value[2] = z;
|
||||
dval->min = min;
|
||||
dval->max = max;
|
||||
return sock;
|
||||
}
|
||||
struct bNodeSocket *nodeAddOutputVector(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_OUT, name, SOCK_VECTOR);
|
||||
return sock;
|
||||
bNodeSocketValueInt *val = default_value;
|
||||
val->subtype = subtype;
|
||||
val->value = value;
|
||||
val->min = min;
|
||||
val->max = max;
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeAddInputRGBA(struct bNodeTree *ntree, struct bNode *node, const char *name,
|
||||
float r, float g, float b, float a)
|
||||
void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_RGBA);
|
||||
bNodeSocketValueRGBA *dval= (bNodeSocketValueRGBA*)sock->default_value;
|
||||
dval->value[0] = r;
|
||||
dval->value[1] = g;
|
||||
dval->value[2] = b;
|
||||
dval->value[3] = a;
|
||||
return sock;
|
||||
}
|
||||
struct bNodeSocket *nodeAddOutputRGBA(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_OUT, name, SOCK_RGBA);
|
||||
return sock;
|
||||
bNodeSocketValueFloat *val = default_value;
|
||||
val->subtype = subtype;
|
||||
val->value = value;
|
||||
val->min = min;
|
||||
val->max = max;
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeAddInputShader(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
void node_socket_set_default_value_boolean(void *default_value, char value)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_SHADER);
|
||||
return sock;
|
||||
}
|
||||
struct bNodeSocket *nodeAddOutputShader(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_OUT, name, SOCK_SHADER);
|
||||
return sock;
|
||||
bNodeSocketValueBoolean *val = default_value;
|
||||
val->value = value;
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeAddInputMesh(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_MESH);
|
||||
return sock;
|
||||
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;
|
||||
}
|
||||
struct bNodeSocket *nodeAddOutputMesh(struct bNodeTree *ntree, struct bNode *node, const char *name)
|
||||
|
||||
void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a)
|
||||
{
|
||||
bNodeSocket *sock= nodeAddSocket(ntree, node, SOCK_OUT, name, SOCK_MESH);
|
||||
return sock;
|
||||
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;
|
||||
bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, stemp->name, stemp->type);
|
||||
sock->flag |= stemp->flag;
|
||||
|
||||
switch (stemp->type) {
|
||||
case SOCK_INT:
|
||||
sock = nodeAddInputInt(ntree, node, stemp->name, stemp->subtype, (int)stemp->val1, (int)stemp->min, (int)stemp->max);
|
||||
node_socket_set_default_value_int(sock->default_value, stemp->subtype, (int)stemp->val1, (int)stemp->min, (int)stemp->max);
|
||||
break;
|
||||
case SOCK_FLOAT:
|
||||
sock = nodeAddInputFloat(ntree, node, stemp->name, stemp->subtype, stemp->val1, stemp->min, stemp->max);
|
||||
node_socket_set_default_value_float(sock->default_value, stemp->subtype, stemp->val1, stemp->min, stemp->max);
|
||||
break;
|
||||
case SOCK_BOOLEAN:
|
||||
sock = nodeAddInputBoolean(ntree, node, stemp->name, (char)stemp->val1);
|
||||
node_socket_set_default_value_boolean(sock->default_value, (char)stemp->val1);
|
||||
break;
|
||||
case SOCK_VECTOR:
|
||||
sock = nodeAddInputVector(ntree, node, stemp->name, stemp->subtype, stemp->val1, stemp->val2, stemp->val3, stemp->min, stemp->max);
|
||||
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:
|
||||
sock = nodeAddInputRGBA(ntree, node, stemp->name, stemp->val1, stemp->val2, stemp->val3, stemp->val4);
|
||||
node_socket_set_default_value_rgba(sock->default_value, stemp->val1, stemp->val2, stemp->val3, stemp->val4);
|
||||
break;
|
||||
case SOCK_SHADER:
|
||||
sock = nodeAddInputShader(ntree, node, stemp->name);
|
||||
node_socket_set_default_value_shader(sock->default_value);
|
||||
break;
|
||||
case SOCK_MESH:
|
||||
sock = nodeAddInputMesh(ntree, node, stemp->name);
|
||||
node_socket_set_default_value_mesh(sock->default_value);
|
||||
break;
|
||||
default:
|
||||
sock = nodeAddSocket(ntree, node, SOCK_IN, stemp->name, stemp->type);
|
||||
}
|
||||
sock->flag |= stemp->flag;
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp)
|
||||
{
|
||||
bNodeSocket *sock;
|
||||
switch (stemp->type) {
|
||||
case SOCK_INT:
|
||||
sock = nodeAddOutputInt(ntree, node, stemp->name);
|
||||
break;
|
||||
case SOCK_FLOAT:
|
||||
sock = nodeAddOutputFloat(ntree, node, stemp->name);
|
||||
break;
|
||||
case SOCK_BOOLEAN:
|
||||
sock = nodeAddOutputBoolean(ntree, node, stemp->name);
|
||||
break;
|
||||
case SOCK_VECTOR:
|
||||
sock = nodeAddOutputVector(ntree, node, stemp->name);
|
||||
break;
|
||||
case SOCK_RGBA:
|
||||
sock = nodeAddOutputRGBA(ntree, node, stemp->name);
|
||||
break;
|
||||
case SOCK_SHADER:
|
||||
sock = nodeAddOutputShader(ntree, node, stemp->name);
|
||||
break;
|
||||
case SOCK_MESH:
|
||||
sock = nodeAddOutputMesh(ntree, node, stemp->name);
|
||||
break;
|
||||
default:
|
||||
sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type);
|
||||
}
|
||||
bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type);
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user