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:
-rw-r--r--source/blender/editors/space_node/node_edit.c227
-rw-r--r--source/blender/editors/space_node/node_header.c13
-rw-r--r--source/blender/editors/space_node/node_intern.h2
3 files changed, 134 insertions, 108 deletions
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index f2b3ed29067..05926782a0d 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -1353,95 +1353,155 @@ static int node_socket_hilights(SpaceNode *snode, int in_out)
/* ****************** Add *********************** */
-static bNodeSocket *get_next_outputsocket(bNodeSocket *sock, bNodeSocket **sockfrom, int totsock)
+
+typedef struct bNodeListItem {
+ struct bNodeListItem *next, *prev;
+ struct bNode *node;
+} bNodeListItem;
+
+int sort_nodes_locx(void *a, void *b)
{
- int a;
+ bNodeListItem *nli1 = (bNodeListItem *)a;
+ bNodeListItem *nli2 = (bNodeListItem *)b;
+ bNode *node1 = nli1->node;
+ bNode *node2 = nli2->node;
- /* first try to find a sockets with matching name */
- for (a=0; a<totsock; a++) {
- if(sockfrom[a]) {
- if(sock->type==sockfrom[a]->type) {
- if (strcmp(sockfrom[a]->name, sock->name)==0)
- return sockfrom[a];
- }
+ if (node1->locx > node2->locx)
+ return 1;
+ else
+ return 0;
+}
+
+static int socket_is_available(bNodeTree *ntree, bNodeSocket *sock, int allow_used)
+{
+ if (sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))
+ return 0;
+
+ if (!allow_used) {
+ if (nodeCountSocketLinks(ntree, sock) > 0)
+ return 0;
+ }
+ return 1;
+}
+
+static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, int allow_multiple)
+{
+ bNodeSocket *sock;
+
+ /* first try to find a socket with a matching name */
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+
+ if (!socket_is_available(ntree, sock, allow_multiple))
+ continue;
+
+ /* check for same types */
+ if (sock->type == sock_target->type) {
+ if (strcmp(sock->name, sock_target->name)==0)
+ return sock;
}
}
/* otherwise settle for the first available socket of the right type */
- for (a=0; a<totsock; a++) {
- if(sockfrom[a]) {
- if(sock->type==sockfrom[a]->type) {
- return sockfrom[a];
- }
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+
+ if (!socket_is_available(ntree, sock, allow_multiple))
+ continue;
+
+ /* check for same types */
+ if (sock->type == sock_target->type) {
+ return sock;
}
}
return NULL;
}
-void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag, int replace)
+/* this is a bit complicated, but designed to prioritise finding
+ * sockets of higher types, such as image, first */
+static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace)
{
- bNodeSocket *sock, *sockfrom[8];
- bNode *node, *nodefrom[8];
- int totsock= 0, socktype=0;
-
- if(node_to==NULL || node_to->inputs.first==NULL)
- return;
-
- /* connect first 1 socket type or first available socket now */
- for(sock= node_to->inputs.first; sock; sock= sock->next) {
- if (!replace && nodeCountSocketLinks(snode->edittree, sock))
- continue;
- if(socktype<sock->type)
- socktype= sock->type;
+ bNodeSocket *sock;
+ int socktype, maxtype=0;
+ int a;
+
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ maxtype = MAX2(sock->type, maxtype);
}
- /* find potential sockets, max 8 should work */
- for(node= snode->edittree->nodes.first; node; node= node->next) {
- if((node->flag & flag) && node!=node_to) {
- for(sock= node->outputs.first; sock; sock= sock->next) {
- if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
- sockfrom[totsock]= sock;
- nodefrom[totsock]= node;
- totsock++;
- if(totsock>7)
- break;
- }
+ /* find sockets of higher 'types' first (i.e. image) */
+ for (socktype=maxtype; socktype >= 0; socktype--) {
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+
+ if (!socket_is_available(ntree, sock, replace)) {
+ a++;
+ continue;
+ }
+
+ if (sock->type == socktype) {
+ /* increment to make sure we don't keep finding
+ * the same socket on every attempt running this function */
+ a++;
+ if (a > num)
+ return sock;
}
}
- if(totsock>7)
- break;
}
+
+ return NULL;
+}
- /* now just get matching socket types and create links */
- for(sock= node_to->inputs.first; sock; sock= sock->next) {
- bNodeSocket *sock_from;
- bNode *node_from;
+void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace)
+{
+ ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list");
+ bNodeListItem *nli;
+ bNode *node;
+ int i;
+
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & NODE_SELECT) {
+ nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item");
+ nli->node = node;
+ BLI_addtail(nodelist, nli);
+ }
+ }
+
+ /* sort nodes left to right */
+ BLI_sortlist(nodelist, sort_nodes_locx);
+
+ for (nli=nodelist->first; nli; nli=nli->next) {
+ bNode *node_fr, *node_to;
+ bNodeSocket *sock_fr, *sock_to;
- if (sock->type != socktype)
- continue;
+ if (nli->next == NULL) break;
- /* find a potential output socket and associated node */
- sock_from = get_next_outputsocket(sock, sockfrom, totsock);
- if (!sock_from)
- continue;
- nodeFindNode(snode->edittree, sock_from, &node_from, NULL);
+ node_fr = nli->node;
+ node_to = nli->next->node;
- /* then connect up the links */
- if (replace) {
- nodeRemSocketLinks(snode->edittree, sock);
- nodeAddLink(snode->edittree, node_from, sock_from, node_to, sock);
- } else {
- if (nodeCountSocketLinks(snode->edittree, sock)==0)
- nodeAddLink(snode->edittree, node_from, sock_from, node_to, sock);
+ /* check over input sockets first */
+ for (i=0; i<BLI_countlist(&node_to->inputs); i++) {
+
+ /* find the best guess input socket */
+ sock_to = best_socket_input(snode->edittree, node_to, i, replace);
+ if (!sock_to) continue;
+
+ /* check for an appropriate output socket to connect from */
+ sock_fr = best_socket_output(snode->edittree, node_fr, sock_to, allow_multiple);
+ if (!sock_fr) continue;
+
+ /* then we can connect */
+ if (replace)
+ nodeRemSocketLinks(snode->edittree, sock_to);
+ nodeAddLink(snode->edittree, node_fr, sock_fr, node_to, sock_to);
+ break;
}
- sock_from = NULL;
}
ntreeSolveOrder(snode->edittree);
+
+ BLI_freelistN(nodelist);
+ MEM_freeN(nodelist);
}
-
/* can be called from menus too, but they should do own undopush and redraws */
bNode *node_add_node(SpaceNode *snode, Scene *scene, int type, float locx, float locy)
{
@@ -1781,53 +1841,10 @@ void NODE_OT_link(wmOperatorType *ot)
static int node_make_link_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode= CTX_wm_space_node(C);
- bNode *fromnode, *tonode;
- bNodeLink *link;
- bNodeSocket *outsock= snode->edittree->selout;
- bNodeSocket *insock= snode->edittree->selin;
int replace = RNA_boolean_get(op->ptr, "replace");
-
- if (!insock || !outsock) {
- bNode *node;
-
- /* no socket selection, join nodes themselves, guessing connections */
- tonode = nodeGetActive(snode->edittree);
-
- if (!tonode) {
- BKE_report(op->reports, RPT_ERROR, "No active node");
- return OPERATOR_CANCELLED;
- }
-
- /* store selection in temp test flag */
- for(node= snode->edittree->nodes.first; node; node= node->next) {
- if(node->flag & NODE_SELECT) node->flag |= NODE_TEST;
- else node->flag &= ~NODE_TEST;
- }
-
- snode_autoconnect(snode, tonode, NODE_TEST, replace);
- node_tree_verify_groups(snode->nodetree);
- snode_handle_recalc(C, snode);
-
- return OPERATOR_FINISHED;
- }
-
-
- if (nodeFindLink(snode->edittree, outsock, insock)) {
- BKE_report(op->reports, RPT_ERROR, "There is already a link between these sockets");
- return OPERATOR_CANCELLED;
- }
- if (nodeFindNode(snode->edittree, outsock, &fromnode, NULL) &&
- nodeFindNode(snode->edittree, insock, &tonode, NULL))
- {
- link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock);
- NodeTagChanged(snode->edittree, tonode);
- node_remove_extra_links(snode, insock, link);
- }
- else
- return OPERATOR_CANCELLED;
+ snode_autoconnect(snode, 0, replace);
- ntreeSolveOrder(snode->edittree);
node_tree_verify_groups(snode->nodetree);
snode_handle_recalc(C, snode);
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index 6426856dfdd..d8a14c6412b 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -78,8 +78,17 @@ static void do_node_add(bContext *C, void *arg, int event)
node= node_add_node(snode, CTX_data_scene(C), event, snode->mx, snode->my);
- /* uses test flag */
- snode_autoconnect(snode, node, NODE_TEST, 0);
+ /* select previous selection before autoconnect */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & NODE_TEST) node->flag |= NODE_SELECT;
+ }
+
+ snode_autoconnect(snode, 1, 0);
+
+ /* deselect after autoconnection */
+ for(node= snode->edittree->nodes.first; node; node= node->next) {
+ if(node->flag & NODE_TEST) node->flag &= ~NODE_SELECT;
+ }
snode_handle_recalc(C, snode);
}
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index ff88b4fde77..1ff2f7d7128 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -81,7 +81,7 @@ void node_deselectall(SpaceNode *snode);
void snode_composite_job(const struct bContext *C, ScrArea *sa);
bNode *node_tree_get_editgroup(bNodeTree *ntree);
void node_tree_verify_groups(bNodeTree *nodetree);
-void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag, int replace);
+void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace);
int node_has_hidden_sockets(bNode *node);
void NODE_OT_duplicate(struct wmOperatorType *ot);