From d95bc9fb9cc159ea6d2102b1f4ed53d48f1730df Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Tue, 16 Apr 2024 22:11:59 +0200 Subject: [PATCH] Made BlendTreeResource::m_nodes and ::m_connections private. This is a prerequisite to properly track Node input/output connections and to compute eval order in the BlendTreeResources. --- src/AnimGraph/AnimGraphResource.cc | 96 ++++---- src/AnimGraph/AnimGraphResource.h | 56 ++++- tests/AnimGraphResourceTests.cc | 344 ++++++++++------------------- 3 files changed, 220 insertions(+), 276 deletions(-) diff --git a/src/AnimGraph/AnimGraphResource.cc b/src/AnimGraph/AnimGraphResource.cc index 8331cdd..4f73ce4 100644 --- a/src/AnimGraph/AnimGraphResource.cc +++ b/src/AnimGraph/AnimGraphResource.cc @@ -222,16 +222,16 @@ AnimNodeResource* sAnimGraphNodeFromJson( // // AnimGraphConnectionResource <-> Json // -json sAnimGraphConnectionToJson(const BlendTreeConnectionResource& connection) { +json sAnimGraphConnectionToJson(const BlendTreeConnectionResource* connection) { json result; result["type"] = "AnimGraphConnectionResource"; - result["source_node_index"] = connection.source_node_index; - result["source_socket_name"] = connection.source_socket_name; + result["source_node_index"] = connection->source_node_index; + result["source_socket_name"] = connection->source_socket_name; - result["target_node_index"] = connection.target_node_index; - result["target_socket_name"] = connection.target_socket_name; + result["target_node_index"] = connection->target_node_index; + result["target_socket_name"] = connection->target_socket_name; return result; } @@ -260,8 +260,8 @@ static json sAnimGraphResourceBlendTreeToJson( const BlendTreeResource& blend_tree_resource = anim_graph_resource.m_blend_tree_resource; - for (size_t i = 0; i < blend_tree_resource.m_nodes.size(); i++) { - const AnimNodeResource* node = blend_tree_resource.m_nodes[i]; + for (size_t i = 0; i < blend_tree_resource.GetNumNodes(); i++) { + const AnimNodeResource* node = blend_tree_resource.GetNode(i); if (node->m_node_type_name == "BlendTree") { const AnimGraphResource* graph_resource = @@ -269,26 +269,26 @@ static json sAnimGraphResourceBlendTreeToJson( result["nodes"][i] = sAnimGraphResourceBlendTreeToJson(*graph_resource); } else { result["nodes"][i] = - sAnimGraphNodeToJson(node, i, blend_tree_resource.m_connections); + sAnimGraphNodeToJson(node, i, blend_tree_resource.GetConnections()); } } - for (size_t i = 0; i < blend_tree_resource.m_connections.size(); i++) { - const BlendTreeConnectionResource& connection = - blend_tree_resource.m_connections[i]; + for (size_t i = 0; i < blend_tree_resource.GetNumConnections(); i++) { + const BlendTreeConnectionResource* connection = + blend_tree_resource.GetConnection(i); result["connections"][i] = sAnimGraphConnectionToJson(connection); } // Graph inputs and outputs { - const AnimNodeResource* graph_output_node = blend_tree_resource.m_nodes[0]; + const AnimNodeResource* graph_output_node = blend_tree_resource.GetNode(0); const std::vector graph_inputs = graph_output_node->m_socket_accessor->m_inputs; for (size_t i = 0; i < graph_inputs.size(); i++) { result["nodes"][0]["inputs"][i] = sSocketToJson(graph_inputs[i]); } - const AnimNodeResource* graph_input_node = blend_tree_resource.m_nodes[1]; + const AnimNodeResource* graph_input_node = blend_tree_resource.GetNode(1); const std::vector graph_outputs = graph_input_node->m_socket_accessor->m_outputs; for (size_t i = 0; i < graph_outputs.size(); i++) { @@ -319,13 +319,13 @@ static bool sAnimGraphResourceBlendTreeFromJson( } AnimNodeResource* node = sAnimGraphNodeFromJson(json_node, i); - blend_tree_resource.m_nodes.push_back(node); + blend_tree_resource.AddNode(node); } // Graph outputs const json& graph_outputs = json_data["nodes"][0]["inputs"]; for (const auto& graph_output : graph_outputs) { - AnimNodeResource* graph_node = blend_tree_resource.m_nodes[0]; + AnimNodeResource* graph_node = blend_tree_resource.GetNode(0); graph_node->m_socket_accessor->m_inputs.push_back( sJsonToSocket(graph_output)); } @@ -334,7 +334,7 @@ static bool sAnimGraphResourceBlendTreeFromJson( if (json_data["nodes"][1].contains("outputs")) { const json& graph_inputs = json_data["nodes"][1]["outputs"]; for (const auto& graph_input : graph_inputs) { - AnimNodeResource* graph_node = blend_tree_resource.m_nodes[1]; + AnimNodeResource* graph_node = blend_tree_resource.GetNode(1); graph_node->m_socket_accessor->m_outputs.push_back( sJsonToSocket(graph_input)); } @@ -352,7 +352,12 @@ static bool sAnimGraphResourceBlendTreeFromJson( BlendTreeConnectionResource connection = sAnimGraphConnectionFromJson(json_connection); - blend_tree_resource.m_connections.push_back(connection); + + blend_tree_resource.ConnectSockets( + blend_tree_resource.GetNode(connection.source_node_index), + connection.source_socket_name, + blend_tree_resource.GetNode(connection.target_node_index), + connection.target_socket_name); } return true; @@ -420,6 +425,11 @@ bool BlendTreeResource::ConnectSockets( connection.target_socket_name = target_socket_name; m_connections.push_back(connection); + m_node_input_connection_indices[target_node_index].emplace_back( + m_connections.size() - 1); + m_node_output_connection_indices[source_node_index].emplace_back( + m_connections.size() - 1); + return true; } @@ -509,12 +519,13 @@ void AnimGraphResource::CreateBlendTreeInstance( void AnimGraphResource::CreateBlendTreeRuntimeNodeInstances( AnimGraphBlendTree& result) const { - for (auto node_resource : m_blend_tree_resource.m_nodes) { + for (const AnimNodeResource* node_resource : + m_blend_tree_resource.GetNodes()) { AnimNode* node = AnimNodeFactory(node_resource->m_node_type_name); if (node_resource->m_node_type_name == "BlendTree") { - AnimGraphResource* embedded_blend_tree_resource = - dynamic_cast(node_resource); + const AnimGraphResource* embedded_blend_tree_resource = + dynamic_cast(node_resource); assert(embedded_blend_tree_resource != nullptr); AnimGraphBlendTree* embedded_blend_tree = dynamic_cast(node); @@ -545,9 +556,9 @@ void AnimGraphResource::PrepareBlendTreeIOData( AnimNodeDescriptorFactory("BlendTree", instance.m_nodes[0]); instance.m_node_descriptor->m_outputs = - m_blend_tree_resource.m_nodes[1]->m_socket_accessor->m_outputs; + m_blend_tree_resource.GetNode(1)->m_socket_accessor->m_outputs; instance.m_node_descriptor->m_inputs = - m_blend_tree_resource.m_nodes[0]->m_socket_accessor->m_inputs; + m_blend_tree_resource.GetNode(0)->m_socket_accessor->m_inputs; // // graph inputs @@ -597,9 +608,10 @@ void AnimGraphResource::PrepareBlendTreeIOData( // connecton data storage // size_t connection_data_storage_size = 0; - for (const auto& connection : m_blend_tree_resource.m_connections) { + for (const BlendTreeConnectionResource& connection : + m_blend_tree_resource.GetConnections()) { const AnimNodeResource* source_node = - m_blend_tree_resource.m_nodes[connection.source_node_index]; + m_blend_tree_resource.GetNode(connection.source_node_index); Socket* source_socket = source_node->m_socket_accessor->GetOutputSocket( connection.source_socket_name.c_str()); @@ -622,19 +634,19 @@ void AnimGraphResource::CreateBlendTreeConnectionInstances( AnimGraphBlendTree& instance, NodeSocketDataOffsetMap& node_offset_map) const { std::vector instance_node_descriptors( - m_blend_tree_resource.m_nodes.size(), + m_blend_tree_resource.GetNumNodes(), nullptr); - for (int i = 0; i < m_blend_tree_resource.m_nodes.size(); i++) { + for (int i = 0; i < m_blend_tree_resource.GetNumNodes(); i++) { instance_node_descriptors[i] = AnimNodeDescriptorFactory( - m_blend_tree_resource.m_nodes[i]->m_node_type_name, + m_blend_tree_resource.GetNode(i)->m_node_type_name, instance.m_nodes[i]); if (i > 1 - && m_blend_tree_resource.m_nodes[i]->m_node_type_name == "BlendTree") { + && m_blend_tree_resource.GetNode(i)->m_node_type_name == "BlendTree") { instance_node_descriptors[i]->m_inputs = - m_blend_tree_resource.m_nodes[i]->m_socket_accessor->m_inputs; + m_blend_tree_resource.GetNode(i)->m_socket_accessor->m_inputs; instance_node_descriptors[i]->m_outputs = - m_blend_tree_resource.m_nodes[i]->m_socket_accessor->m_outputs; + m_blend_tree_resource.GetNode(i)->m_socket_accessor->m_outputs; } } @@ -642,7 +654,9 @@ void AnimGraphResource::CreateBlendTreeConnectionInstances( instance_node_descriptors[1]->m_outputs = instance.m_node_descriptor->m_outputs; - for (const auto& connection : m_blend_tree_resource.m_connections) { + size_t connection_data_offset = 0; + for (const BlendTreeConnectionResource& connection : + m_blend_tree_resource.GetConnections()) { NodeDescriptorBase* source_node_descriptor = instance_node_descriptors[connection.source_node_index]; NodeDescriptorBase* target_node_descriptor = @@ -684,9 +698,9 @@ void AnimGraphResource::CreateBlendTreeConnectionInstances( instance.m_node_output_connections[connection.source_node_index] .push_back(embedded_graph_activation_connection); - AnimGraphResource* source_blend_tree_resource = - dynamic_cast( - m_blend_tree_resource.m_nodes[connection.source_node_index]); + const AnimGraphResource* source_blend_tree_resource = + dynamic_cast( + m_blend_tree_resource.GetNode(connection.source_node_index)); AnimGraphBlendTree* source_blend_tree = dynamic_cast(source_node); @@ -701,9 +715,9 @@ void AnimGraphResource::CreateBlendTreeConnectionInstances( // that the embedded node knows about its connection partner in the parent // tree. This allows the embedded node to properly activate the node in // the parent graph. - AnimGraphResource* target_blend_tree_resource = - dynamic_cast( - m_blend_tree_resource.m_nodes[connection.target_node_index]); + const AnimGraphResource* target_blend_tree_resource = + dynamic_cast( + m_blend_tree_resource.GetNode(connection.target_node_index)); AnimGraphBlendTree* target_blend_tree = dynamic_cast(target_node); @@ -750,7 +764,7 @@ void AnimGraphResource::CreateBlendTreeConnectionInstances( } NodeSocketPair node_socket_pair{ - m_blend_tree_resource.m_nodes[connection.source_node_index], + m_blend_tree_resource.GetNode(connection.source_node_index), source_socket->m_name}; NodeSocketDataOffsetMap::const_iterator socket_data_offset_iter = @@ -822,15 +836,15 @@ void AnimGraphResource::CreateBlendTreeConnectionInstances( const_input_buffer_offset += i->m_type_size; } - for (int i = 0; i < m_blend_tree_resource.m_nodes.size(); i++) { + for (int i = 0; i < m_blend_tree_resource.GetNumNodes(); i++) { delete instance_node_descriptors[i]; } } void AnimGraphResource::SetRuntimeNodeProperties( AnimGraphBlendTree& result) const { - for (int i = 2; i < m_blend_tree_resource.m_nodes.size(); i++) { - const AnimNodeResource* node_resource = m_blend_tree_resource.m_nodes[i]; + for (int i = 2; i < m_blend_tree_resource.GetNumNodes(); i++) { + const AnimNodeResource* node_resource = m_blend_tree_resource.GetNode(i); NodeDescriptorBase* node_instance_accessor = AnimNodeDescriptorFactory( node_resource->m_node_type_name, diff --git a/src/AnimGraph/AnimGraphResource.h b/src/AnimGraph/AnimGraphResource.h index e7dfca9..466092d 100644 --- a/src/AnimGraph/AnimGraphResource.h +++ b/src/AnimGraph/AnimGraphResource.h @@ -32,8 +32,8 @@ struct BlendTreeConnectionResource { }; struct BlendTreeResource { - std::vector m_nodes; - std::vector m_connections; + std::vector > m_node_input_connection_indices; + std::vector > m_node_output_connection_indices; ~BlendTreeResource() { CleanupNodes(); } @@ -41,6 +41,9 @@ struct BlendTreeResource { CleanupNodes(); m_connections.clear(); + + m_node_input_connection_indices.clear(); + m_node_output_connection_indices.clear(); } void CleanupNodes() { @@ -54,10 +57,13 @@ struct BlendTreeResource { } void InitGraphConnectors() { - m_nodes.push_back(AnimNodeResourceFactory("BlendTreeSockets")); - m_nodes[0]->m_name = "Outputs"; - m_nodes.push_back(AnimNodeResourceFactory("BlendTreeSockets")); - m_nodes[1]->m_name = "Inputs"; + AddNode(AnimNodeResourceFactory("BlendTreeSockets")); + AnimNodeResource* output_node = GetGraphOutputNode(); + output_node->m_name = "Outputs"; + + AddNode(AnimNodeResourceFactory("BlendTreeSockets")); + AnimNodeResource* input_node = GetGraphInputNode(); + output_node->m_name = "Inputs"; } [[nodiscard]] AnimNodeResource* GetGraphOutputNode() const { @@ -77,6 +83,40 @@ struct BlendTreeResource { return -1; } + [[maybe_unused]] size_t AddNode(AnimNodeResource* node_resource) { + m_nodes.push_back(node_resource); + m_node_input_connection_indices.emplace_back(); + m_node_output_connection_indices.emplace_back(); + return m_nodes.size() - 1; + } + + [[nodiscard]] size_t GetNumNodes() const { return m_nodes.size(); } + [[nodiscard]] AnimNodeResource* GetNode(size_t i) { return m_nodes[i]; } + [[nodiscard]] const AnimNodeResource* GetNode(size_t i) const { + return m_nodes[i]; + } + [[nodiscard]] const std::vector& GetNodes() const { + return m_nodes; + } + + [[nodiscard]] size_t GetNumConnections() const { + return m_connections.size(); + } + + [[nodiscard]] BlendTreeConnectionResource* GetConnection(size_t i) { + return &m_connections[i]; + } + + [[nodiscard]] const BlendTreeConnectionResource* GetConnection( + size_t i) const { + return &m_connections[i]; + } + + [[nodiscard]] const std::vector& GetConnections() + const { + return m_connections; + } + bool ConnectSockets( const AnimNodeResource* source_node, const std::string& source_socket_name, @@ -143,6 +183,10 @@ struct BlendTreeResource { return -1; } + + private: + std::vector m_nodes; + std::vector m_connections; }; struct StateMachineTransitionResources { diff --git a/tests/AnimGraphResourceTests.cc b/tests/AnimGraphResourceTests.cc index ec1ccfd..dd88e4a 100644 --- a/tests/AnimGraphResourceTests.cc +++ b/tests/AnimGraphResourceTests.cc @@ -28,11 +28,9 @@ class SimpleAnimSamplerGraphResource { blend_tree_resource->InitGraphConnectors(); // Prepare graph inputs and outputs - blend_tree_resource->m_nodes.push_back( - AnimNodeResourceFactory("AnimSampler")); - walk_node_index = blend_tree_resource->m_nodes.size() - 1; - - walk_node = blend_tree_resource->m_nodes[walk_node_index]; + walk_node_index = + blend_tree_resource->AddNode(AnimNodeResourceFactory("AnimSampler")); + walk_node = blend_tree_resource->GetNode(walk_node_index); walk_node->m_name = "WalkAnim"; walk_node->m_socket_accessor->SetPropertyValue( "Filename", @@ -72,28 +70,26 @@ class Blend2GraphResource { blend_tree_resource->InitGraphConnectors(); // Prepare graph inputs and outputs - blend_tree_resource->m_nodes.push_back( - AnimNodeResourceFactory("AnimSampler")); - walk_node_index = blend_tree_resource->m_nodes.size() - 1; + walk_node_index = + blend_tree_resource->AddNode(AnimNodeResourceFactory("AnimSampler")); - blend_tree_resource->m_nodes.push_back( - AnimNodeResourceFactory("AnimSampler")); - run_node_index = blend_tree_resource->m_nodes.size() - 1; + run_node_index = + blend_tree_resource->AddNode(AnimNodeResourceFactory("AnimSampler")); - blend_tree_resource->m_nodes.push_back(AnimNodeResourceFactory("Blend2")); - blend_node_index = blend_tree_resource->m_nodes.size() - 1; + blend_node_index = + blend_tree_resource->AddNode(AnimNodeResourceFactory("Blend2")); - walk_node = blend_tree_resource->m_nodes[walk_node_index]; + walk_node = blend_tree_resource->GetNode(walk_node_index); walk_node->m_name = "WalkAnim"; walk_node->m_socket_accessor->SetPropertyValue( "Filename", std::string("media/Walking-loop.ozz")); - run_node = blend_tree_resource->m_nodes[run_node_index]; + run_node = blend_tree_resource->GetNode(run_node_index); run_node->m_socket_accessor->SetPropertyValue( "Filename", std::string("media/Running0-loop.ozz")); run_node->m_name = "RunAnim"; - blend_node = blend_tree_resource->m_nodes[blend_node_index]; + blend_node = blend_tree_resource->GetNode(blend_node_index); blend_node->m_name = "BlendWalkRun"; AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode(); @@ -161,11 +157,10 @@ class EmbeddedBlendTreeGraphResource { nullptr); // Parent AnimSampler - parent_blend_tree_resource->m_nodes.push_back( + walk_node_index = parent_blend_tree_resource->AddNode( AnimNodeResourceFactory("AnimSampler")); - walk_node_index = parent_blend_tree_resource->m_nodes.size() - 1; - walk_node_resource = parent_blend_tree_resource->m_nodes[walk_node_index]; + walk_node_resource = parent_blend_tree_resource->GetNode(walk_node_index); walk_node_resource->m_name = "WalkAnim"; walk_node_resource->m_socket_accessor->SetPropertyValue( "Filename", @@ -174,12 +169,10 @@ class EmbeddedBlendTreeGraphResource { // // Embedded Tree // - parent_blend_tree_resource->m_nodes.push_back( + embedded_blend_tree_node_index = parent_blend_tree_resource->AddNode( AnimNodeResourceFactory("BlendTree")); - embedded_blend_tree_node_index = - parent_blend_tree_resource->m_nodes.size() - 1; embedded_graph = dynamic_cast( - parent_blend_tree_resource->m_nodes.back()); + parent_blend_tree_resource->GetNode(embedded_blend_tree_node_index)); embedded_graph->m_name = "EmbeddedBlendTree"; embedded_graph->m_node_type_name = "BlendTree"; embedded_graph->m_graph_type_name = "BlendTree"; @@ -200,12 +193,10 @@ class EmbeddedBlendTreeGraphResource { nullptr); // Embedded: SpeedScale node - embedded_blend_tree_resource->m_nodes.push_back( + embedded_speed_scale_index = embedded_blend_tree_resource->AddNode( AnimNodeResourceFactory("SpeedScale")); - embedded_speed_scale_index = - embedded_blend_tree_resource->m_nodes.size() - 1; AnimNodeResource* embedded_speed_scale_resource = - embedded_blend_tree_resource->m_nodes[embedded_speed_scale_index]; + embedded_blend_tree_resource->GetNode(embedded_speed_scale_index); embedded_speed_scale_resource->m_socket_accessor->SetInputValue( "SpeedScale", 0.1f); @@ -291,11 +282,10 @@ class EmbeddedTreeBlend2GraphResource { nullptr); // Parent AnimSampler - parent_blend_tree_resource->m_nodes.push_back( + walk_node_index = parent_blend_tree_resource->AddNode( AnimNodeResourceFactory("AnimSampler")); - walk_node_index = parent_blend_tree_resource->m_nodes.size() - 1; - walk_node_resource = parent_blend_tree_resource->m_nodes[walk_node_index]; + walk_node_resource = parent_blend_tree_resource->GetNode(walk_node_index); walk_node_resource->m_name = "WalkAnim"; walk_node_resource->m_socket_accessor->SetPropertyValue( "Filename", @@ -304,12 +294,10 @@ class EmbeddedTreeBlend2GraphResource { // // Embedded Tree // - parent_blend_tree_resource->m_nodes.push_back( + embedded_blend_tree_node_index = parent_blend_tree_resource->AddNode( AnimNodeResourceFactory("BlendTree")); - embedded_blend_tree_node_index = - parent_blend_tree_resource->m_nodes.size() - 1; embedded_graph = dynamic_cast( - parent_blend_tree_resource->m_nodes.back()); + parent_blend_tree_resource->GetNode(embedded_blend_tree_node_index)); embedded_graph->m_name = "EmbeddedTreeBlend2GraphResource"; embedded_graph->m_node_type_name = "BlendTree"; embedded_graph->m_graph_type_name = "BlendTree"; @@ -333,24 +321,21 @@ class EmbeddedTreeBlend2GraphResource { nullptr); // Embedded nodes - embedded_blend_tree_resource->m_nodes.push_back( + embedded_blend2_node_index = embedded_blend_tree_resource->AddNode( AnimNodeResourceFactory("Blend2")); - embedded_blend2_node_index = - embedded_blend_tree_resource->m_nodes.size() - 1; - embedded_blend_tree_resource->m_nodes.push_back( + embedded_run_node_index = embedded_blend_tree_resource->AddNode( AnimNodeResourceFactory("AnimSampler")); - embedded_run_node_index = embedded_blend_tree_resource->m_nodes.size() - 1; // Configure node resources embedded_blend2_node_resource = - embedded_blend_tree_resource->m_nodes[embedded_blend2_node_index]; + embedded_blend_tree_resource->GetNode(embedded_blend2_node_index); embedded_blend2_node_resource->m_socket_accessor->SetInputValue( "Weight", 0.1f); embedded_run_node_resource = - embedded_blend_tree_resource->m_nodes[embedded_run_node_index]; + embedded_blend_tree_resource->GetNode(embedded_run_node_index); embedded_run_node_resource->m_name = "RunAnim"; embedded_run_node_resource->m_socket_accessor->SetPropertyValue( "Filename", @@ -418,6 +403,64 @@ bool load_skeleton(ozz::animation::Skeleton& skeleton, const char* filename) { return true; } +void CheckBlendTreeResourcesEqual( + const BlendTreeResource* blend_tree_resource_reference, + const BlendTreeResource* blend_tree_resource_rhs) { + REQUIRE( + blend_tree_resource_reference->GetNumNodes() + == blend_tree_resource_rhs->GetNumNodes()); + for (size_t i = 0; i < blend_tree_resource_reference->GetNumNodes(); i++) { + const AnimNodeResource* node = blend_tree_resource_reference->GetNode(i); + const AnimNodeResource* node_loaded = blend_tree_resource_rhs->GetNode(i); + + REQUIRE(node->m_name == node_loaded->m_name); + REQUIRE(node->m_node_type_name == node_loaded->m_node_type_name); + } + + REQUIRE( + blend_tree_resource_reference->GetNumConnections() + == blend_tree_resource_rhs->GetNumConnections()); + for (size_t i = 0; i < blend_tree_resource_reference->GetNumConnections(); + i++) { + const BlendTreeConnectionResource* connection = + blend_tree_resource_reference->GetConnection(i); + const BlendTreeConnectionResource* connection_loaded = + blend_tree_resource_rhs->GetConnection(i); + + REQUIRE( + connection->source_node_index == connection_loaded->source_node_index); + REQUIRE( + connection->source_socket_name + == connection_loaded->source_socket_name); + REQUIRE( + connection->target_node_index == connection_loaded->target_node_index); + REQUIRE( + connection->target_socket_name + == connection_loaded->target_socket_name); + } +} + +void CheckAnimGraphResourceEqual( + const AnimGraphResource& graph_resource_reference, + const AnimGraphResource& graph_resource_rhs) { + REQUIRE( + graph_resource_reference.m_graph_type_name + == graph_resource_rhs.m_graph_type_name); + REQUIRE(graph_resource_reference.m_name == graph_resource_rhs.m_name); + + REQUIRE(graph_resource_reference.m_graph_type_name == "BlendTree"); + + const BlendTreeResource* blend_tree_resource_reference = + &graph_resource_reference.m_blend_tree_resource; + + const BlendTreeResource* blend_tree_resource_rhs = + &graph_resource_rhs.m_blend_tree_resource; + + CheckBlendTreeResourcesEqual( + blend_tree_resource_reference, + blend_tree_resource_rhs); +} + TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") { int node_id = 3321; int input_index = 221; @@ -447,44 +490,7 @@ TEST_CASE_METHOD( AnimGraphResource graph_resource_loaded; graph_resource_loaded.LoadFromFile("TestGraphAnimSamplerBlendTree.json"); - REQUIRE( - graph_resource.m_graph_type_name - == graph_resource_loaded.m_graph_type_name); - REQUIRE(graph_resource.m_name == graph_resource_loaded.m_name); - - BlendTreeResource* blend_tree_resource_loaded = - &graph_resource_loaded.m_blend_tree_resource; - - REQUIRE( - blend_tree_resource->m_nodes.size() - == blend_tree_resource_loaded->m_nodes.size()); - for (size_t i = 0; i < blend_tree_resource->m_nodes.size(); i++) { - const AnimNodeResource* node = blend_tree_resource->m_nodes[i]; - const AnimNodeResource* node_loaded = - blend_tree_resource_loaded->m_nodes[i]; - - REQUIRE(node->m_name == node_loaded->m_name); - REQUIRE(node->m_node_type_name == node_loaded->m_node_type_name); - } - - REQUIRE( - blend_tree_resource->m_connections.size() - == blend_tree_resource_loaded->m_connections.size()); - for (size_t i = 0; i < blend_tree_resource->m_connections.size(); i++) { - const BlendTreeConnectionResource& connection = - blend_tree_resource->m_connections[i]; - const BlendTreeConnectionResource& connection_loaded = - blend_tree_resource_loaded->m_connections[i]; - - REQUIRE( - connection.source_node_index == connection_loaded.source_node_index); - REQUIRE( - connection.source_socket_name == connection_loaded.source_socket_name); - REQUIRE( - connection.target_node_index == connection_loaded.target_node_index); - REQUIRE( - connection.target_socket_name == connection_loaded.target_socket_name); - } + CheckAnimGraphResourceEqual(graph_resource, graph_resource_loaded); } TEST_CASE_METHOD( @@ -558,20 +564,20 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { blend_tree_resource.InitGraphConnectors(); // Prepare graph inputs and outputs - blend_tree_resource.m_nodes.push_back(AnimNodeResourceFactory("AnimSampler")); - size_t walk_node_index = blend_tree_resource.m_nodes.size() - 1; + size_t walk_node_index = + blend_tree_resource.AddNode(AnimNodeResourceFactory("AnimSampler")); - blend_tree_resource.m_nodes.push_back(AnimNodeResourceFactory("SpeedScale")); - size_t speed_scale_node_index = blend_tree_resource.m_nodes.size() - 1; + size_t speed_scale_node_index = + blend_tree_resource.AddNode(AnimNodeResourceFactory("SpeedScale")); - AnimNodeResource* walk_node = blend_tree_resource.m_nodes[walk_node_index]; + AnimNodeResource* walk_node = blend_tree_resource.GetNode(walk_node_index); walk_node->m_name = "WalkAnim"; walk_node->m_socket_accessor->SetPropertyValue( "Filename", std::string("media/Walking-loop.ozz")); AnimNodeResource* speed_scale_node = - blend_tree_resource.m_nodes[speed_scale_node_index]; + blend_tree_resource.GetNode(speed_scale_node_index); speed_scale_node->m_name = "SpeedScale"; float speed_scale_value = 1.35f; speed_scale_node->m_socket_accessor->SetInputValue( @@ -602,7 +608,7 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { graph_resource_loaded.m_blend_tree_resource; Socket* speed_scale_resource_loaded_input = - blend_tree_resource_loaded.m_nodes[speed_scale_node_index] + blend_tree_resource_loaded.GetNode(speed_scale_node_index) ->m_socket_accessor->GetInputSocket("SpeedScale"); REQUIRE(speed_scale_resource_loaded_input != nullptr); @@ -628,50 +634,16 @@ TEST_CASE_METHOD( AnimGraphResource graph_resource_loaded; graph_resource_loaded.LoadFromFile("TestGraphBlend2Graph.animgraph.json"); - REQUIRE( - graph_resource.m_graph_type_name - == graph_resource_loaded.m_graph_type_name); - REQUIRE(graph_resource.m_name == graph_resource_loaded.m_name); + CheckAnimGraphResourceEqual(graph_resource, graph_resource_loaded); BlendTreeResource* blend_tree_resource_loaded = &graph_resource_loaded.m_blend_tree_resource; - REQUIRE( - blend_tree_resource->m_nodes.size() - == blend_tree_resource_loaded->m_nodes.size()); - for (size_t i = 0; i < blend_tree_resource->m_nodes.size(); i++) { - const AnimNodeResource* node = blend_tree_resource->m_nodes[i]; - const AnimNodeResource* node_loaded = - blend_tree_resource_loaded->m_nodes[i]; - - REQUIRE(node->m_name == node_loaded->m_name); - REQUIRE(node->m_node_type_name == node_loaded->m_node_type_name); - } - - REQUIRE( - blend_tree_resource->m_connections.size() - == blend_tree_resource_loaded->m_connections.size()); - for (size_t i = 0; i < blend_tree_resource->m_connections.size(); i++) { - const BlendTreeConnectionResource& connection = - blend_tree_resource->m_connections[i]; - const BlendTreeConnectionResource& connection_loaded = - blend_tree_resource_loaded->m_connections[i]; - - REQUIRE( - connection.source_node_index == connection_loaded.source_node_index); - REQUIRE( - connection.source_socket_name == connection_loaded.source_socket_name); - REQUIRE( - connection.target_node_index == connection_loaded.target_node_index); - REQUIRE( - connection.target_socket_name == connection_loaded.target_socket_name); - } - // Check that the constant weight of the Blend2 node was properly applied when // loading the resource. const NodeDescriptor* blend2_node_descriptor_loaded = dynamic_cast*>( - blend_tree_resource_loaded->m_nodes[blend_node_index] + blend_tree_resource_loaded->GetNode(blend_node_index) ->m_socket_accessor); REQUIRE_THAT( @@ -794,9 +766,8 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { blend_tree_resource.InitGraphConnectors(); // Prepare graph inputs and outputs - blend_tree_resource.m_nodes.push_back( + size_t float_to_vec3_node_index = blend_tree_resource.AddNode( AnimNodeResourceFactory("MathFloatToVec3Node")); - size_t float_to_vec3_node_index = blend_tree_resource.m_nodes.size() - 1; AnimNodeResource* graph_output_node = blend_tree_resource.GetGraphOutputNode(); @@ -815,7 +786,7 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { // Prepare graph inputs and outputs AnimNodeResource* float_to_vec3_node_resource = - blend_tree_resource.m_nodes[float_to_vec3_node_index]; + blend_tree_resource.GetNode(float_to_vec3_node_index); REQUIRE(blend_tree_resource.ConnectSockets( graph_input_node_resource, @@ -856,9 +827,9 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { graph_resource_loaded.m_blend_tree_resource; const AnimNodeResource* graph_loaded_output_node = - graph_blend_tree_loaded.m_nodes[0]; + graph_blend_tree_loaded.GetGraphOutputNode(); const AnimNodeResource* graph_loaded_input_node = - graph_blend_tree_loaded.m_nodes[1]; + graph_blend_tree_loaded.GetGraphInputNode(); THEN("Graph inputs and outputs must be in loaded resource as well.") { REQUIRE( @@ -952,11 +923,10 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { blend_tree_resource.InitGraphConnectors(); // Prepare graph inputs and outputs - blend_tree_resource.m_nodes.push_back(AnimNodeResourceFactory("MathAddNode")); - size_t math_add0_node_index = blend_tree_resource.m_nodes.size() - 1; - - blend_tree_resource.m_nodes.push_back(AnimNodeResourceFactory("MathAddNode")); - size_t math_add1_node_index = blend_tree_resource.m_nodes.size() - 1; + size_t math_add0_node_index = + blend_tree_resource.AddNode(AnimNodeResourceFactory("MathAddNode")); + size_t math_add1_node_index = + blend_tree_resource.AddNode(AnimNodeResourceFactory("MathAddNode")); AnimNodeResource* graph_output_node = blend_tree_resource.GetGraphOutputNode(); @@ -978,9 +948,9 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { // Prepare graph inputs and outputs AnimNodeResource* math_add0_node = - blend_tree_resource.m_nodes[math_add0_node_index]; + blend_tree_resource.GetNode(math_add0_node_index); AnimNodeResource* math_add1_node = - blend_tree_resource.m_nodes[math_add1_node_index]; + blend_tree_resource.GetNode(math_add1_node_index); // direct output REQUIRE(blend_tree_resource.ConnectSockets( @@ -1095,112 +1065,28 @@ TEST_CASE_METHOD( AnimGraphResource parent_graph_resource_loaded; parent_graph_resource_loaded.LoadFromFile("TestGraphEmbeddedBlendTree.json"); - // // Check the loaded parent graph - // - CHECK(parent_graph_resource.m_name == parent_graph_resource_loaded.m_name); - CHECK( - parent_graph_resource.m_graph_type_name - == parent_graph_resource_loaded.m_graph_type_name); - CHECK( - parent_graph_resource.m_node_type_name - == parent_graph_resource_loaded.m_node_type_name); + CheckAnimGraphResourceEqual( + parent_graph_resource, + parent_graph_resource_loaded); const BlendTreeResource& parent_blend_tree_resource_loaded = parent_graph_resource_loaded.m_blend_tree_resource; - CHECK( - parent_blend_tree_resource->m_nodes.size() - == parent_blend_tree_resource_loaded.m_nodes.size()); - for (size_t i = 0; i < parent_blend_tree_resource->m_nodes.size(); i++) { - const AnimNodeResource* parent_node = - parent_blend_tree_resource->m_nodes[i]; - const AnimNodeResource* parent_node_loaded = - parent_blend_tree_resource_loaded.m_nodes[i]; - - CHECK(parent_node->m_name == parent_node_loaded->m_name); - CHECK( - parent_node->m_node_type_name == parent_node_loaded->m_node_type_name); - } - - CHECK( - parent_blend_tree_resource->m_connections.size() - == parent_blend_tree_resource_loaded.m_connections.size()); - for (size_t i = 0; i < parent_blend_tree_resource->m_connections.size(); - i++) { - const BlendTreeConnectionResource& parent_connection = - parent_blend_tree_resource->m_connections[i]; - const BlendTreeConnectionResource& parent_connection_loaded = - parent_blend_tree_resource_loaded.m_connections[i]; - - CHECK( - parent_connection.source_node_index - == parent_connection_loaded.source_node_index); - CHECK( - parent_connection.source_socket_name - == parent_connection_loaded.source_socket_name); - CHECK( - parent_connection.target_node_index - == parent_connection_loaded.target_node_index); - CHECK( - parent_connection.target_socket_name - == parent_connection_loaded.target_socket_name); - } - - // // Check the loaded embedded graph - // REQUIRE( - parent_blend_tree_resource_loaded.m_nodes[3]->m_node_type_name + parent_blend_tree_resource_loaded.GetNode(3)->m_node_type_name == "BlendTree"); const AnimGraphResource* embedded_graph_loaded = - dynamic_cast( - parent_blend_tree_resource_loaded.m_nodes[3]); - const BlendTreeResource& embedded_blend_tree_resource_loaded = - embedded_graph_loaded->m_blend_tree_resource; + dynamic_cast( + parent_blend_tree_resource_loaded.GetNode(3)); + const BlendTreeResource* embedded_blend_tree_resource_loaded = + &embedded_graph_loaded->m_blend_tree_resource; - CHECK( - embedded_blend_tree_resource->m_nodes.size() - == embedded_blend_tree_resource_loaded.m_nodes.size()); - CHECK( - embedded_blend_tree_resource->m_connections.size() - == embedded_blend_tree_resource_loaded.m_connections.size()); - - for (size_t i = 0; i < embedded_blend_tree_resource->m_nodes.size(); i++) { - const AnimNodeResource* parent_node = - embedded_blend_tree_resource->m_nodes[i]; - const AnimNodeResource* parent_node_loaded = - embedded_blend_tree_resource_loaded.m_nodes[i]; - - CHECK(parent_node->m_name == parent_node_loaded->m_name); - CHECK( - parent_node->m_node_type_name == parent_node_loaded->m_node_type_name); - } - - CHECK( - embedded_blend_tree_resource->m_connections.size() - == embedded_blend_tree_resource_loaded.m_connections.size()); - for (size_t i = 0; i < embedded_blend_tree_resource->m_connections.size(); - i++) { - const BlendTreeConnectionResource& embedded_connection = - embedded_blend_tree_resource->m_connections[i]; - const BlendTreeConnectionResource& embedded_connection_loaded = - embedded_blend_tree_resource_loaded.m_connections[i]; - - CHECK( - embedded_connection.source_node_index - == embedded_connection_loaded.source_node_index); - CHECK( - embedded_connection.source_socket_name - == embedded_connection_loaded.source_socket_name); - CHECK( - embedded_connection.target_node_index - == embedded_connection_loaded.target_node_index); - CHECK( - embedded_connection.target_socket_name - == embedded_connection_loaded.target_socket_name); - } + CheckBlendTreeResourcesEqual( + embedded_blend_tree_resource, + embedded_blend_tree_resource_loaded); } TEST_CASE_METHOD(