From 625a3ae79fe779bf0c47193d4f09439ef4dfb2b9 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sun, 18 Jan 2026 23:02:06 +0100 Subject: [PATCH] Started exposing more functions to GDScript and made BLTBlendTreeGraph part of BLTBlendTree such that return codes look nicer in Godot. --- blendalot_animation_node.cpp | 173 ++++++++++++++++- blendalot_animation_node.h | 291 ++++++++-------------------- demo/main.gd | 13 ++ demo/synced_blend_tree_node.tres | 20 +- register_types.cpp | 1 + tests/test_synced_animation_graph.h | 33 ++-- 6 files changed, 289 insertions(+), 242 deletions(-) diff --git a/blendalot_animation_node.cpp b/blendalot_animation_node.cpp index 285ee1c..1418d25 100644 --- a/blendalot_animation_node.cpp +++ b/blendalot_animation_node.cpp @@ -41,6 +41,18 @@ void BLTAnimationNode::_animation_node_removed(const ObjectID &p_oid, const Stri } void BLTAnimationNodeBlendTree::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_node", "animation_node"), &BLTAnimationNodeBlendTree::add_node); + ClassDB::bind_method(D_METHOD("get_output_node"), &BLTAnimationNodeBlendTree::get_output_node); + ClassDB::bind_method(D_METHOD("add_connection", "source_node", "target_node", "target_port_name"), &BLTAnimationNodeBlendTree::add_connection); + + BIND_CONSTANT(CONNECTION_OK); + BIND_CONSTANT(CONNECTION_ERROR_GRAPH_ALREADY_INITIALIZED); + BIND_CONSTANT(CONNECTION_ERROR_NO_SOURCE_NODE); + BIND_CONSTANT(CONNECTION_ERROR_NO_TARGET_NODE); + BIND_CONSTANT(CONNECTION_ERROR_PARENT_EXISTS); + BIND_CONSTANT(CONNECTION_ERROR_TARGET_PORT_NOT_FOUND); + BIND_CONSTANT(CONNECTION_ERROR_TARGET_PORT_ALREADY_CONNECTED); + BIND_CONSTANT(CONNECTION_ERROR_CONNECTION_CREATES_LOOP); } void BLTAnimationNodeBlendTree::_get_property_list(List *p_list) const { @@ -395,4 +407,163 @@ bool BLTAnimationNodeBlend2::_set(const StringName &p_name, const Variant &p_val } return false; -} \ No newline at end of file +} + +BLTAnimationNodeBlendTree::BLTBlendTreeGraph::BLTBlendTreeGraph() { + Ref output_node; + output_node.instantiate(); + output_node->name = "Output"; + add_node(output_node); +} + +Ref BLTAnimationNodeBlendTree::BLTBlendTreeGraph::get_output_node() { + return nodes[0]; +} + +int BLTAnimationNodeBlendTree::BLTBlendTreeGraph::find_node_index(const Ref &node) const { + for (int i = 0; i < nodes.size(); i++) { + if (nodes[i] == node) { + return i; + } + } + + return -1; +} + +int BLTAnimationNodeBlendTree::BLTBlendTreeGraph::find_node_index_by_name(const StringName &name) const { + for (int i = 0; i < nodes.size(); i++) { + if (nodes[i]->name == name) { + return i; + } + } + + return -1; +} + +void BLTAnimationNodeBlendTree::BLTBlendTreeGraph::add_node(const Ref &node) { + StringName node_base_name = node->name; + if (node_base_name.is_empty()) { + node_base_name = node->get_class_name(); + } + node->name = node_base_name; + + int number_suffix = 1; + while (find_node_index_by_name(node->name) != -1) { + node->name = vformat("%s %d", node_base_name, number_suffix); + number_suffix++; + } + + nodes.push_back(node); + node_connection_info.push_back(NodeConnectionInfo(node.ptr())); +} + +void BLTAnimationNodeBlendTree::BLTBlendTreeGraph::sort_nodes_and_references() { + LocalVector sorted_node_indices = get_sorted_node_indices(); + + Vector> sorted_nodes; + LocalVector 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) { + if (connection_info.parent_node_index != -1) { + connection_info.parent_node_index = sorted_node_indices[connection_info.parent_node_index]; + } + connection_info.apply_node_mapping(sorted_node_indices); + } +} + +LocalVector BLTAnimationNodeBlendTree::BLTBlendTreeGraph::get_sorted_node_indices() { + LocalVector result; + + sort_nodes_recursive(0, result); + result.reverse(); + + return result; +} + +void BLTAnimationNodeBlendTree::BLTBlendTreeGraph::sort_nodes_recursive(int node_index, LocalVector &result) { + for (int input_node_index : node_connection_info[node_index].connected_child_node_index_at_port) { + if (input_node_index >= 0) { + sort_nodes_recursive(input_node_index, result); + } + } + result.push_back(node_index); +} + +void BLTAnimationNodeBlendTree::BLTBlendTreeGraph::add_index_and_update_subtrees_recursive(int node, int node_parent) { + if (node_parent == -1) { + return; + } + + node_connection_info[node_parent].input_subtree_node_indices.insert(node); + + for (int index : node_connection_info[node].input_subtree_node_indices) { + node_connection_info[node_parent].input_subtree_node_indices.insert(index); + } + + add_index_and_update_subtrees_recursive(node_parent, node_connection_info[node_parent].parent_node_index); +} + +BLTAnimationNodeBlendTree::ConnectionError BLTAnimationNodeBlendTree::BLTBlendTreeGraph::add_connection(const Ref &source_node, const Ref &target_node, const StringName &target_port_name) { + ConnectionError result = is_connection_valid(source_node, target_node, target_port_name); + if (result != CONNECTION_OK) { + return result; + } + + int source_node_index = find_node_index(source_node); + int target_node_index = find_node_index(target_node); + int target_input_port_index = target_node->get_input_index(target_port_name); + + node_connection_info[source_node_index].parent_node_index = target_node_index; + node_connection_info[target_node_index].connected_child_node_index_at_port[target_input_port_index] = source_node_index; + connections.push_back(BLTBlendTreeConnection{ source_node, target_node, target_port_name }); + + add_index_and_update_subtrees_recursive(source_node_index, target_node_index); + + return CONNECTION_OK; +} + +BLTAnimationNodeBlendTree::ConnectionError BLTAnimationNodeBlendTree::BLTBlendTreeGraph::is_connection_valid(const Ref &source_node, const Ref &target_node, StringName target_port_name) const { + int source_node_index = find_node_index(source_node); + if (source_node_index == -1) { + print_error("Cannot connect nodes: source node not found."); + return CONNECTION_ERROR_NO_SOURCE_NODE; + } + + if (node_connection_info[source_node_index].parent_node_index != -1) { + print_error("Cannot connect node: source node already has a parent."); + return CONNECTION_ERROR_PARENT_EXISTS; + } + + int target_node_index = find_node_index(target_node); + if (target_node_index == -1) { + print_error("Cannot connect nodes: target node not found."); + return CONNECTION_ERROR_NO_TARGET_NODE; + } + + Vector target_inputs; + target_node->get_input_names(target_inputs); + + if (!target_inputs.has(target_port_name)) { + print_error("Cannot connect nodes: target port not found."); + return CONNECTION_ERROR_TARGET_PORT_NOT_FOUND; + } + + int target_input_port_index = target_node->get_input_index(target_port_name); + if (node_connection_info[target_node_index].connected_child_node_index_at_port[target_input_port_index] != -1) { + print_error("Cannot connect node: target port already connected"); + return CONNECTION_ERROR_TARGET_PORT_ALREADY_CONNECTED; + } + + if (node_connection_info[source_node_index].input_subtree_node_indices.has(target_node_index)) { + print_error("Cannot connect node: connection would create loop."); + return CONNECTION_ERROR_CONNECTION_CREATES_LOOP; + } + + return CONNECTION_OK; +} diff --git a/blendalot_animation_node.h b/blendalot_animation_node.h index 3e8af64..a3f4ee7 100644 --- a/blendalot_animation_node.h +++ b/blendalot_animation_node.h @@ -428,221 +428,79 @@ struct BLTBlendTreeConnection { const StringName target_port_name = ""; }; -/** - * @class BLTBlendTreeGraph - * Helper class that is used to build runtime blend trees and also to validate connections. - */ -struct BLTBlendTreeGraph { - struct NodeConnectionInfo { - int parent_node_index = -1; - HashSet input_subtree_node_indices; // Contains all nodes down to the tree leaves that influence this node. - LocalVector connected_child_node_index_at_port; // Contains for each input port the index of the node that is connected to it. - - NodeConnectionInfo() = default; - - explicit NodeConnectionInfo(const BLTAnimationNode *node) { - parent_node_index = -1; - for (int i = 0; i < node->get_input_count(); i++) { - connected_child_node_index_at_port.push_back(-1); - } - } - - void _print_subtree() const { - String result = vformat("subtree node indices (%d): ", input_subtree_node_indices.size()); - bool is_first = true; - for (int index : input_subtree_node_indices) { - if (is_first) { - result += vformat("%d", index); - is_first = false; - } else { - result += vformat(", %d", index); - } - } - print_line(result); - } - - void apply_node_mapping(const LocalVector &node_index_mapping) { - // Map connected node indices - for (unsigned int j = 0; j < connected_child_node_index_at_port.size(); j++) { - int connected_node_index = connected_child_node_index_at_port[j]; - connected_child_node_index_at_port[j] = node_index_mapping.find(connected_node_index); - } - - // Map connected subtrees - HashSet old_indices = input_subtree_node_indices; - input_subtree_node_indices.clear(); - for (int old_index : old_indices) { - input_subtree_node_indices.insert(node_index_mapping.find(old_index)); - } - } - }; - - Vector> nodes; // All added nodes - LocalVector node_connection_info; - LocalVector connections; - - BLTBlendTreeGraph() { - Ref output_node; - output_node.instantiate(); - output_node->name = "Output"; - add_node(output_node); - } - - Ref get_output_node() const { - return nodes[0]; - } - - int find_node_index(const Ref &node) const { - for (int i = 0; i < nodes.size(); i++) { - if (nodes[i] == node) { - return i; - } - } - - return -1; - } - - int find_node_index_by_name(const StringName &name) const { - for (int i = 0; i < nodes.size(); i++) { - if (nodes[i]->name == name) { - return i; - } - } - - return -1; - } - - void add_node(const Ref &node) { - StringName node_base_name = node->name; - if (node_base_name.is_empty()) { - node_base_name = node->get_class_name(); - } - node->name = node_base_name; - - int number_suffix = 1; - while (find_node_index_by_name(node->name) != -1) { - node->name = vformat("%s %d", node_base_name, number_suffix); - number_suffix++; - } - - nodes.push_back(node); - node_connection_info.push_back(NodeConnectionInfo(node.ptr())); - } - - void sort_nodes_and_references() { - LocalVector sorted_node_indices = get_sorted_node_indices(); - - Vector> sorted_nodes; - LocalVector 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) { - if (connection_info.parent_node_index != -1) { - connection_info.parent_node_index = sorted_node_indices[connection_info.parent_node_index]; - } - connection_info.apply_node_mapping(sorted_node_indices); - } - } - - LocalVector get_sorted_node_indices() { - LocalVector result; - - sort_nodes_recursive(0, result); - result.reverse(); - - return result; - } - - void sort_nodes_recursive(int node_index, LocalVector &result) { - for (int input_node_index : node_connection_info[node_index].connected_child_node_index_at_port) { - if (input_node_index >= 0) { - sort_nodes_recursive(input_node_index, result); - } - } - result.push_back(node_index); - } - - void add_index_and_update_subtrees_recursive(int node, int node_parent) { - if (node_parent == -1) { - return; - } - - node_connection_info[node_parent].input_subtree_node_indices.insert(node); - - for (int index : node_connection_info[node].input_subtree_node_indices) { - node_connection_info[node_parent].input_subtree_node_indices.insert(index); - } - - add_index_and_update_subtrees_recursive(node_parent, node_connection_info[node_parent].parent_node_index); - } - - bool add_connection(const Ref &source_node, const Ref &target_node, const StringName &target_port_name) { - if (!is_connection_valid(source_node, target_node, target_port_name)) { - return false; - } - - int source_node_index = find_node_index(source_node); - int target_node_index = find_node_index(target_node); - int target_input_port_index = target_node->get_input_index(target_port_name); - - node_connection_info[source_node_index].parent_node_index = target_node_index; - node_connection_info[target_node_index].connected_child_node_index_at_port[target_input_port_index] = source_node_index; - connections.push_back(BLTBlendTreeConnection{ source_node, target_node, target_port_name }); - - add_index_and_update_subtrees_recursive(source_node_index, target_node_index); - - return true; - } - - bool is_connection_valid(const Ref &source_node, const Ref &target_node, StringName target_port_name) { - int source_node_index = find_node_index(source_node); - if (source_node_index == -1) { - print_error("Cannot connect nodes: source node not found."); - return false; - } - - if (node_connection_info[source_node_index].parent_node_index != -1) { - print_error("Cannot connect node: source node already has a parent."); - return false; - } - - int target_node_index = find_node_index(target_node); - if (target_node_index == -1) { - print_error("Cannot connect nodes: target node not found."); - return false; - } - - Vector target_inputs; - target_node->get_input_names(target_inputs); - - if (!target_inputs.has(target_port_name)) { - print_error("Cannot connect nodes: target port not found."); - return false; - } - - int target_input_port_index = target_node->get_input_index(target_port_name); - if (node_connection_info[target_node_index].connected_child_node_index_at_port[target_input_port_index] != -1) { - print_error("Cannot connect node: target port already connected"); - return false; - } - - if (node_connection_info[source_node_index].input_subtree_node_indices.has(target_node_index)) { - print_error("Cannot connect node: connection would create loop."); - return false; - } - - return true; - } -}; - class BLTAnimationNodeBlendTree : public BLTAnimationNode { GDCLASS(BLTAnimationNodeBlendTree, BLTAnimationNode); +public: + enum ConnectionError { + CONNECTION_OK, + CONNECTION_ERROR_GRAPH_ALREADY_INITIALIZED, + CONNECTION_ERROR_NO_SOURCE_NODE, + CONNECTION_ERROR_NO_TARGET_NODE, + CONNECTION_ERROR_PARENT_EXISTS, + CONNECTION_ERROR_TARGET_PORT_NOT_FOUND, + CONNECTION_ERROR_TARGET_PORT_ALREADY_CONNECTED, + CONNECTION_ERROR_CONNECTION_CREATES_LOOP, + }; + + /** + * @class BLTBlendTreeGraph + * Helper class that is used to build runtime blend trees and also to validate connections. + */ + struct BLTBlendTreeGraph { + struct NodeConnectionInfo { + int parent_node_index = -1; + HashSet input_subtree_node_indices; // Contains all nodes down to the tree leaves that influence this node. + LocalVector connected_child_node_index_at_port; // Contains for each input port the index of the node that is connected to it. + + NodeConnectionInfo() = default; + + explicit NodeConnectionInfo(const BLTAnimationNode *node) { + parent_node_index = -1; + for (int i = 0; i < node->get_input_count(); i++) { + connected_child_node_index_at_port.push_back(-1); + } + } + + void apply_node_mapping(const LocalVector &node_index_mapping) { + // Map connected node indices + for (unsigned int j = 0; j < connected_child_node_index_at_port.size(); j++) { + int connected_node_index = connected_child_node_index_at_port[j]; + connected_child_node_index_at_port[j] = node_index_mapping.find(connected_node_index); + } + + // Map connected subtrees + HashSet old_indices = input_subtree_node_indices; + input_subtree_node_indices.clear(); + for (int old_index : old_indices) { + input_subtree_node_indices.insert(node_index_mapping.find(old_index)); + } + } + + void _print_subtree() const; + }; + + Vector> nodes; // All added nodes + LocalVector node_connection_info; + LocalVector connections; + + BLTBlendTreeGraph(); + + Ref get_output_node(); + + int find_node_index(const Ref &node) const; + int find_node_index_by_name(const StringName &name) const; + void sort_nodes_and_references(); + LocalVector get_sorted_node_indices(); + void sort_nodes_recursive(int node_index, LocalVector &result); + void add_index_and_update_subtrees_recursive(int node, int node_parent); + ConnectionError is_connection_valid(const Ref &source_node, const Ref &target_node, StringName target_port_name) const; + + void add_node(const Ref &node); + ConnectionError add_connection(const Ref &source_node, const Ref &target_node, const StringName &target_port_name); + }; + +private: BLTBlendTreeGraph tree_graph; bool tree_initialized = false; @@ -720,10 +578,10 @@ public: tree_graph.add_node(node); } - bool add_connection(const Ref &source_node, const Ref &target_node, const StringName &target_port_name) { + ConnectionError add_connection(const Ref &source_node, const Ref &target_node, const StringName &target_port_name) { if (tree_initialized) { print_error("Cannot add connection to BlendTree: BlendTree already initialized."); - return false; + return CONNECTION_ERROR_GRAPH_ALREADY_INITIALIZED; } return tree_graph.add_connection(source_node, target_node, target_port_name); @@ -745,7 +603,8 @@ public: return true; } - void activate_inputs(const Vector> &input_nodes) override { + void + activate_inputs(const Vector> &input_nodes) override { GodotProfileZone("SyncedBlendTree::activate_inputs"); tree_graph.nodes[0]->active = true; @@ -839,3 +698,5 @@ public: } } }; + +VARIANT_ENUM_CAST(BLTAnimationNodeBlendTree::ConnectionError) diff --git a/demo/main.gd b/demo/main.gd index d4963cc..9934242 100644 --- a/demo/main.gd +++ b/demo/main.gd @@ -12,6 +12,19 @@ extends Node3D func _ready() -> void: blend_weight_slider.value = 0.5 + var blend_tree: BLTAnimationNodeBlendTree = BLTAnimationNodeBlendTree.new() + var output_node: BLTAnimationNodeOutput = blend_tree.get_output_node() + var sampler_node_1: BLTAnimationNodeSampler = BLTAnimationNodeSampler.new() + + sampler_node_1.animation = "animation_library/Walk-InPlace" + + blend_tree.add_node(sampler_node_1) + var result = blend_tree.add_connection(sampler_node_1, output_node, "Input") + var anim_graph: BLTAnimationGraph = mixamo_amy_walk_run_synced.get_node("SyncedAnimationGraph") + + anim_graph.tree_root = blend_tree + + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass diff --git a/demo/synced_blend_tree_node.tres b/demo/synced_blend_tree_node.tres index 1afa9ed..e3124c5 100644 --- a/demo/synced_blend_tree_node.tres +++ b/demo/synced_blend_tree_node.tres @@ -1,21 +1,21 @@ -[gd_resource type="SyncedBlendTree" load_steps=4 format=3] +[gd_resource type="BLTAnimationNodeBlendTree" load_steps=4 format=3] -[sub_resource type="AnimationSamplerNode" id="AnimationSamplerNode_bvt3d"] +[sub_resource type="BLTAnimationNodeSampler" id="BLTAnimationNodeSampler_bvt3d"] animation = &"animation_library/TestAnimationB" -[sub_resource type="AnimationSamplerNode" id="AnimationSamplerNode_sntl5"] +[sub_resource type="BLTAnimationNodeSampler" id="BLTAnimationNodeSampler_sntl5"] animation = &"animation_library/TestAnimationA" -[sub_resource type="AnimationBlend2Node" id="AnimationBlend2Node_n4m28"] +[sub_resource type="BLTAnimationNodeBlend2" id="BLTAnimationNodeBlend2_n4m28"] sync = false blend_amount = 0.5 sync = false [resource] -nodes/Blend2/node = SubResource("AnimationBlend2Node_n4m28") +nodes/Blend2/node = SubResource("BLTAnimationNodeBlend2_n4m28") nodes/Blend2/position = Vector2(0, 0) -"nodes/AnimationSamplerNode 1/node" = SubResource("AnimationSamplerNode_bvt3d") -"nodes/AnimationSamplerNode 1/position" = Vector2(0, 0) -nodes/AnimationSamplerNode/node = SubResource("AnimationSamplerNode_sntl5") -nodes/AnimationSamplerNode/position = Vector2(0, 0) -node_connections = [&"Blend2", 0, &"AnimationSamplerNode", &"Blend2", 1, &"AnimationSamplerNode 1", &"Output", 0, &"Blend2"] +"nodes/BLTAnimationNodeSampler 1/node" = SubResource("BLTAnimationNodeSampler_bvt3d") +"nodes/BLTAnimationNodeSampler 1/position" = Vector2(0, 0) +nodes/BLTAnimationNodeSampler/node = SubResource("BLTAnimationNodeSampler_sntl5") +nodes/BLTAnimationNodeSampler/position = Vector2(0, 0) +node_connections = [&"Blend2", 0, &"BLTAnimationNodeSampler", &"Blend2", 1, &"BLTAnimationNodeSampler 1", &"Output", 0, &"Blend2"] diff --git a/register_types.cpp b/register_types.cpp index a924f42..e33bf83 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -9,6 +9,7 @@ void initialize_blendalot_animgraph_module(ModuleInitializationLevel p_level) { } ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); diff --git a/tests/test_synced_animation_graph.h b/tests/test_synced_animation_graph.h index 8d6e373..f3923a9 100644 --- a/tests/test_synced_animation_graph.h +++ b/tests/test_synced_animation_graph.h @@ -142,7 +142,7 @@ struct SyncedAnimationGraphFixture { namespace TestSyncedAnimationGraph { TEST_CASE("[SyncedAnimationGraph] Test BlendTree construction") { - BlendTreeGraph tree_constructor; + BLTAnimationNodeBlendTree::BLTBlendTreeGraph tree_constructor; Ref animation_sampler_node0; animation_sampler_node0.instantiate(); @@ -174,7 +174,7 @@ TEST_CASE("[SyncedAnimationGraph] Test BlendTree construction") { // Sampler1 -+ Blend0 -\ // Sampler2 -----------+ Blend1 - Output - CHECK(tree_constructor.add_connection(animation_sampler_node0, node_blend0, "Input0")); + CHECK(BLTAnimationNodeBlendTree::CONNECTION_OK == tree_constructor.add_connection(animation_sampler_node0, node_blend0, "Input0")); // Ensure that subtree is properly updated int sampler0_index = tree_constructor.find_node_index(animation_sampler_node0); @@ -182,12 +182,16 @@ TEST_CASE("[SyncedAnimationGraph] Test BlendTree construction") { CHECK(tree_constructor.node_connection_info[blend0_index].input_subtree_node_indices.has(sampler0_index)); // Connect blend0 to blend1 - CHECK(tree_constructor.add_connection(node_blend0, node_blend1, "Input0")); + CHECK(BLTAnimationNodeBlendTree::CONNECTION_OK == tree_constructor.add_connection(node_blend0, node_blend1, "Input0")); + + // Creating a loop must fail + CHECK(BLTAnimationNodeBlendTree::CONNECTION_ERROR_CONNECTION_CREATES_LOOP == tree_constructor.add_connection(node_blend1, node_blend0, "Input1")); + + // Correct connection of Sampler1 to Blend0 + CHECK(BLTAnimationNodeBlendTree::CONNECTION_OK == tree_constructor.add_connection(animation_sampler_node1, node_blend0, "Input1")); // Connecting to an already connected port must fail - CHECK(!tree_constructor.add_connection(animation_sampler_node1, node_blend0, "Input0")); - // Correct connection of Sampler1 to Blend0 - CHECK(tree_constructor.add_connection(animation_sampler_node1, node_blend0, "Input1")); + CHECK(BLTAnimationNodeBlendTree::CONNECTION_ERROR_TARGET_PORT_ALREADY_CONNECTED == tree_constructor.add_connection(animation_sampler_node2, node_blend0, "Input0")); // Ensure that subtree is properly updated int sampler1_index = tree_constructor.find_node_index(animation_sampler_node0); @@ -196,12 +200,9 @@ TEST_CASE("[SyncedAnimationGraph] Test BlendTree construction") { CHECK(tree_constructor.node_connection_info[blend1_index].input_subtree_node_indices.has(sampler0_index)); CHECK(tree_constructor.node_connection_info[blend1_index].input_subtree_node_indices.has(blend0_index)); - // Creating a loop must fail - CHECK(!tree_constructor.add_connection(node_blend1, node_blend0, "Input1")); - // Perform remaining connections - CHECK(tree_constructor.add_connection(node_blend1, tree_constructor.get_output_node(), "Input")); - CHECK(tree_constructor.add_connection(animation_sampler_node2, node_blend1, "Input1")); + CHECK(BLTAnimationNodeBlendTree::CONNECTION_OK == tree_constructor.add_connection(node_blend1, tree_constructor.get_output_node(), "Input")); + CHECK(BLTAnimationNodeBlendTree::CONNECTION_OK == tree_constructor.add_connection(animation_sampler_node2, node_blend1, "Input1")); // Output node must have all nodes in its subtree: CHECK(tree_constructor.node_connection_info[0].input_subtree_node_indices.has(1)); @@ -286,7 +287,7 @@ TEST_CASE_FIXTURE(SyncedAnimationGraphFixture, "[SceneTree][SyncedAnimationGraph animation_sampler_node->animation_name = "animation_library/TestAnimationA"; synced_blend_tree_node->add_node(animation_sampler_node); - REQUIRE(synced_blend_tree_node->add_connection(animation_sampler_node, synced_blend_tree_node->get_output_node(), "Input")); + REQUIRE(BLTAnimationNodeBlendTree::CONNECTION_OK == synced_blend_tree_node->add_connection(animation_sampler_node, synced_blend_tree_node->get_output_node(), "Input")); synced_blend_tree_node->initialize(synced_animation_graph->get_context()); @@ -337,9 +338,9 @@ TEST_CASE_FIXTURE(SyncedAnimationGraphFixture, "[SceneTree][SyncedAnimationGraph // Connect nodes Vector blend2_inputs; blend2_node->get_input_names(blend2_inputs); - REQUIRE(synced_blend_tree_node->add_connection(animation_sampler_node_a, blend2_node, blend2_inputs[0])); - REQUIRE(synced_blend_tree_node->add_connection(animation_sampler_node_b, blend2_node, blend2_inputs[1])); - REQUIRE(synced_blend_tree_node->add_connection(blend2_node, synced_blend_tree_node->get_output_node(), "Input")); + REQUIRE(BLTAnimationNodeBlendTree::CONNECTION_OK == synced_blend_tree_node->add_connection(animation_sampler_node_a, blend2_node, blend2_inputs[0])); + REQUIRE(BLTAnimationNodeBlendTree::CONNECTION_OK == synced_blend_tree_node->add_connection(animation_sampler_node_b, blend2_node, blend2_inputs[1])); + REQUIRE(BLTAnimationNodeBlendTree::CONNECTION_OK == synced_blend_tree_node->add_connection(blend2_node, synced_blend_tree_node->get_output_node(), "Input")); synced_blend_tree_node->initialize(synced_animation_graph->get_context()); @@ -430,7 +431,7 @@ TEST_CASE_FIXTURE(SyncedAnimationGraphFixture, "[SceneTree][SyncedAnimationGraph // Test saving and loading of the blend tree to a resource ResourceSaver::save(synced_blend_tree_node, "synced_blend_tree_node.tres"); - REQUIRE(ClassDB::class_exists("AnimationSamplerNode")); + REQUIRE(ClassDB::class_exists("BLTAnimationNodeSampler")); // Load blend tree Ref loaded_synced_blend_tree = ResourceLoader::load("synced_blend_tree_node.tres");