diff options
author | Hans Goudey <h.goudey@me.com> | 2022-10-12 04:07:53 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-10-12 04:33:31 +0300 |
commit | 0f60872461e19282d8d058c6edc5e2cebd4f5c7e (patch) | |
tree | ba742fbc6f51d4705083422ab7f4ee7796abd097 /source/blender | |
parent | b9e4d930b389e8e36599766fe9d1486d8cd9b8cb (diff) |
Cleanup: Simplify node insert after drag code
- Give functions and variables more descriptive names
- Use references for arguments
- Use tree topology cache to avoid iterating over all links
- Group related code together
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/include/ED_node.h | 28 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_relationships.cc | 285 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_convert_node.cc | 15 |
3 files changed, 146 insertions, 182 deletions
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index c30b8c5ec6a..24e14fdce72 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -87,17 +87,6 @@ void ED_node_tag_update_id(struct ID *id); float ED_node_grid_size(void); -/* node_relationships.cc */ - -/** - * Test == 0, clear all intersect flags. - */ -void ED_node_link_intersect_test(struct ScrArea *area, int test); -/** - * Assumes link with #NODE_LINKFLAG_HILITE set. - */ -void ED_node_link_insert(struct Main *bmain, struct ScrArea *area); - /* node_edit.cc */ void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo); @@ -186,3 +175,20 @@ bool ED_space_node_color_sample(struct Main *bmain, #ifdef __cplusplus } #endif + +#ifdef __cplusplus + +/* node_relationships.cc */ + +namespace blender::ed::space_node { + +void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion ®ion); +/** + * Assumes link with #NODE_LINKFLAG_HILITE set. + */ +void node_insert_on_link_flags(Main &bmain, SpaceNode &snode); +void node_insert_on_link_flags_clear(bNodeTree &node_tree); + +} // namespace blender::ed::space_node + +#endif
\ No newline at end of file diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index e631cb5aa42..f53eaf0f2bd 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -64,6 +64,10 @@ struct NodeInsertOfsData { float offset_x; /* offset to apply to node chain */ }; +namespace blender::ed::space_node { + +bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out); + static void clear_picking_highlight(ListBase *links) { LISTBASE_FOREACH (bNodeLink *, link, links) { @@ -71,8 +75,6 @@ static void clear_picking_highlight(ListBase *links) } } -namespace blender::ed::space_node { - void update_multi_input_indices_for_removed_links(bNode &node); /* -------------------------------------------------------------------- */ @@ -1883,100 +1885,55 @@ void NODE_OT_detach(wmOperatorType *ot) /** \name Automatic Node Insert on Dragging * \{ */ -/* prevent duplicate testing code below */ -static bool ed_node_link_conditions(ScrArea *area, - bool test, - SpaceNode **r_snode, - bNode **r_select) +static bNode *get_selected_node_for_insertion(bNodeTree &node_tree) { - SpaceNode *snode = area ? (SpaceNode *)area->spacedata.first : nullptr; - - *r_snode = snode; - *r_select = nullptr; - - /* no unlucky accidents */ - if (area == nullptr || area->spacetype != SPACE_NODE) { - return false; - } - - if (!test) { - /* no need to look for a node */ - return true; - } - - bNode *node; - bNode *select = nullptr; - for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) { + bNode *selected_node = nullptr; + int selected_node_count = 0; + for (bNode *node : node_tree.all_nodes()) { if (node->flag & SELECT) { - if (select) { - break; - } - select = node; + selected_node = node; + selected_node_count++; + } + if (selected_node_count > 1) { + return nullptr; } } - /* only one selected */ - if (node || select == nullptr) { - return false; + if (!selected_node) { + return nullptr; } - - /* correct node */ - if (BLI_listbase_is_empty(&select->inputs) || BLI_listbase_is_empty(&select->outputs)) { - return false; + if (selected_node->input_sockets().is_empty() || selected_node->output_sockets().is_empty()) { + return nullptr; } - - ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); - - /* test node for links */ - LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - if (node_link_is_hidden_or_dimmed(region->v2d, *link)) { - continue; - } - - if (link->tonode == select || link->fromnode == select) { - return false; - } + if (std::any_of(selected_node->input_sockets().begin(), + selected_node->input_sockets().end(), + [&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) { + return nullptr; } - - *r_select = select; - return true; + if (std::any_of(selected_node->output_sockets().begin(), + selected_node->output_sockets().end(), + [&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) { + return nullptr; + }; + return selected_node; } -/** \} */ - -} // namespace blender::ed::space_node - -/* -------------------------------------------------------------------- */ -/** \name Node Line Intersection Test - * \{ */ - -void ED_node_link_intersect_test(ScrArea *area, int test) +void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion ®ion) { - using namespace blender; - using namespace blender::ed::space_node; - - bNode *select; - SpaceNode *snode; - if (!ed_node_link_conditions(area, test, &snode, &select)) { - return; - } + bNodeTree &node_tree = *snode.edittree; + node_tree.ensure_topology_cache(); - /* clear flags */ - LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - link->flag &= ~NODE_LINKFLAG_HILITE; - } + node_insert_on_link_flags_clear(node_tree); - if (test == 0) { + bNode *node_to_insert = get_selected_node_for_insertion(node_tree); + if (!node_to_insert) { return; } - ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); - /* find link to select/highlight */ bNodeLink *selink = nullptr; float dist_best = FLT_MAX; - LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { - - if (node_link_is_hidden_or_dimmed(region->v2d, *link)) { + LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { continue; } @@ -1988,10 +1945,10 @@ void ED_node_link_intersect_test(ScrArea *area, int test) * upper left node edge of a intersected line segment */ for (int i = 0; i < NODE_LINK_RESOL; i++) { /* Check if the node rectangle intersects the line from this point to next one. */ - if (BLI_rctf_isect_segment(&select->totr, coords[i], coords[i + 1])) { + if (BLI_rctf_isect_segment(&node_to_insert->totr, coords[i], coords[i + 1])) { /* store the shortest distance to the upper left edge * of all intersections found so far */ - const float node_xy[] = {select->totr.xmin, select->totr.ymax}; + const float node_xy[] = {node_to_insert->totr.xmin, node_to_insert->totr.ymax}; /* to be precise coords should be clipped by select->totr, * but not done since there's no real noticeable difference */ @@ -2011,9 +1968,89 @@ void ED_node_link_intersect_test(ScrArea *area, int test) } } -/** \} */ +void node_insert_on_link_flags_clear(bNodeTree &node_tree) +{ + LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { + link->flag &= ~NODE_LINKFLAG_HILITE; + } +} -namespace blender::ed::space_node { +void node_insert_on_link_flags(Main &bmain, SpaceNode &snode) +{ + bNodeTree &node_tree = *snode.edittree; + node_tree.ensure_topology_cache(); + bNode *node_to_insert = get_selected_node_for_insertion(node_tree); + if (!node_to_insert) { + return; + } + + /* Find link to insert on. */ + bNodeTree &ntree = *snode.edittree; + bNodeLink *old_link = nullptr; + LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { + if (link->flag & NODE_LINKFLAG_HILITE) { + old_link = link; + break; + } + } + if (old_link == nullptr) { + return; + } + + old_link->flag &= ~NODE_LINKFLAG_HILITE; + + bNodeSocket *best_input = get_main_socket(ntree, *node_to_insert, SOCK_IN); + bNodeSocket *best_output = get_main_socket(ntree, *node_to_insert, SOCK_OUT); + + if (node_to_insert->type != NODE_REROUTE) { + /* Ignore main sockets when the types don't match. */ + if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr && + !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type), + static_cast<eNodeSocketDatatype>(best_input->type))) { + best_input = nullptr; + } + if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr && + !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type), + static_cast<eNodeSocketDatatype>(old_link->tosock->type))) { + best_output = nullptr; + } + } + + bNode *from_node = old_link->fromnode; + bNodeSocket *from_socket = old_link->fromsock; + bNode *to_node = old_link->tonode; + + if (best_output != nullptr) { + /* Relink the "start" of the existing link to the newly inserted node. */ + old_link->fromnode = node_to_insert; + old_link->fromsock = best_output; + BKE_ntree_update_tag_link_changed(&ntree); + } + else { + nodeRemLink(&ntree, old_link); + } + + if (best_input != nullptr) { + /* Add a new link that connects the node on the left to the newly inserted node. */ + nodeAddLink(&ntree, from_node, from_socket, node_to_insert, best_input); + } + + /* Set up insert offset data, it needs stuff from here. */ + if ((snode.flag & SNODE_SKIP_INSOFFSET) == 0) { + BLI_assert(snode.runtime->iofsd == nullptr); + NodeInsertOfsData *iofsd = MEM_cnew<NodeInsertOfsData>(__func__); + + iofsd->insert = node_to_insert; + iofsd->prev = from_node; + iofsd->next = to_node; + + snode.runtime->iofsd = iofsd; + } + + ED_node_tree_propagate_change(nullptr, &bmain, &ntree); +} + +/** \} */ /* -------------------------------------------------------------------- */ /** \name Node Insert Offset Operator @@ -2050,7 +2087,7 @@ static int get_main_socket_priority(const bNodeSocket *socket) } /** Get the "main" socket based on the node declaration or an heuristic. */ -static bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) +bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) { ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs; @@ -2428,85 +2465,3 @@ void NODE_OT_insert_offset(wmOperatorType *ot) /** \} */ } // namespace blender::ed::space_node - -/* -------------------------------------------------------------------- */ -/** \name Note Link Insert - * \{ */ - -void ED_node_link_insert(Main *bmain, ScrArea *area) -{ - using namespace blender::ed::space_node; - - bNode *node_to_insert; - SpaceNode *snode; - if (!ed_node_link_conditions(area, true, &snode, &node_to_insert)) { - return; - } - - /* Find link to insert on. */ - bNodeTree &ntree = *snode->edittree; - bNodeLink *old_link = nullptr; - LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (link->flag & NODE_LINKFLAG_HILITE) { - old_link = link; - break; - } - } - if (old_link == nullptr) { - return; - } - - old_link->flag &= ~NODE_LINKFLAG_HILITE; - - bNodeSocket *best_input = get_main_socket(ntree, *node_to_insert, SOCK_IN); - bNodeSocket *best_output = get_main_socket(ntree, *node_to_insert, SOCK_OUT); - - if (node_to_insert->type != NODE_REROUTE) { - /* Ignore main sockets when the types don't match. */ - if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr && - !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type), - static_cast<eNodeSocketDatatype>(best_input->type))) { - best_input = nullptr; - } - if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr && - !ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type), - static_cast<eNodeSocketDatatype>(old_link->tosock->type))) { - best_output = nullptr; - } - } - - bNode *from_node = old_link->fromnode; - bNodeSocket *from_socket = old_link->fromsock; - bNode *to_node = old_link->tonode; - - if (best_output != nullptr) { - /* Relink the "start" of the existing link to the newly inserted node. */ - old_link->fromnode = node_to_insert; - old_link->fromsock = best_output; - BKE_ntree_update_tag_link_changed(&ntree); - } - else { - nodeRemLink(&ntree, old_link); - } - - if (best_input != nullptr) { - /* Add a new link that connects the node on the left to the newly inserted node. */ - nodeAddLink(&ntree, from_node, from_socket, node_to_insert, best_input); - } - - /* Set up insert offset data, it needs stuff from here. */ - if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) { - BLI_assert(snode->runtime->iofsd == nullptr); - NodeInsertOfsData *iofsd = MEM_cnew<NodeInsertOfsData>(__func__); - - iofsd->insert = node_to_insert; - iofsd->prev = from_node; - iofsd->next = to_node; - - snode->runtime->iofsd = iofsd; - } - - ED_node_tree_propagate_change(nullptr, bmain, snode->edittree); -} - -/** \} */ diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc index 3b88a368266..eb5eb822d69 100644 --- a/source/blender/editors/transform/transform_convert_node.cc +++ b/source/blender/editors/transform/transform_convert_node.cc @@ -160,7 +160,9 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t) static void flushTransNodes(TransInfo *t) { + using namespace blender::ed; const float dpi_fac = UI_DPI_FAC; + SpaceNode *snode = static_cast<SpaceNode *>(t->area->spacedata.first); TransCustomDataNode *customdata = (TransCustomDataNode *)t->custom.type.data; @@ -220,7 +222,7 @@ static void flushTransNodes(TransInfo *t) /* handle intersection with noodles */ if (tc->data_len == 1) { - ED_node_link_intersect_test(t->area, 1); + space_node::node_insert_on_link_flags_set(*snode, *t->region); } } } @@ -233,13 +235,15 @@ static void flushTransNodes(TransInfo *t) static void special_aftertrans_update__node(bContext *C, TransInfo *t) { + using namespace blender::ed; Main *bmain = CTX_data_main(C); + SpaceNode *snode = (SpaceNode *)t->area->spacedata.first; + bNodeTree *ntree = snode->edittree; + const bool canceled = (t->state == TRANS_CANCEL); - SpaceNode *snode = (SpaceNode *)t->area->spacedata.first; if (canceled && t->remove_on_cancel) { /* remove selected nodes on cancel */ - bNodeTree *ntree = snode->edittree; if (ntree) { LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { if (node->flag & NODE_SELECT) { @@ -252,11 +256,10 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t) if (!canceled) { ED_node_post_apply_transform(C, snode->edittree); - ED_node_link_insert(bmain, t->area); + space_node::node_insert_on_link_flags(*bmain, *snode); } - /* clear link line */ - ED_node_link_intersect_test(t->area, 0); + space_node::node_insert_on_link_flags_clear(*ntree); } /** \} */ |