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:
Diffstat (limited to 'source/blender/nodes/intern/node_util.c')
-rw-r--r--source/blender/nodes/intern/node_util.c136
1 files changed, 117 insertions, 19 deletions
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;