diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index fdc82307ce0..7c12a1114ec 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -2610,6 +2610,18 @@ int node_get_resize_cursor(NodeResizeDirection directions) return WM_CURSOR_EDIT; } +static const bNode *find_node_under_cursor(SpaceNode &snode, const float2 &cursor) +{ + /* Check nodes front to back. */ + const Span nodes = snode.edittree->all_nodes(); + for (int i = nodes.index_range().last(); i > 0; i--) { + if (BLI_rctf_isect_pt(&nodes[i]->runtime->totr, cursor[0], cursor[1])) { + return nodes[i]; + } + } + return nullptr; +} + void node_set_cursor(wmWindow &win, SpaceNode &snode, const float2 &cursor) { const bNodeTree *ntree = snode.edittree; @@ -2617,36 +2629,28 @@ void node_set_cursor(wmWindow &win, SpaceNode &snode, const float2 &cursor) WM_cursor_set(&win, WM_CURSOR_DEFAULT); return; } - - bNode *node; - bNodeSocket *sock; - int wmcursor = WM_CURSOR_DEFAULT; - - if (node_find_indicated_socket( - snode, &node, &sock, cursor, (eNodeSocketInOut)(SOCK_IN | SOCK_OUT))) { + if (node_find_indicated_socket(snode, cursor, SOCK_IN | SOCK_OUT)) { + WM_cursor_set(&win, WM_CURSOR_DEFAULT); + return; + } + const bNode *node = find_node_under_cursor(snode, cursor); + if (!node) { + WM_cursor_set(&win, WM_CURSOR_DEFAULT); + return; + } + const NodeResizeDirection dir = node_get_resize_direction(node, cursor[0], cursor[1]); + if (node->is_frame() && dir == NODE_RESIZE_NONE) { + /* Indicate that frame nodes can be moved/selected on their borders. */ + const rctf frame_inside = node_frame_rect_inside(*node); + if (!BLI_rctf_isect_pt(&frame_inside, cursor[0], cursor[1])) { + WM_cursor_set(&win, WM_CURSOR_NSEW_SCROLL); + return; + } WM_cursor_set(&win, WM_CURSOR_DEFAULT); return; } - /* Check nodes front to back. */ - for (node = (bNode *)ntree->nodes.last; node; node = node->prev) { - if (BLI_rctf_isect_pt(&node->runtime->totr, cursor[0], cursor[1])) { - break; /* First hit on node stops. */ - } - } - if (node) { - NodeResizeDirection dir = node_get_resize_direction(node, cursor[0], cursor[1]); - wmcursor = node_get_resize_cursor(dir); - /* We want to indicate that Frame nodes can be moved/selected on their borders. */ - if (node->type == NODE_FRAME && dir == NODE_RESIZE_NONE) { - const rctf frame_inside = node_frame_rect_inside(*node); - if (!BLI_rctf_isect_pt(&frame_inside, cursor[0], cursor[1])) { - wmcursor = WM_CURSOR_NSEW_SCROLL; - } - } - } - - WM_cursor_set(&win, wmcursor); + WM_cursor_set(&win, node_get_resize_cursor(dir)); } static void count_multi_input_socket_links(bNodeTree &ntree, SpaceNode &snode) diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 1d132c99ec1..940216db9a3 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -1205,24 +1205,21 @@ static bool cursor_isect_multi_input_socket(const float2 &cursor, const bNodeSoc return false; } -bool node_find_indicated_socket(SpaceNode &snode, - bNode **nodep, - bNodeSocket **sockp, - const float2 &cursor, - const eNodeSocketInOut in_out) +bNodeSocket *node_find_indicated_socket(SpaceNode &snode, + const float2 &cursor, + const eNodeSocketInOut in_out) { rctf rect; - const float size_sock_padded = NODE_SOCKSIZE + 4; - *nodep = nullptr; - *sockp = nullptr; + snode.edittree->ensure_topology_cache(); + + const Span nodes = snode.edittree->all_nodes(); + for (int i = nodes.index_range().last(); i > 0; i--) { + bNode &node = *nodes[i]; - /* check if we click in a socket */ - LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode.edittree->nodes) { BLI_rctf_init_pt_radius(&rect, cursor, size_sock_padded); - - if (!(node->flag & NODE_HIDDEN)) { + if (!(node.flag & NODE_HIDDEN)) { /* extra padding inside and out - allow dragging on the text areas too */ if (in_out == SOCK_IN) { rect.xmax += NODE_SOCKSIZE; @@ -1235,37 +1232,31 @@ bool node_find_indicated_socket(SpaceNode &snode, } if (in_out & SOCK_IN) { - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + for (bNodeSocket *sock : node.input_sockets()) { if (sock->is_visible()) { const float2 location(sock->runtime->locx, sock->runtime->locy); - if (sock->flag & SOCK_MULTI_INPUT && !(node->flag & NODE_HIDDEN)) { + if (sock->flag & SOCK_MULTI_INPUT && !(node.flag & NODE_HIDDEN)) { if (cursor_isect_multi_input_socket(cursor, *sock)) { - if (!socket_is_occluded(location, *node, snode)) { - *nodep = node; - *sockp = sock; - return true; + if (!socket_is_occluded(location, node, snode)) { + return sock; } } } else if (BLI_rctf_isect_pt(&rect, location.x, location.y)) { - if (!socket_is_occluded(location, *node, snode)) { - *nodep = node; - *sockp = sock; - return true; + if (!socket_is_occluded(location, node, snode)) { + return sock; } } } } } if (in_out & SOCK_OUT) { - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + for (bNodeSocket *sock : node.output_sockets()) { if (sock->is_visible()) { const float2 location(sock->runtime->locx, sock->runtime->locy); if (BLI_rctf_isect_pt(&rect, location.x, location.y)) { - if (!socket_is_occluded(location, *node, snode)) { - *nodep = node; - *sockp = sock; - return true; + if (!socket_is_occluded(location, node, snode)) { + return sock; } } } @@ -1273,7 +1264,7 @@ bool node_find_indicated_socket(SpaceNode &snode, } } - return false; + return nullptr; } /** \} */ diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 5e2fcfeb87c..74ee9f6b3ad 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -311,12 +311,9 @@ bool composite_node_editable(bContext *C); bool node_has_hidden_sockets(bNode *node); void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set); int node_render_changed_exec(bContext *, wmOperator *); -/** Type is #SOCK_IN and/or #SOCK_OUT. */ -bool node_find_indicated_socket(SpaceNode &snode, - bNode **nodep, - bNodeSocket **sockp, - const float2 &cursor, - eNodeSocketInOut in_out); +bNodeSocket *node_find_indicated_socket(SpaceNode &snode, + const float2 &cursor, + eNodeSocketInOut in_out); float node_link_dim_factor(const View2D &v2d, const bNodeLink &link); bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link); diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index b21f69259de..1025c1b2edf 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -124,27 +124,24 @@ static void pick_input_link_by_link_intersect(const bContext &C, float2 drag_start; RNA_float_get_array(op.ptr, "drag_start", drag_start); - bNode *node; - bNodeSocket *socket; - node_find_indicated_socket(*snode, &node, &socket, drag_start, SOCK_IN); + bNodeSocket *socket = node_find_indicated_socket(*snode, drag_start, SOCK_IN); + bNode &node = socket->owner_node(); /* Distance to test overlapping of cursor on link. */ const float cursor_link_touch_distance = 12.5f * UI_DPI_FAC; bNodeLink *link_to_pick = nullptr; clear_picking_highlight(&snode->edittree->links); - LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - if (link->tosock == socket) { - /* Test if the cursor is near a link. */ - std::array coords; - node_link_bezier_points_evaluated(*link, coords); + for (bNodeLink *link : socket->directly_linked_links()) { + /* Test if the cursor is near a link. */ + std::array coords; + node_link_bezier_points_evaluated(*link, coords); - for (const int i : IndexRange(coords.size() - 1)) { - const float distance = dist_squared_to_line_segment_v2(cursor, coords[i], coords[i + 1]); - if (distance < cursor_link_touch_distance) { - link_to_pick = link; - nldrag.last_picked_multi_input_socket_link = link_to_pick; - } + for (const int i : IndexRange(coords.size() - 1)) { + const float distance = dist_squared_to_line_segment_v2(cursor, coords[i], coords[i + 1]); + if (distance < cursor_link_touch_distance) { + link_to_pick = link; + nldrag.last_picked_multi_input_socket_link = link_to_pick; } } } @@ -164,8 +161,8 @@ static void pick_input_link_by_link_intersect(const bContext &C, link_to_pick->flag |= NODE_LINK_TEMP_HIGHLIGHT; ED_area_tag_redraw(CTX_wm_area(&C)); - if (!node_find_indicated_socket(*snode, &node, &socket, cursor, SOCK_IN)) { - pick_link(nldrag, *snode, node, *link_to_pick); + if (!node_find_indicated_socket(*snode, cursor, SOCK_IN)) { + pick_link(nldrag, *snode, &node, *link_to_pick); } } } @@ -952,13 +949,11 @@ static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cur bNodeLinkDrag &nldrag = *static_cast(op.customdata); if (nldrag.in_out == SOCK_OUT) { - bNode *tnode; - bNodeSocket *tsock = nullptr; - snode.edittree->ensure_topology_cache(); - if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) { + if (bNodeSocket *tsock = node_find_indicated_socket(snode, cursor, SOCK_IN)) { + bNode &tnode = tsock->owner_node(); for (bNodeLink &link : nldrag.links) { /* skip if socket is on the same node as the fromsock */ - if (tnode && link.fromnode == tnode) { + if (link.fromnode == &tnode) { continue; } @@ -972,16 +967,16 @@ static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cur } /* attach links to the socket */ - link.tonode = tnode; + link.tonode = &tnode; link.tosock = tsock; - nldrag.last_node_hovered_while_dragging_a_link = tnode; + nldrag.last_node_hovered_while_dragging_a_link = &tnode; if (existing_link_connected_to_fromsock) { link.multi_input_socket_index = existing_link_connected_to_fromsock->multi_input_socket_index; continue; } if (link.tosock && link.tosock->flag & SOCK_MULTI_INPUT) { - sort_multi_input_socket_links_with_drag(*tnode, link, cursor); + sort_multi_input_socket_links_with_drag(tnode, link, cursor); } } } @@ -997,21 +992,20 @@ static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cur } } else { - bNode *tnode; - bNodeSocket *tsock = nullptr; - if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) { + if (bNodeSocket *tsock = node_find_indicated_socket(snode, cursor, SOCK_OUT)) { + bNode &node = tsock->owner_node(); for (bNodeLink &link : nldrag.links) { /* skip if this is already the target socket */ if (link.fromsock == tsock) { continue; } /* skip if socket is on the same node as the fromsock */ - if (tnode && link.tonode == tnode) { + if (link.tonode == &node) { continue; } /* attach links to the socket */ - link.fromnode = tnode; + link.fromnode = &node; link.fromsock = tsock; } } @@ -1094,12 +1088,11 @@ static std::unique_ptr node_link_init(SpaceNode &snode, const float2 cursor, const bool detach) { - /* output indicated? */ - bNode *node; - bNodeSocket *sock; - if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { + if (bNodeSocket *sock = node_find_indicated_socket(snode, cursor, SOCK_OUT)) { + bNode &node = sock->owner_node(); + std::unique_ptr nldrag = std::make_unique(); - nldrag->start_node = node; + nldrag->start_node = &node; nldrag->start_socket = sock; nldrag->start_link_count = nodeCountSocketLinks(snode.edittree, sock); int link_limit = nodeSocketLinkLimit(sock); @@ -1121,16 +1114,16 @@ static std::unique_ptr node_link_init(SpaceNode &snode, else { /* dragged links are fixed on output side */ nldrag->in_out = SOCK_OUT; - nldrag->links.append(create_drag_link(*node, *sock)); + nldrag->links.append(create_drag_link(node, *sock)); } return nldrag; } - /* or an input? */ - if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) { + if (bNodeSocket *sock = node_find_indicated_socket(snode, cursor, SOCK_IN)) { + bNode &node = sock->owner_node(); std::unique_ptr nldrag = std::make_unique(); - nldrag->last_node_hovered_while_dragging_a_link = node; - nldrag->start_node = node; + nldrag->last_node_hovered_while_dragging_a_link = &node; + nldrag->start_node = &node; nldrag->start_socket = sock; nldrag->start_link_count = nodeCountSocketLinks(snode.edittree, sock); @@ -1154,15 +1147,13 @@ static std::unique_ptr node_link_init(SpaceNode &snode, nodeRemLink(snode.edittree, link_to_pick); /* send changed event to original link->tonode */ - if (node) { - BKE_ntree_update_tag_node_property(snode.edittree, node); - } + BKE_ntree_update_tag_node_property(snode.edittree, &node); } } else { /* dragged links are fixed on input side */ nldrag->in_out = SOCK_IN; - nldrag->links.append(create_drag_link(*node, *sock)); + nldrag->links.append(create_drag_link(node, *sock)); } return nldrag; } diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 67ed9a34c7d..9f133f10c1f 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -175,14 +175,9 @@ static bool is_position_over_node_or_socket(SpaceNode &snode, const float2 &mous if (node_under_mouse_tweak(*snode.edittree, mouse)) { return true; } - - bNode *node; - bNodeSocket *sock; - if (node_find_indicated_socket( - snode, &node, &sock, mouse, (eNodeSocketInOut)(SOCK_IN | SOCK_OUT))) { + if (node_find_indicated_socket(snode, mouse, SOCK_IN | SOCK_OUT)) { return true; } - return false; } @@ -532,9 +527,8 @@ static bool node_mouse_select(bContext *C, const Object *ob = CTX_data_active_object(C); const Scene *scene = CTX_data_scene(C); const wmWindowManager *wm = CTX_wm_manager(C); - bNode *node; + bNode *node = nullptr; bNodeSocket *sock = nullptr; - bNodeSocket *tsock; /* always do socket_select when extending selection. */ const bool socket_select = (params->sel_op == SEL_OP_XOR) || @@ -551,7 +545,9 @@ static bool node_mouse_select(bContext *C, if (socket_select) { /* NOTE: unlike nodes #SelectPick_Params isn't fully supported. */ const bool extend = (params->sel_op == SEL_OP_XOR); - if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) { + sock = node_find_indicated_socket(snode, cursor, SOCK_IN); + if (sock) { + node = &sock->owner_node(); found = true; node_was_selected = node->flag & SELECT; @@ -560,41 +556,43 @@ static bool node_mouse_select(bContext *C, node_socket_toggle(node, *sock, true); changed = true; } - else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { - found = true; - node_was_selected = node->flag & SELECT; + if (!changed) { + sock = node_find_indicated_socket(snode, cursor, SOCK_OUT); + if (sock) { + node = &sock->owner_node(); + found = true; + node_was_selected = node->flag & SELECT; - if (sock->flag & SELECT) { - if (extend) { - node_socket_deselect(node, *sock, true); - changed = true; + if (sock->flag & SELECT) { + if (extend) { + node_socket_deselect(node, *sock, true); + changed = true; + } } - } - else { - /* Only allow one selected output per node, for sensible linking. - * Allow selecting outputs from different nodes though, if extend is true. */ - if (node) { - for (tsock = (bNodeSocket *)node->outputs.first; tsock; tsock = tsock->next) { + else { + /* Only allow one selected output per node, for sensible linking. + * Allow selecting outputs from different nodes though, if extend is true. */ + for (bNodeSocket *tsock : node->output_sockets()) { if (tsock == sock) { continue; } node_socket_deselect(node, *tsock, true); changed = true; } - } - if (!extend) { - for (bNode *tnode : node_tree.all_nodes()) { - if (tnode == node) { - continue; - } - for (tsock = (bNodeSocket *)tnode->outputs.first; tsock; tsock = tsock->next) { - node_socket_deselect(tnode, *tsock, true); - changed = true; + if (!extend) { + for (bNode *tnode : node_tree.all_nodes()) { + if (tnode == node) { + continue; + } + for (bNodeSocket *tsock : tnode->output_sockets()) { + node_socket_deselect(tnode, *tsock, true); + changed = true; + } } } + node_socket_select(node, *sock); + changed = true; } - node_socket_select(node, *sock); - changed = true; } } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index a003947cabe..7053836f7ff 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -254,6 +254,7 @@ typedef enum eNodeSocketInOut { SOCK_IN = 1 << 0, SOCK_OUT = 1 << 1, } eNodeSocketInOut; +ENUM_OPERATORS(eNodeSocketInOut, SOCK_OUT); /** #bNodeSocket.flag, first bit is selection. */ typedef enum eNodeSocketFlag {