diff options
author | Fabian Schempp <fabianschempp@googlemail.com> | 2021-03-10 16:57:57 +0300 |
---|---|---|
committer | Fabian Schempp <fabianschempp@googlemail.com> | 2021-03-10 16:57:57 +0300 |
commit | 576c392241bde1d6497b00490e97e104ac887132 (patch) | |
tree | 97a7455970cb104b5571ed37386ca3fa22dad0ad /source/blender/editors/space_node/node_relationships.c | |
parent | 5991c5c9289792e8f9d14375b254ba81306680ac (diff) |
Nodes: Sortable Multi Input Sockets
This Patch removes the auto sorting from Multi-Input Sockets and allows
the links to be sorted by drag and drop instead.
As a minor related change, it fixes the drawing of the mute line to
connect to the first input instead of the socket's center.
Diffstat (limited to 'source/blender/editors/space_node/node_relationships.c')
-rw-r--r-- | source/blender/editors/space_node/node_relationships.c | 82 |
1 files changed, 77 insertions, 5 deletions
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 35dd865047e..963349f876b 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -434,6 +434,75 @@ static bool snode_autoconnect_input(SpaceNode *snode, return true; } +typedef struct LinkAndPosition { + struct bNodeLink *link; + float multi_socket_position[2]; +} LinkAndPosition; + +static int compare_link_by_y_position(const void *a, const void *b) +{ + const LinkAndPosition *link_and_position_a = *(const LinkAndPosition **)a; + const LinkAndPosition *link_and_position_b = *(const LinkAndPosition **)b; + + BLI_assert(link_and_position_a->link->tosock == link_and_position_b->link->tosock); + const float link_a_y = link_and_position_a->multi_socket_position[1]; + const float link_b_y = link_and_position_b->multi_socket_position[1]; + return link_a_y > link_b_y ? 1 : -1; +} + +void sort_multi_input_socket_links(SpaceNode *snode, + bNode *node, + bNodeLink *drag_link, + float cursor[2]) +{ + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + if (!(socket->flag & SOCK_MULTI_INPUT)) { + continue; + } + /* The total is calculated in #node_update_nodetree, which runs before this draw step. */ + int total_inputs = socket->total_inputs + 1; + struct LinkAndPosition **input_links = MEM_malloc_arrayN( + total_inputs, sizeof(LinkAndPosition *), __func__); + + int index = 0; + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (link->tosock == socket) { + struct LinkAndPosition *link_and_position = MEM_callocN(sizeof(struct LinkAndPosition), + __func__); + link_and_position->link = link; + node_link_calculate_multi_input_position(link->tosock->locx, + link->tosock->locy, + link->multi_input_socket_index, + link->tosock->total_inputs, + link_and_position->multi_socket_position); + input_links[index] = link_and_position; + index++; + } + } + + if (drag_link) { + LinkAndPosition *link_and_position = MEM_callocN(sizeof(LinkAndPosition), __func__); + link_and_position->link = drag_link; + copy_v2_v2(link_and_position->multi_socket_position, cursor); + input_links[index] = link_and_position; + index++; + } + + qsort(input_links, index, sizeof(bNodeLink *), compare_link_by_y_position); + + for (int i = 0; i < index; i++) { + input_links[i]->link->multi_input_socket_index = i; + } + + for (int i = 0; i < index; i++) { + if (input_links[i]) { + MEM_freeN(input_links[i]); + } + } + MEM_freeN(input_links); + } +} + static void snode_autoconnect(Main *bmain, SpaceNode *snode, const bool allow_multiple, @@ -816,10 +885,6 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { bNodeLink *link = linkdata->data; - /* skip if this is already the target socket */ - if (link->tosock == tsock) { - continue; - } /* skip if socket is on the same node as the fromsock */ if (tnode && link->fromnode == tnode) { continue; @@ -828,12 +893,17 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) /* attach links to the socket */ link->tonode = tnode; link->tosock = tsock; + snode->runtime->last_node_hovered_while_dragging_a_link = tnode; + sort_multi_input_socket_links(snode, tnode, link, cursor); } } else { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { bNodeLink *link = linkdata->data; - + if (snode->runtime->last_node_hovered_while_dragging_a_link) { + sort_multi_input_socket_links( + snode, snode->runtime->last_node_hovered_while_dragging_a_link, NULL, cursor); + } link->tonode = NULL; link->tosock = NULL; } @@ -2090,6 +2160,8 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) snode_update(snode, select); ED_node_tag_update_id((ID *)snode->edittree); ED_node_tag_update_id(snode->id); + + sort_multi_input_socket_links(snode, node, NULL, NULL); } } } |