Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2014-03-02 19:04:25 +0400
committerLukas Tönne <lukas.toenne@gmail.com>2014-03-02 19:04:25 +0400
commitfd553c5b7bdfd5bec1cc005bc67785c54916a64a (patch)
tree35dc06e8085b1ede7208fc545f9919426583e217 /source/blender/nodes/intern
parent6137ae29c110c755e7892d28bf7052fb319aa746 (diff)
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
Diffstat (limited to 'source/blender/nodes/intern')
-rw-r--r--source/blender/nodes/intern/node_socket.c2
-rw-r--r--source/blender/nodes/intern/node_util.c136
2 files changed, 119 insertions, 19 deletions
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index b30658fa2be..b791f6f7393 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -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);
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index 3997d9cbcac..8fb455cd319 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -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;