Fix T37334: Better "internal links" function for muting and node disconnect.

Implements a more flexible internal connect function for standard nodes
(compositor, shader, texture). Allow feasible datatype connections by
priority.

The priorities for common datatypes in compositor, shader and texture
nodes are encoded in a simple function. Certain impossible connections
(e.g. color -> cycles shader) are excluded by giving them -1 priority.

Priority overrides link status: If a higher priority input can be found,
this will be used regardless of link status. Link status only comes into
play for inputs with same priority.

Reviewers: brecht

CC: sebastian_k

Differential Revision: https://developer.blender.org/D356
This commit is contained in:
Lukas Tönne 2014-03-02 16:04:25 +01:00
parent 6137ae29c1
commit fd553c5b7b
Notes: blender-bot 2023-02-14 11:38:08 +01:00
Referenced by issue #37334, ColorRamp mute is not working
16 changed files with 166 additions and 58 deletions

View File

@ -101,6 +101,8 @@ typedef struct bNodeSocketTemplate {
float min, max;
int subtype; /* would use PropertySubType but this is a bad level include to use RNA */
int flag;
/* optional: allowed inputs for internal links */
const bool *internal_links;
/* after this line is used internal only */
struct bNodeSocket *sock; /* used to hold verified socket */

View File

@ -128,19 +128,23 @@ typedef struct bNodeSocket {
/* XXX deprecated, socket input values are stored in default_value now. kept for forward compatibility */
bNodeStack ns DNA_DEPRECATED; /* custom data for inputs, only UI writes in this */
/* optional: allowed inputs for internal links */
const bool *internal_links;
} bNodeSocket;
/* sock->type */
#define SOCK_CUSTOM -1 /* socket has no integer type */
#define SOCK_FLOAT 0
#define SOCK_VECTOR 1
#define SOCK_RGBA 2
#define SOCK_SHADER 3
#define SOCK_BOOLEAN 4
#define __SOCK_MESH 5 /* deprecated */
#define SOCK_INT 6
#define SOCK_STRING 7
#define NUM_SOCKET_TYPES 8 /* must be last! */
typedef enum eNodeSocketDatatype {
SOCK_CUSTOM = -1, /* socket has no integer type */
SOCK_FLOAT = 0,
SOCK_VECTOR = 1,
SOCK_RGBA = 2,
SOCK_SHADER = 3,
SOCK_BOOLEAN = 4,
__SOCK_MESH = 5, /* deprecated */
SOCK_INT = 6,
SOCK_STRING = 7
} eNodeSocketDatatype;
/* socket side (input/output) */
typedef enum eNodeSocketInOut {

View File

@ -56,6 +56,7 @@ struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struc
bNodeSocket *sock = nodeAddStaticSocket(ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
sock->flag |= stemp->flag;
sock->internal_links = stemp->internal_links;
/* initialize default_value */
switch (stemp->type) {
@ -117,6 +118,7 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in
sock->type = stemp->type;
sock->limit = (stemp->limit == 0 ? 0xFFF : stemp->limit);
sock->flag |= stemp->flag;
sock->internal_links = stemp->internal_links;
BLI_remlink(socklist, sock);

View File

@ -81,6 +81,7 @@ void *node_initexec_curves(bNodeExecContext *UNUSED(context), bNode *node, bNode
return NULL; /* unused return */
}
/**** Labels ****/
void node_blend_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
@ -111,45 +112,139 @@ void node_filter_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int m
BLI_strncpy(label, IFACE_(name), maxlen);
}
/**** Internal Links (mute and disconnect) ****/
/* common datatype priorities, works for compositor, shader and texture nodes alike
* defines priority of datatype connection based on output type (to):
* < 0 : never connect these types
* >= 0 : priority of connection (higher values chosen first)
*/
static int node_datatype_priority(eNodeSocketDatatype from, eNodeSocketDatatype to)
{
switch (to) {
case SOCK_RGBA:
switch (from) {
case SOCK_RGBA: return 4;
case SOCK_FLOAT: return 3;
case SOCK_INT: return 2;
case SOCK_BOOLEAN: return 1;
default: return -1;
}
case SOCK_VECTOR:
switch (from) {
case SOCK_VECTOR: return 4;
case SOCK_FLOAT: return 3;
case SOCK_INT: return 2;
case SOCK_BOOLEAN: return 1;
default: return -1;
}
case SOCK_FLOAT:
switch (from) {
case SOCK_FLOAT: return 5;
case SOCK_INT: return 4;
case SOCK_BOOLEAN: return 3;
case SOCK_RGBA: return 2;
case SOCK_VECTOR: return 1;
default: return -1;
}
case SOCK_INT:
switch (from) {
case SOCK_INT: return 5;
case SOCK_FLOAT: return 4;
case SOCK_BOOLEAN: return 3;
case SOCK_RGBA: return 2;
case SOCK_VECTOR: return 1;
default: return -1;
}
case SOCK_BOOLEAN:
switch (from) {
case SOCK_BOOLEAN: return 5;
case SOCK_INT: return 4;
case SOCK_FLOAT: return 3;
case SOCK_RGBA: return 2;
case SOCK_VECTOR: return 1;
default: return -1;
}
case SOCK_SHADER:
switch (from) {
case SOCK_SHADER: return 1;
default: return -1;
}
case SOCK_STRING:
switch (from) {
case SOCK_STRING: return 1;
default: return -1;
}
default: return -1;
}
}
/* select a suitable input socket for an output */
static bNodeSocket *select_internal_link_input(bNode *node, bNodeSocket *output)
{
const bool *allowed_inputs = output->internal_links;
bNodeSocket *selected = NULL, *input;
int i;
int sel_priority = -1;
bool sel_is_linked = false;
for (input = node->inputs.first, i = 0; input; input = input->next, ++i) {
int priority = node_datatype_priority(input->type, output->type);
bool is_linked = (input->link != NULL);
bool preferred;
if (nodeSocketIsHidden(input) || /* ignore hidden sockets */
(allowed_inputs && !allowed_inputs[i]) || /* ignore if input is not allowed */
priority < 0 || /* ignore incompatible types */
(priority < sel_priority)) /* ignore if we already found a higher priority input */
continue;
/* determine if this input is preferred over the currently selected */
preferred = (priority > sel_priority) || /* prefer higher datatype priority */
(is_linked && !sel_is_linked); /* prefer linked over unlinked */
if (preferred) {
selected = input;
sel_is_linked = is_linked;
sel_priority = priority;
}
}
return selected;
}
void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
{
bNodeLink *link;
bNodeSocket *output, *input, *selected;
bNodeSocket *output, *input;
/* sanity check */
if (!ntree)
return;
/* use link pointer as a tag for handled sockets (for outputs is unused anyway) */
for (output = node->outputs.first; output; output = output->next)
output->link = NULL;
for (link = ntree->links.first; link; link = link->next) {
if (nodeLinkIsHidden(link))
continue;
output = link->fromsock;
if (link->fromnode != node || output->link)
continue;
if (nodeSocketIsHidden(output))
continue;
output->link = link; /* not really used, just for tagging handled sockets */
/* look for suitable input */
selected = NULL;
for (input = node->inputs.first; input; input = input->next) {
/* only use if same type */
if (input->type == output->type) {
if (!selected) {
selected = input;
}
else {
/* linked inputs preferred */
if (input->link && !selected->link)
selected = input;
}
}
}
input = select_internal_link_input(node, output);
if (selected) {
if (input) {
bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link");
ilink->fromnode = node;
ilink->fromsock = selected;
ilink->fromsock = input;
ilink->tonode = node;
ilink->tosock = output;
/* internal link is always valid */
@ -163,6 +258,9 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
output->link = NULL;
}
/**** Default value RNA access ****/
float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
{
PointerRNA ptr;

View File

@ -30,21 +30,21 @@
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_brick_in[] = {
{ SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE | SOCK_NO_INTERNAL_LINK},
{ SOCK_RGBA, 1, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 1, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 1, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{ SOCK_FLOAT, 1, N_("Mortar Size"), 0.02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.125f},
{ SOCK_FLOAT, 1, N_("Bias"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Brick Width"), 0.5f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f},
{ SOCK_FLOAT, 1, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f},
{ SOCK_RGBA, 1, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Mortar Size"), 0.02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.125f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Bias"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Brick Width"), 0.5f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_tex_brick_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -33,13 +33,13 @@ static bNodeSocketTemplate sh_node_tex_checker_in[] = {
{ SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_RGBA, 1, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 1, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{ SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_tex_checker_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -37,7 +37,7 @@ static bNodeSocketTemplate sh_node_tex_environment_in[] = {
};
static bNodeSocketTemplate sh_node_tex_environment_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -35,8 +35,8 @@ static bNodeSocketTemplate sh_node_tex_gradient_in[] = {
};
static bNodeSocketTemplate sh_node_tex_gradient_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -37,8 +37,8 @@ static bNodeSocketTemplate sh_node_tex_image_in[] = {
};
static bNodeSocketTemplate sh_node_tex_image_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Alpha"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 0, N_("Alpha"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -37,8 +37,8 @@ static bNodeSocketTemplate sh_node_tex_magic_in[] = {
};
static bNodeSocketTemplate sh_node_tex_magic_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -41,8 +41,8 @@ static bNodeSocketTemplate sh_node_tex_musgrave_in[] = {
};
static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -38,8 +38,8 @@ static bNodeSocketTemplate sh_node_tex_noise_in[] = {
};
static bNodeSocketTemplate sh_node_tex_noise_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -35,7 +35,7 @@ static bNodeSocketTemplate sh_node_tex_sky_in[] = {
};
static bNodeSocketTemplate sh_node_tex_sky_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -36,8 +36,8 @@ static bNodeSocketTemplate sh_node_tex_voronoi_in[] = {
};
static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};

View File

@ -38,9 +38,11 @@ static bNodeSocketTemplate sh_node_tex_wave_in[] = {
{ -1, 0, "" }
};
const bool internal_links[5] = {0,0,0,0,0};
static bNodeSocketTemplate sh_node_tex_wave_out[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, 0, internal_links},
{ SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR, 0, internal_links},
{ -1, 0, "" }
};

View File

@ -42,9 +42,9 @@ static bNodeSocketTemplate sh_node_texture_in[] = {
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_texture_out[] = {
{ SOCK_FLOAT, 0, N_("Value")},
{ SOCK_RGBA, 0, N_("Color")},
{ SOCK_VECTOR, 0, N_("Normal")},
{ SOCK_FLOAT, 0, N_("Value"), 0, 0, 0, 0, 0, 0, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_RGBA, 0, N_("Color"), 0, 0, 0, 0, 0, 0, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_VECTOR, 0, N_("Normal"), 0, 0, 0, 0, 0, 0, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ -1, 0, "" }
};