Nodes: make new frame node child of common parent of selected nodes

Previously, the new frame was always added as root frame and did not have a parent.
Now, the common root frame of all selected nodes is detected and the new frame is attached to it.

Pull Request: https://projects.blender.org/blender/blender/pulls/121972
This commit is contained in:
Jacques Lucke
2024-05-23 13:24:35 +02:00
parent 46f5079f11
commit 0f32291d15

View File

@@ -1822,6 +1822,45 @@ static void node_join_attach_recursive(bNodeTree &ntree,
}
}
static Vector<const bNode *> get_sorted_node_parents(const bNode &node)
{
Vector<const bNode *> parents;
for (const bNode *parent = node.parent; parent; parent = parent->parent) {
parents.append(parent);
}
/* Reverse so that the root frame is the first element (if there is any). */
std::reverse(parents.begin(), parents.end());
return parents;
}
static const bNode *find_common_parent_node(const Span<const bNode *> nodes)
{
if (nodes.is_empty()) {
return nullptr;
}
/* The common parent node also has to be a parent of the first node. */
Vector<const bNode *> candidates = get_sorted_node_parents(*nodes[0]);
for (const bNode *node : nodes.drop_front(1)) {
const Vector<const bNode *> parents = get_sorted_node_parents(*node);
/* Possibly shrink set of candidates so that it only contains the parents common with the
* current node. */
candidates.resize(std::min(candidates.size(), parents.size()));
for (const int i : candidates.index_range()) {
if (candidates[i] != parents[i]) {
candidates.resize(i);
break;
}
}
if (candidates.is_empty()) {
break;
}
}
if (candidates.is_empty()) {
return nullptr;
}
return candidates.last();
}
static int node_join_exec(bContext *C, wmOperator * /*op*/)
{
Main &bmain = *CTX_data_main(C);
@@ -1832,6 +1871,7 @@ static int node_join_exec(bContext *C, wmOperator * /*op*/)
bNode *frame_node = bke::nodeAddStaticNode(C, &ntree, NODE_FRAME);
bke::nodeSetActive(&ntree, frame_node);
frame_node->parent = const_cast<bNode *>(find_common_parent_node(selected_nodes.as_span()));
ntree.ensure_topology_cache();