Nodes: improve inserting nodes with link-drag-search

This makes link-drag-search more convenient when one wants to insert a new node
between existing nodes. The change currently also affects normal node-insertion
when dragging it. The exact behavior still has to be figured out.

Pull Request: https://projects.blender.org/blender/blender/pulls/128197
This commit is contained in:
Jacques Lucke
2024-09-30 11:14:43 +02:00
parent 866ef5b468
commit 83fa565ec2
3 changed files with 51 additions and 18 deletions

View File

@@ -27,7 +27,14 @@ namespace blender::ed::space_node {
VectorSet<bNode *> get_selected_nodes(bNodeTree &node_tree);
void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion &region, bool attach_enabled);
/**
* \param is_new_node: If the node was just inserted, it is allowed to be inserted in a link, even
* if it is linked already (after link-drag-search).
*/
void node_insert_on_link_flags_set(SpaceNode &snode,
const ARegion &region,
bool attach_enabled,
bool is_new_node);
/**
* Assumes link with #NODE_LINK_INSERT_TARGET set.

View File

@@ -2255,18 +2255,6 @@ static bNode *get_selected_node_for_insertion(bNodeTree &node_tree)
if (selected_node->input_sockets().is_empty() || selected_node->output_sockets().is_empty()) {
return nullptr;
}
if (std::any_of(selected_node->input_sockets().begin(),
selected_node->input_sockets().end(),
[&](const bNodeSocket *socket) { return socket->is_directly_linked(); }))
{
return nullptr;
}
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;
}
@@ -2298,7 +2286,8 @@ static bool node_can_be_inserted_on_link(bNodeTree &tree, bNode &node, const bNo
void node_insert_on_link_flags_set(SpaceNode &snode,
const ARegion &region,
const bool attach_enabled)
const bool attach_enabled,
const bool is_new_node)
{
bNodeTree &node_tree = *snode.edittree;
node_tree.ensure_topology_cache();
@@ -2309,6 +2298,16 @@ void node_insert_on_link_flags_set(SpaceNode &snode,
if (!node_to_insert) {
return;
}
Vector<bNodeSocket *> already_linked_sockets;
for (bNodeSocket *socket : node_to_insert->input_sockets()) {
already_linked_sockets.extend(socket->directly_linked_sockets());
}
for (bNodeSocket *socket : node_to_insert->output_sockets()) {
already_linked_sockets.extend(socket->directly_linked_sockets());
}
if (!is_new_node && !already_linked_sockets.is_empty()) {
return;
}
/* Find link to select/highlight. */
bNodeLink *selink = nullptr;
@@ -2317,6 +2316,24 @@ void node_insert_on_link_flags_set(SpaceNode &snode,
if (node_link_is_hidden_or_dimmed(region.v2d, *link)) {
continue;
}
if (ELEM(node_to_insert, link->fromnode, link->tonode)) {
/* Don't insert on a link that is connected to the node already. */
continue;
}
if (is_new_node && !already_linked_sockets.is_empty()) {
/* Only allow links coming from or going to the already linked socket after
* link-drag-search. */
bool is_linked_to_linked = false;
for (const bNodeSocket *socket : already_linked_sockets) {
if (ELEM(socket, link->fromsock, link->tosock)) {
is_linked_to_linked = true;
break;
}
}
if (!is_linked_to_linked) {
continue;
}
}
std::array<float2, NODE_LINK_RESOL + 1> coords;
node_link_bezier_points_evaluated(*link, coords);
@@ -2407,6 +2424,8 @@ void node_insert_on_link_flags(Main &bmain, SpaceNode &snode)
bNodeSocket *from_socket = old_link->fromsock;
bNode *to_node = old_link->tonode;
const bool best_input_is_linked = best_input && best_input->is_directly_linked();
if (best_output != nullptr) {
/* Relink the "start" of the existing link to the newly inserted node. */
old_link->fromnode = node_to_insert;
@@ -2418,8 +2437,11 @@ void node_insert_on_link_flags(Main &bmain, SpaceNode &snode)
}
if (best_input != nullptr) {
/* Add a new link that connects the node on the left to the newly inserted node. */
bke::node_add_link(&ntree, from_node, from_socket, node_to_insert, best_input);
/* Don't change an existing link. */
if (!best_input_is_linked) {
/* Add a new link that connects the node on the left to the newly inserted node. */
bke::node_add_link(&ntree, from_node, from_socket, node_to_insert, best_input);
}
}
/* Set up insert offset data, it needs stuff from here. */

View File

@@ -35,6 +35,8 @@ struct TransCustomDataNode {
/* Compare if the view has changed so we can update with `transformViewUpdate`. */
rctf viewrect_prev;
bool is_new_node;
};
/* -------------------------------------------------------------------- */
@@ -109,8 +111,10 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t)
NODE_EDGE_PAN_DELAY,
NODE_EDGE_PAN_ZOOM_INFLUENCE);
customdata->viewrect_prev = customdata->edgepan_data.initial_rect;
customdata->is_new_node = t->remove_on_cancel;
space_node::node_insert_on_link_flags_set(*snode, *t->region, t->modifiers & MOD_NODE_ATTACH);
space_node::node_insert_on_link_flags_set(
*snode, *t->region, t->modifiers & MOD_NODE_ATTACH, customdata->is_new_node);
t->custom.type.data = customdata;
t->custom.type.use_free = true;
@@ -239,7 +243,7 @@ static void flushTransNodes(TransInfo *t)
/* Handle intersection with noodles. */
if (tc->data_len == 1) {
space_node::node_insert_on_link_flags_set(
*snode, *t->region, t->modifiers & MOD_NODE_ATTACH);
*snode, *t->region, t->modifiers & MOD_NODE_ATTACH, customdata->is_new_node);
}
}
}