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 | |
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')
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 13 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.cc | 57 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 17 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_group.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 11 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_relationships.c | 82 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 1 | ||||
-rw-r--r-- | source/blender/nodes/NOD_node_tree_ref.hh | 2 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_tree_ref.cc | 40 |
9 files changed, 141 insertions, 85 deletions
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index a9a7ef5a0a2..75ea5b9a1bf 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3593,6 +3593,13 @@ bool node_link_bezier_handles(const View2D *v2d, if (link->fromsock) { vec[0][0] = link->fromsock->locx; vec[0][1] = link->fromsock->locy; + if (link->fromsock->flag & SOCK_MULTI_INPUT) { + node_link_calculate_multi_input_position(link->fromsock->locx, + link->fromsock->locy, + link->fromsock->total_inputs - 1, + link->fromsock->total_inputs, + vec[0]); + } fromreroute = (link->fromnode && link->fromnode->type == NODE_REROUTE); } else { @@ -3606,7 +3613,11 @@ bool node_link_bezier_handles(const View2D *v2d, vec[3][0] = link->tosock->locx; vec[3][1] = link->tosock->locy; if (!(link->tonode->flag & NODE_HIDDEN) && link->tosock->flag & SOCK_MULTI_INPUT) { - node_link_calculate_multi_input_position(link, vec[3]); + node_link_calculate_multi_input_position(link->tosock->locx, + link->tosock->locy, + link->multi_input_socket_index, + link->tosock->total_inputs, + vec[3]); } toreroute = (link->tonode && link->tonode->type == NODE_REROUTE); } diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 5a0cacf070b..bb0cd754c7b 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -1780,25 +1780,6 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree) } } -static bool compare_link_by_angle_to_node(const bNodeLink *link_a, const bNodeLink *link_b) -{ - BLI_assert(link_a->tosock == link_b->tosock); - const float socket_location[2] = {link_a->tosock->locx, link_a->tosock->locy}; - const float up_direction[2] = {0.0f, 1.0f}; - - float delta_a[2] = {link_a->fromsock->locx - socket_location[0], - link_a->fromsock->locy - socket_location[1]}; - normalize_v2(delta_a); - const float angle_a = angle_normalized_v2v2(up_direction, delta_a); - - float delta_b[2] = {link_b->fromsock->locx - socket_location[0], - link_b->fromsock->locy - socket_location[1]}; - normalize_v2(delta_b); - const float angle_b = angle_normalized_v2v2(up_direction, delta_b); - - return angle_a > angle_b; -} - static void node_draw(const bContext *C, ARegion *region, SpaceNode *snode, @@ -1813,42 +1794,6 @@ static void node_draw(const bContext *C, #define USE_DRAW_TOT_UPDATE -/** - * Automatically sort the input links to multi-input sockets to avoid crossing noodles. - */ -static void sort_multi_input_socket_links(bNodeTree *ntree, SpaceNode *snode) -{ - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { - if (socket->flag & SOCK_MULTI_INPUT) { - /* The total is calculated in #node_update_nodetree, which runs before this draw step. */ - const int total_inputs = socket->total_inputs; - Vector<bNodeLink *> input_links; - input_links.reserve(total_inputs); - - LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { - if (link->tosock == socket) { - input_links.append(link); - } - } - LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { - LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { - bNodeLink *link = (bNodeLink *)linkdata->data; - if (link->tosock == socket) { - input_links.append(link); - } - } - } - - std::sort(input_links.begin(), input_links.end(), compare_link_by_angle_to_node); - for (const int i : input_links.index_range()) { - input_links[i]->multi_input_socket_index = i; - } - } - } - } -} - void node_draw_nodetree(const bContext *C, ARegion *region, SpaceNode *snode, @@ -1885,8 +1830,6 @@ void node_draw_nodetree(const bContext *C, GPU_blend(GPU_BLEND_ALPHA); nodelink_batch_start(snode); - sort_multi_input_socket_links(ntree, snode); - LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { if (!nodeLinkIsHidden(link)) { node_draw_link(®ion->v2d, snode, link); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 5205e50b0bf..afdc9efb78b 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -107,14 +107,15 @@ float node_socket_calculate_height(const bNodeSocket *socket) return sock_height; } -void node_link_calculate_multi_input_position(const bNodeLink *link, float r[2]) -{ - float offset = (link->tosock->total_inputs * NODE_MULTI_INPUT_LINK_GAP - - NODE_MULTI_INPUT_LINK_GAP) * - 0.5; - r[0] = link->tosock->locx - NODE_SOCKSIZE * 0.5f; - r[1] = link->tosock->locy - offset + - (link->multi_input_socket_index * NODE_MULTI_INPUT_LINK_GAP); +void node_link_calculate_multi_input_position(const float socket_x, + const float socket_y, + const int index, + const int total_inputs, + float r[2]) +{ + float offset = (total_inputs * NODE_MULTI_INPUT_LINK_GAP - NODE_MULTI_INPUT_LINK_GAP) * 0.5; + r[0] = socket_x - NODE_SOCKSIZE * 0.5f; + r[1] = socket_y - offset + (index * NODE_MULTI_INPUT_LINK_GAP); } static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags) diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index b3ae336aadf..e1de4bfc21e 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -1030,6 +1030,9 @@ static int node_group_make_exec(bContext *C, wmOperator *op) nodeSetActive(ntree, gnode); if (ngroup) { ED_node_tree_push(snode, ngroup, gnode); + LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) { + sort_multi_input_socket_links(snode, node, NULL, NULL); + } ntreeUpdateTree(bmain, ngroup); } } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 19700b258ae..241cbee00f0 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -77,6 +77,7 @@ typedef struct SpaceNode_Runtime { /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ /** Temporary data for node insert offset (in UI called Auto-offset). */ struct NodeInsertOfsData *iofsd; + struct bNode *last_node_hovered_while_dragging_a_link; } SpaceNode_Runtime; /* space_node.c */ @@ -86,7 +87,11 @@ void space_node_group_offset(struct SpaceNode *snode, float *x, float *y); /* node_draw.cc */ float node_socket_calculate_height(const bNodeSocket *socket); -void node_link_calculate_multi_input_position(const bNodeLink *link, float r[2]); +void node_link_calculate_multi_input_position(const float socket_x, + const float socket_y, + const int index, + const int total_inputs, + float r[2]); int node_get_colorid(struct bNode *node); int node_get_resize_cursor(int directions); @@ -215,6 +220,10 @@ void NODE_OT_group_separate(struct wmOperatorType *ot); void NODE_OT_group_edit(struct wmOperatorType *ot); /* node_relationships.c */ +void sort_multi_input_socket_links(struct SpaceNode *snode, + struct bNode *node, + struct bNodeLink *drag_link, + float cursor[2]); bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); void NODE_OT_link(struct wmOperatorType *ot); 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); } } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 82509599931..d19d270a7ac 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -394,7 +394,6 @@ typedef struct bNodeLink { bNodeSocket *fromsock, *tosock; int flag; - /* A runtime storage for automatically sorted links to multi-input sockets. */ int multi_input_socket_index; } bNodeLink; diff --git a/source/blender/nodes/NOD_node_tree_ref.hh b/source/blender/nodes/NOD_node_tree_ref.hh index 3c898aaf0ff..ec0444852c8 100644 --- a/source/blender/nodes/NOD_node_tree_ref.hh +++ b/source/blender/nodes/NOD_node_tree_ref.hh @@ -238,7 +238,7 @@ class NodeTreeRef : NonCopyable, NonMovable { OutputSocketRef &find_output_socket(Map<bNode *, NodeRef *> &node_mapping, bNode *bnode, bNodeSocket *bsocket); - void find_targets_skipping_reroutes(OutputSocketRef &socket_ref, Vector<SocketRef *> &r_targets); + void find_origins_skipping_reroutes(InputSocketRef &socket, Vector<SocketRef *> &r_origins); }; using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc index 0ea2538d6f1..775e16d0a29 100644 --- a/source/blender/nodes/intern/node_tree_ref.cc +++ b/source/blender/nodes/intern/node_tree_ref.cc @@ -88,17 +88,35 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) link.blink_ = blink; links_.append(&link); + from_socket.directly_linked_sockets_.append(&to_socket); - to_socket.directly_linked_sockets_.append(&from_socket); from_socket.directly_linked_links_.append(&link); to_socket.directly_linked_links_.append(&link); } - for (OutputSocketRef *socket : output_sockets_) { + for (InputSocketRef *input_socket : input_sockets_) { + if (input_socket->is_multi_input_socket()) { + std::sort(input_socket->directly_linked_links_.begin(), + input_socket->directly_linked_links_.end(), + [&](const LinkRef *a, const LinkRef *b) -> bool { + int index_a = a->blink()->multi_input_socket_index; + int index_b = b->blink()->multi_input_socket_index; + return index_a > index_b; + }); + } + } + + for (InputSocketRef *input_socket : input_sockets_) { + for (const LinkRef *link : input_socket->directly_linked_links()) { + input_socket->directly_linked_sockets_.append(link->from_); + } + } + + for (InputSocketRef *socket : input_sockets_) { if (!socket->node_->is_reroute_node()) { - this->find_targets_skipping_reroutes(*socket, socket->linked_sockets_); - for (SocketRef *target : socket->linked_sockets_) { - target->linked_sockets_.append(socket); + this->find_origins_skipping_reroutes(*socket, socket->linked_sockets_); + for (SocketRef *origin : socket->linked_sockets_) { + origin->linked_sockets_.append(socket); } } } @@ -155,15 +173,15 @@ OutputSocketRef &NodeTreeRef::find_output_socket(Map<bNode *, NodeRef *> &node_m return *node->outputs_[0]; } -void NodeTreeRef::find_targets_skipping_reroutes(OutputSocketRef &socket, - Vector<SocketRef *> &r_targets) +void NodeTreeRef::find_origins_skipping_reroutes(InputSocketRef &socket, + Vector<SocketRef *> &r_origins) { - for (SocketRef *direct_target : socket.directly_linked_sockets_) { - if (direct_target->node_->is_reroute_node()) { - this->find_targets_skipping_reroutes(*direct_target->node_->outputs_[0], r_targets); + for (SocketRef *direct_origin : socket.directly_linked_sockets_) { + if (direct_origin->node_->is_reroute_node()) { + this->find_origins_skipping_reroutes(*direct_origin->node_->inputs_[0], r_origins); } else { - r_targets.append_non_duplicates(direct_target); + r_origins.append_non_duplicates(direct_origin); } } } |