Ensure nodes that are added to the tree but not within the subtree of the root are still referenced after sorting.

This commit is contained in:
Martin Felis 2026-02-01 10:15:48 +01:00
parent 0554691e46
commit a2295680d1
2 changed files with 33 additions and 3 deletions

View File

@ -545,6 +545,10 @@ bool BLTAnimationNodeBlendTree::BLTBlendTreeGraph::remove_node(const Ref<BLTAnim
}
}
if (connection_info.parent_node_index > removed_node_index) {
connection_info.parent_node_index--;
}
// Map connected subtrees
HashSet<int> old_indices = connection_info.input_subtree_node_indices;
connection_info.input_subtree_node_indices.clear();
@ -563,13 +567,14 @@ bool BLTAnimationNodeBlendTree::BLTBlendTreeGraph::remove_node(const Ref<BLTAnim
void BLTAnimationNodeBlendTree::BLTBlendTreeGraph::sort_nodes_and_references() {
LocalVector<int> sorted_node_indices = get_sorted_node_indices();
Vector<Ref<BLTAnimationNode>> sorted_nodes;
LocalVector<Ref<BLTAnimationNode>> sorted_nodes;
LocalVector<NodeConnectionInfo> old_node_connection_info = node_connection_info;
for (unsigned int i = 0; i < sorted_node_indices.size(); i++) {
int node_index = sorted_node_indices[i];
sorted_nodes.push_back(nodes[node_index]);
node_connection_info[i] = old_node_connection_info[node_index];
}
nodes = sorted_nodes;
for (NodeConnectionInfo &connection_info : node_connection_info) {
@ -586,6 +591,20 @@ LocalVector<int> BLTAnimationNodeBlendTree::BLTBlendTreeGraph::get_sorted_node_i
sort_nodes_recursive(0, result);
result.reverse();
HashSet<int> connected_node_indices;
for (int node_index : result) {
connected_node_indices.insert(node_index);
}
// Ensure that nodes that are not reachable from the root node are still added to
// the sorted nodes indices.
for (Ref<BLTAnimationNode> &node : nodes) {
int node_index = find_node_index(node);
if (!connected_node_indices.has(node_index)) {
result.push_back(node_index);
}
}
return result;
}

View File

@ -537,7 +537,14 @@ TEST_CASE_FIXTURE(BlendTreeFixture, "[SceneTree][Blendalot][BlendTreeGraph][Chan
CHECK(blend_tree_graph.node_connection_info[0].input_subtree_node_indices.size() == 6);
CHECK(blend_tree_graph.node_connection_info[blend2_node_a_index_pre_remove].input_subtree_node_indices.size() == 5);
SUBCASE("Remove animation_sampler_node_a") {
SUBCASE("Removing the output node does nothing") {
int num_nodes = blend_tree_graph.nodes.size();
int num_connections = blend_tree_graph.connections.size();
CHECK(blend_tree_graph.remove_node(blend_tree_graph.get_output_node()) == false);
CHECK(blend_tree_graph.connections.size() == num_connections);
}
SUBCASE("Remove a node with no children") {
blend_tree_graph.remove_node(animation_sampler_node_a);
for (const BLTBlendTreeConnection &connection : blend_tree_graph.connections) {
@ -561,8 +568,12 @@ TEST_CASE_FIXTURE(BlendTreeFixture, "[SceneTree][Blendalot][BlendTreeGraph][Chan
CHECK(blend_tree_graph.node_connection_info[blend2_node_b_index_post_remove].input_subtree_node_indices.has(animation_sampler_node_b_index_post_remove));
}
SUBCASE("Remove blend2_node_a") {
SUBCASE("Remove a node with parent and children") {
int num_nodes = blend_tree_graph.nodes.size();
blend_tree_graph.remove_node(blend2_node_a);
blend_tree_graph.sort_nodes_and_references();
CHECK(blend_tree_graph.nodes.size() == num_nodes - 1);
for (const BLTBlendTreeConnection &connection : blend_tree_graph.connections) {
bool is_connection_with_removed_node = connection.source_node == blend2_node_a || connection.target_node == blend2_node_a;