From 99f11e61d837aa66ac20f8eee4bb80f2dedab5a5 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Mon, 25 Mar 2024 21:10:27 +0100 Subject: [PATCH] Refactored AnimGraphResourceTests such that some tests use reusable fixtures. --- src/AnimGraph/AnimGraphData.h | 17 + tests/AnimGraphResourceTests.cc | 701 ++++++++++++++++++++++---------- 2 files changed, 495 insertions(+), 223 deletions(-) diff --git a/src/AnimGraph/AnimGraphData.h b/src/AnimGraph/AnimGraphData.h index cd3423f..d9ad84e 100644 --- a/src/AnimGraph/AnimGraphData.h +++ b/src/AnimGraph/AnimGraphData.h @@ -319,6 +319,13 @@ struct NodeDescriptorBase { return *socket->m_reference.ptr_ptr; } + template + T GetInputValue(const char* name) const { + const Socket* socket = FindSocket(name, m_inputs); + assert(GetSocketType() == socket->m_type); + return socket->GetValue(); + } + template void SetInput(const char* name, T* value_ptr) { Socket* socket = FindSocket(name, m_inputs); @@ -423,6 +430,16 @@ struct NodeDescriptorBase { return nullptr; } + const Socket* FindSocket(const char* name, const std::vector& sockets) const { + for (int i = 0, n = sockets.size(); i < n; i++) { + if (sockets[i].m_name == name) { + return &sockets[i]; + } + } + + return nullptr; + } + int FindSocketIndex(const char* name, std::vector& sockets) { for (int i = 0, n = sockets.size(); i < n; i++) { if (sockets[i].m_name == name) { diff --git a/tests/AnimGraphResourceTests.cc b/tests/AnimGraphResourceTests.cc index bc50d48..2e275ca 100644 --- a/tests/AnimGraphResourceTests.cc +++ b/tests/AnimGraphResourceTests.cc @@ -12,6 +12,223 @@ #include "ozz/base/io/stream.h" #include "ozz/base/log.h" +class SimpleAnimSamplerGraphResource { + protected: + AnimGraphResource graph_resource; + BlendTreeResource* blend_tree_resource = nullptr; + size_t walk_node_index = -1; + AnimNodeResource* walk_node = nullptr; + + public: + SimpleAnimSamplerGraphResource() { + graph_resource.m_name = "AnimSamplerBlendTree"; + graph_resource.m_node_type_name = "BlendTree"; + graph_resource.m_graph_type_name = "BlendTree"; + + blend_tree_resource = &graph_resource.m_blend_tree_resource; + 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->m_name = "WalkAnim"; + walk_node->m_socket_accessor->SetPropertyValue( + "Filename", + std::string("media/Walking-loop.ozz")); + + AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode(); + graph_node->m_socket_accessor->RegisterInput( + "GraphOutput", + nullptr); + + blend_tree_resource->ConnectSockets( + walk_node, + "Output", + blend_tree_resource->GetGraphOutputNode(), + "GraphOutput"); + } +}; + +class Blend2GraphResource { + protected: + AnimGraphResource graph_resource; + BlendTreeResource* blend_tree_resource = nullptr; + size_t walk_node_index = -1; + size_t run_node_index = -1; + size_t blend_node_index = -1; + AnimNodeResource* walk_node = nullptr; + AnimNodeResource* run_node = nullptr; + AnimNodeResource* blend_node = nullptr; + + public: + Blend2GraphResource() { + graph_resource.m_name = "WalkRunBlendGraph"; + graph_resource.m_node_type_name = "BlendTree"; + graph_resource.m_graph_type_name = "BlendTree"; + + blend_tree_resource = &graph_resource.m_blend_tree_resource; + 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; + + blend_tree_resource->m_nodes.push_back( + AnimNodeResourceFactory("AnimSampler")); + run_node_index = blend_tree_resource->m_nodes.size() - 1; + + blend_tree_resource->m_nodes.push_back(AnimNodeResourceFactory("Blend2")); + blend_node_index = blend_tree_resource->m_nodes.size() - 1; + + walk_node = blend_tree_resource->m_nodes[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->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->m_name = "BlendWalkRun"; + + AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode(); + graph_node->m_socket_accessor->RegisterInput( + "GraphOutput", + nullptr); + + REQUIRE(graph_node->m_socket_accessor->m_inputs.size() == 1); + REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input0") == 0); + REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input1") == 1); + blend_node->m_socket_accessor->SetInputValue("Weight", 0.123f); + + blend_tree_resource + ->ConnectSockets(walk_node, "Output", blend_node, "Input0"); + blend_tree_resource + ->ConnectSockets(run_node, "Output", blend_node, "Input1"); + blend_tree_resource->ConnectSockets( + blend_node, + "Output", + blend_tree_resource->GetGraphOutputNode(), + "GraphOutput"); + } +}; + +// +// Used for tests with a BlendTree within a BlendTree +// +// +-----------Parent BlendTree-------------+ +// | | +// | +-----Embd Btree---+ | +// | AnmSmpl--+-\ | | +// | | \-SpdScale------+--Out | +// | |------------------+ | +// | | +// +----------------------------------------+ +// +class EmbeddedBlendTreeGraphResource { + protected: + AnimGraphResource parent_graph_resource; + BlendTreeResource* parent_blend_tree_resource = nullptr; + + AnimGraphResource* embedded_graph = nullptr; + BlendTreeResource* embedded_blend_tree_resource = nullptr; + + size_t walk_node_index = -1; + AnimNodeResource* walk_node = nullptr; + + public: + EmbeddedBlendTreeGraphResource() { + const char* parent_graph_filename = "TestGraphEmbeddedBlendTree.json"; + parent_graph_resource.m_name = "ParentBlendTree"; + parent_graph_resource.m_graph_type_name = "BlendTree"; + parent_graph_resource.m_node_type_name = "BlendTree"; + + parent_blend_tree_resource = &parent_graph_resource.m_blend_tree_resource; + parent_blend_tree_resource->Reset(); + parent_blend_tree_resource->InitGraphConnectors(); + + // Setup parent outputs + AnimNodeResource* parent_blend_tree_outputs = + parent_blend_tree_resource->GetGraphOutputNode(); + parent_blend_tree_outputs->m_socket_accessor->RegisterInput( + "Output", + nullptr); + + // Parent AnimSampler + parent_blend_tree_resource->m_nodes.push_back( + AnimNodeResourceFactory("AnimSampler")); + + walk_node = parent_blend_tree_resource->m_nodes.back(); + walk_node->m_name = "WalkAnim"; + walk_node->m_socket_accessor->SetPropertyValue( + "Filename", + std::string("media/Walking-loop.ozz")); + + // + // Embedded Tree + // + parent_blend_tree_resource->m_nodes.push_back( + AnimNodeResourceFactory("BlendTree")); + size_t embedded_blend_tree_node_index = + parent_blend_tree_resource->m_nodes.size() - 1; + embedded_graph = dynamic_cast( + parent_blend_tree_resource->m_nodes.back()); + embedded_graph->m_name = "EmbeddedBlendTree"; + embedded_graph->m_node_type_name = "BlendTree"; + embedded_blend_tree_resource = &embedded_graph->m_blend_tree_resource; + + // Embedded: outputs + AnimNodeResource* embedded_outputs = + embedded_blend_tree_resource->GetGraphOutputNode(); + embedded_outputs->m_socket_accessor->RegisterInput( + "AnimOutput", + nullptr); + + // Embedded: inputs + AnimNodeResource* embedded_inputs = + embedded_blend_tree_resource->GetGraphInputNode(); + embedded_inputs->m_socket_accessor->RegisterOutput( + "AnimInput", + nullptr); + + // Embedded: SpeedScale node + embedded_blend_tree_resource->m_nodes.push_back( + AnimNodeResourceFactory("SpeedScale")); + AnimNodeResource* embedded_speed_scale_resource = + embedded_blend_tree_resource->m_nodes.back(); + + // Embedded: setup connections + embedded_blend_tree_resource->ConnectSockets( + embedded_inputs, + "AnimInput", + embedded_speed_scale_resource, + "Input"); + embedded_blend_tree_resource->ConnectSockets( + embedded_speed_scale_resource, + "Output", + embedded_outputs, + "AnimOutput"); + + // Parent: setup connections + REQUIRE(parent_blend_tree_resource->ConnectSockets( + walk_node, + "Output", + embedded_graph, + "AnimInput")); + REQUIRE(parent_blend_tree_resource->ConnectSockets( + embedded_graph, + "AnimOutput", + parent_blend_tree_outputs, + "Output")); + } +}; + bool load_skeleton(ozz::animation::Skeleton& skeleton, const char* filename) { assert(filename); ozz::io::File file(filename, "rb"); @@ -52,40 +269,62 @@ TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") { CHECK(output_index == parsed_output_index); } -TEST_CASE("AnimSamplerGraph", "[AnimGraphResource]") { - AnimGraphResource graph_resource; - graph_resource.m_name = "AnimSamplerBlendTree"; - graph_resource.m_graph_type_name = "BlendTree"; - - BlendTreeResource& blend_tree_resource = graph_resource.m_blend_tree_resource; - 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; - - AnimNodeResource* walk_node = blend_tree_resource.m_nodes[walk_node_index]; - walk_node->m_name = "WalkAnim"; - walk_node->m_socket_accessor->SetPropertyValue( - "Filename", - std::string("media/Walking-loop.ozz")); - - AnimNodeResource* graph_node = blend_tree_resource.m_nodes[0]; - graph_node->m_socket_accessor->RegisterInput("GraphOutput", nullptr); - - blend_tree_resource.ConnectSockets( - walk_node, - "Output", - blend_tree_resource.GetGraphOutputNode(), - "GraphOutput"); - +TEST_CASE_METHOD( + SimpleAnimSamplerGraphResource, + "SimpleAnimSamplerGraphResource saving and loading results in same " + "resource", + "[SimpleAnimSamplerGraphResource]") { graph_resource.SaveToFile("TestGraphAnimSamplerBlendTree.json"); 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); + } +} + +TEST_CASE_METHOD( + SimpleAnimSamplerGraphResource, + "SimpleAnimSamplerGraphResource emulated evaluation", + "[SimpleAnimSamplerGraphResource]") { AnimGraphBlendTree anim_graph_blend_tree; - graph_resource_loaded.CreateBlendTreeInstance(anim_graph_blend_tree); + graph_resource.CreateBlendTreeInstance(anim_graph_blend_tree); AnimGraphContext graph_context; ozz::animation::Skeleton skeleton; @@ -95,8 +334,10 @@ TEST_CASE("AnimSamplerGraph", "[AnimGraphResource]") { REQUIRE(anim_graph_blend_tree.Init(graph_context)); REQUIRE(anim_graph_blend_tree.m_nodes.size() == 3); - REQUIRE(anim_graph_blend_tree.m_nodes[0]->m_node_type_name == "BlendTreeSockets"); - REQUIRE(anim_graph_blend_tree.m_nodes[1]->m_node_type_name == "BlendTreeSockets"); + REQUIRE( + anim_graph_blend_tree.m_nodes[0]->m_node_type_name == "BlendTreeSockets"); + REQUIRE( + anim_graph_blend_tree.m_nodes[1]->m_node_type_name == "BlendTreeSockets"); REQUIRE(anim_graph_blend_tree.m_nodes[2]->m_node_type_name == "AnimSampler"); // connections within the graph @@ -107,11 +348,15 @@ TEST_CASE("AnimSamplerGraph", "[AnimGraphResource]") { dynamic_cast(anim_graph_blend_tree.m_nodes[0]); // check node input dependencies - size_t anim_sampler_index = anim_graph_blend_tree.GetAnimNodeIndex(anim_sampler_walk); + size_t anim_sampler_index = + anim_graph_blend_tree.GetAnimNodeIndex(anim_sampler_walk); - REQUIRE(anim_graph_blend_tree.m_node_output_connections[anim_sampler_index].size() == 1); + REQUIRE( + anim_graph_blend_tree.m_node_output_connections[anim_sampler_index].size() + == 1); CHECK( - anim_graph_blend_tree.m_node_output_connections[anim_sampler_index][0].m_target_node + anim_graph_blend_tree.m_node_output_connections[anim_sampler_index][0] + .m_target_node == graph_output_node); // Ensure animation sampler nodes use the correct files @@ -166,9 +411,12 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { speed_scale_value); AnimNodeResource* graph_node = blend_tree_resource.GetGraphOutputNode(); - graph_node->m_socket_accessor->RegisterInput("GraphOutput", nullptr); + graph_node->m_socket_accessor->RegisterInput( + "GraphOutput", + nullptr); - blend_tree_resource.ConnectSockets(walk_node, "Output", speed_scale_node, "Input"); + blend_tree_resource + .ConnectSockets(walk_node, "Output", speed_scale_node, "Input"); blend_tree_resource.ConnectSockets( speed_scale_node, @@ -176,15 +424,18 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { blend_tree_resource.GetGraphOutputNode(), "GraphOutput"); - graph_resource.SaveToFile("TestGraphAnimSamplerSpeedScaleGraph.animgraph.json"); + graph_resource.SaveToFile( + "TestGraphAnimSamplerSpeedScaleGraph.animgraph.json"); AnimGraphResource graph_resource_loaded; graph_resource_loaded.LoadFromFile( "TestGraphAnimSamplerSpeedScaleGraph.animgraph.json"); - BlendTreeResource& blend_tree_resource_loaded = graph_resource_loaded.m_blend_tree_resource; + BlendTreeResource& blend_tree_resource_loaded = + graph_resource_loaded.m_blend_tree_resource; Socket* speed_scale_resource_loaded_input = - blend_tree_resource_loaded.m_nodes[speed_scale_node_index]->m_socket_accessor->GetInputSocket("SpeedScale"); + blend_tree_resource_loaded.m_nodes[speed_scale_node_index] + ->m_socket_accessor->GetInputSocket("SpeedScale"); REQUIRE(speed_scale_resource_loaded_input != nullptr); REQUIRE_THAT( @@ -194,64 +445,80 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { AnimGraphBlendTree blend_tree; graph_resource_loaded.CreateBlendTreeInstance(blend_tree); - REQUIRE_THAT(*dynamic_cast(blend_tree.m_nodes[speed_scale_node_index])->i_speed_scale, - Catch::Matchers::WithinAbs(speed_scale_value, 0.1)); + REQUIRE_THAT( + *dynamic_cast(blend_tree.m_nodes[speed_scale_node_index]) + ->i_speed_scale, + Catch::Matchers::WithinAbs(speed_scale_value, 0.1)); } -TEST_CASE("Blend2Graph", "[AnimGraphResource]") { - AnimGraphResource graph_resource; - graph_resource.m_name = "WalkRunBlendGraph"; - graph_resource.m_graph_type_name = "BlendTree"; - - BlendTreeResource& blend_tree_resource = graph_resource.m_blend_tree_resource; - blend_tree_resource.Reset(); - 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; - - blend_tree_resource.m_nodes.push_back(AnimNodeResourceFactory("AnimSampler")); - size_t run_node_index = blend_tree_resource.m_nodes.size() - 1; - - blend_tree_resource.m_nodes.push_back(AnimNodeResourceFactory("Blend2")); - size_t blend_node_index = blend_tree_resource.m_nodes.size() - 1; - - AnimNodeResource* walk_node = blend_tree_resource.m_nodes[walk_node_index]; - walk_node->m_name = "WalkAnim"; - walk_node->m_socket_accessor->SetPropertyValue( - "Filename", - std::string("media/Walking-loop.ozz")); - AnimNodeResource* run_node = blend_tree_resource.m_nodes[run_node_index]; - run_node->m_socket_accessor->SetPropertyValue( - "Filename", - std::string("media/Running0-loop.ozz")); - run_node->m_name = "RunAnim"; - AnimNodeResource* blend_node = blend_tree_resource.m_nodes[blend_node_index]; - blend_node->m_name = "BlendWalkRun"; - - AnimNodeResource* graph_node = blend_tree_resource.GetGraphOutputNode(); - graph_node->m_socket_accessor->RegisterInput("GraphOutput", nullptr); - - REQUIRE(graph_node->m_socket_accessor->m_inputs.size() == 1); - REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input0") == 0); - REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input1") == 1); - - blend_tree_resource.ConnectSockets(walk_node, "Output", blend_node, "Input0"); - blend_tree_resource.ConnectSockets(run_node, "Output", blend_node, "Input1"); - blend_tree_resource.ConnectSockets( - blend_node, - "Output", - blend_tree_resource.GetGraphOutputNode(), - "GraphOutput"); - +TEST_CASE_METHOD( + Blend2GraphResource, + "Blend2GraphResource saving and loading results in same resource", + "[Blend2GraphResource]") { graph_resource.SaveToFile("TestGraphBlend2Graph.animgraph.json"); 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); + + 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] + ->m_socket_accessor); + + REQUIRE_THAT( + blend_node->m_socket_accessor->GetInputValue("Weight"), + Catch::Matchers::WithinAbs( + blend2_node_descriptor_loaded->GetInputValue("Weight"), + 0.01)); +} + +TEST_CASE_METHOD( + Blend2GraphResource, + "Blend2GraphResource graph unsynced evaluation", + "[Blend2GraphResource]") { AnimGraphBlendTree blend_tree_graph; - graph_resource_loaded.CreateBlendTreeInstance(blend_tree_graph); + graph_resource.CreateBlendTreeInstance(blend_tree_graph); AnimGraphContext graph_context; ozz::animation::Skeleton skeleton; @@ -272,11 +539,14 @@ TEST_CASE("Blend2Graph", "[AnimGraphResource]") { dynamic_cast(blend_tree_graph.m_nodes[2]); AnimSamplerNode* anim_sampler_run = dynamic_cast(blend_tree_graph.m_nodes[3]); - Blend2Node* blend2_instance = dynamic_cast(blend_tree_graph.m_nodes[4]); + Blend2Node* blend2_instance = + dynamic_cast(blend_tree_graph.m_nodes[4]); // check node input dependencies - size_t anim_sampler_index0 = blend_tree_graph.GetAnimNodeIndex(anim_sampler_walk); - size_t anim_sampler_index1 = blend_tree_graph.GetAnimNodeIndex(anim_sampler_run); + size_t anim_sampler_index0 = + blend_tree_graph.GetAnimNodeIndex(anim_sampler_walk); + size_t anim_sampler_index1 = + blend_tree_graph.GetAnimNodeIndex(anim_sampler_run); size_t blend_index = blend_tree_graph.GetAnimNodeIndex(blend2_instance); REQUIRE(blend_tree_graph.m_node_input_connections[blend_index].size() == 2); @@ -288,15 +558,19 @@ TEST_CASE("Blend2Graph", "[AnimGraphResource]") { == anim_sampler_run); REQUIRE( - blend_tree_graph.m_node_output_connections[anim_sampler_index0].size() == 1); + blend_tree_graph.m_node_output_connections[anim_sampler_index0].size() + == 1); CHECK( - blend_tree_graph.m_node_output_connections[anim_sampler_index0][0].m_target_node + blend_tree_graph.m_node_output_connections[anim_sampler_index0][0] + .m_target_node == blend2_instance); REQUIRE( - blend_tree_graph.m_node_output_connections[anim_sampler_index1].size() == 1); + blend_tree_graph.m_node_output_connections[anim_sampler_index1].size() + == 1); CHECK( - blend_tree_graph.m_node_output_connections[anim_sampler_index1][0].m_target_node + blend_tree_graph.m_node_output_connections[anim_sampler_index1][0] + .m_target_node == blend2_instance); // Ensure animation sampler nodes use the correct files @@ -349,12 +623,14 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { graph_resource_origin.m_name = "TestInputOutputGraph"; graph_resource_origin.m_graph_type_name = "BlendTree"; - BlendTreeResource& blend_tree_resource = graph_resource_origin.m_blend_tree_resource; + BlendTreeResource& blend_tree_resource = + graph_resource_origin.m_blend_tree_resource; blend_tree_resource.Reset(); blend_tree_resource.InitGraphConnectors(); // Prepare graph inputs and outputs - blend_tree_resource.m_nodes.push_back(AnimNodeResourceFactory("MathFloatToVec3Node")); + blend_tree_resource.m_nodes.push_back( + AnimNodeResourceFactory("MathFloatToVec3Node")); size_t float_to_vec3_node_index = blend_tree_resource.m_nodes.size() - 1; AnimNodeResource* graph_output_node = @@ -366,8 +642,7 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { "GraphVec3Output", nullptr); - AnimNodeResource* graph_input_node = - blend_tree_resource.GetGraphInputNode(); + AnimNodeResource* graph_input_node = blend_tree_resource.GetGraphInputNode(); graph_input_node->m_socket_accessor->RegisterOutput( "GraphFloatInput", nullptr); @@ -411,7 +686,8 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { AnimGraphResource graph_resource_loaded; graph_resource_loaded.LoadFromFile(filename); - BlendTreeResource& graph_blend_tree_loaded = graph_resource_loaded.m_blend_tree_resource; + BlendTreeResource& graph_blend_tree_loaded = + graph_resource_loaded.m_blend_tree_resource; const AnimNodeResource* graph_loaded_output_node = graph_blend_tree_loaded.m_nodes[0]; @@ -461,7 +737,8 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { // GraphFloatOutput is directly connected to GraphFloatInput therefore // we need to get the pointer here. - float* graph_float_ptr = blend_tree_node.GetOutputPtr("GraphFloatOutput"); + float* graph_float_ptr = + blend_tree_node.GetOutputPtr("GraphFloatOutput"); Vec3 graph_vec3_output; blend_tree_node.SetOutput("GraphVec3Output", &graph_vec3_output); @@ -482,13 +759,13 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { } } - TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { AnimGraphResource graph_resource_origin; graph_resource_origin.m_name = "TestSimpleMathGraph"; graph_resource_origin.m_graph_type_name = "BlendTree"; - BlendTreeResource& blend_tree_resource = graph_resource_origin.m_blend_tree_resource; + BlendTreeResource& blend_tree_resource = + graph_resource_origin.m_blend_tree_resource; blend_tree_resource.Reset(); blend_tree_resource.InitGraphConnectors(); @@ -512,8 +789,7 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { "GraphFloat2Output", nullptr); - AnimNodeResource* graph_input_node = - blend_tree_resource.GetGraphInputNode(); + AnimNodeResource* graph_input_node = blend_tree_resource.GetGraphInputNode(); graph_input_node->m_socket_accessor->RegisterOutput( "GraphFloatInput", nullptr); @@ -594,7 +870,8 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { // float0 output is directly connected to the graph input, therefore // we have to get a ptr to the input data here. - float* float0_output_ptr = blend_tree.GetOutputPtr("GraphFloat0Output"); + float* float0_output_ptr = + blend_tree.GetOutputPtr("GraphFloat0Output"); float float1_output = -1.f; float float2_output = -1.f; @@ -618,7 +895,6 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { } } - // // Tests whether BlendTree within a BlendTree can be saved and loaded // @@ -631,139 +907,118 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { // | | // +----------------------------------------+ // -TEST_CASE("EmbeddedBlendTreeSaveLoad", "[AnimGraphResource]") { - const char* parent_graph_filename = "TestGraphEmbeddedBlendTree.json"; - AnimGraphResource parent_graph_resource; - parent_graph_resource.m_name = "ParentBlendTree"; - parent_graph_resource.m_graph_type_name = "BlendTree"; - parent_graph_resource.m_node_type_name = "BlendTree"; +TEST_CASE_METHOD( + EmbeddedBlendTreeGraphResource, + "EmbeddedBlendTreeGraphResource saving and loading results in same " + "resource", + "[EmbeddedBlendTreeGraphResource]") { + parent_graph_resource.SaveToFile("TestGraphEmbeddedBlendTree.json"); - BlendTreeResource& parent_blend_tree_resource = - parent_graph_resource.m_blend_tree_resource; - parent_blend_tree_resource.Reset(); - parent_blend_tree_resource.InitGraphConnectors(); - - // Setup parent outputs - AnimNodeResource* parent_blend_tree_outputs = parent_blend_tree_resource.GetGraphOutputNode(); - parent_blend_tree_outputs->m_socket_accessor->RegisterInput("Output", nullptr); - - // Parent AnimSampler - parent_blend_tree_resource.m_nodes.push_back( - AnimNodeResourceFactory("AnimSampler")); - - AnimNodeResource* walk_node = - parent_blend_tree_resource.m_nodes.back(); - walk_node->m_name = "WalkAnim"; - walk_node->m_socket_accessor->SetPropertyValue( - "Filename", - std::string("media/Walking-loop.ozz")); - - // - // Embedded Tree - // - parent_blend_tree_resource.m_nodes.push_back( - AnimNodeResourceFactory("BlendTree")); - size_t embedded_blend_tree_node_index = - parent_blend_tree_resource.m_nodes.size() - 1; - AnimGraphResource* embedded_graph = - dynamic_cast(parent_blend_tree_resource.m_nodes.back()); - embedded_graph->m_name = "EmbeddedBlendTree"; - embedded_graph->m_node_type_name = "BlendTree"; - BlendTreeResource* embedded_blend_tree_resource = &embedded_graph->m_blend_tree_resource; - - // Embedded: outputs - AnimNodeResource* embedded_outputs = - embedded_blend_tree_resource->GetGraphOutputNode(); - embedded_outputs->m_socket_accessor->RegisterInput( - "AnimOutput", - nullptr); - - // Embedded: inputs - AnimNodeResource* embedded_inputs = - embedded_blend_tree_resource->GetGraphInputNode(); - embedded_inputs->m_socket_accessor->RegisterOutput( - "AnimInput", - nullptr); - - // Embedded: SpeedScale node - embedded_blend_tree_resource->m_nodes.push_back( - AnimNodeResourceFactory("SpeedScale")); - AnimNodeResource* embedded_speed_scale_resource = embedded_blend_tree_resource->m_nodes.back(); - - embedded_blend_tree_resource->ConnectSockets(embedded_inputs, "AnimInput", embedded_speed_scale_resource, "Input"); - embedded_blend_tree_resource->ConnectSockets(embedded_speed_scale_resource, "Output", embedded_outputs, "AnimOutput"); - - // - // Parent: setup connections - // - REQUIRE(parent_blend_tree_resource.ConnectSockets(walk_node, "Output", embedded_graph, "AnimInput")); - REQUIRE(parent_blend_tree_resource.ConnectSockets(embedded_graph, "AnimOutput", parent_blend_tree_outputs, "Output")); - - parent_graph_resource.SaveToFile(parent_graph_filename); - - // - // Load the graph - // AnimGraphResource parent_graph_resource_loaded; - parent_graph_resource_loaded.LoadFromFile(parent_graph_filename); + 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 + 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); - - 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]; - + + 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_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( + 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 == "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; - - 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()); - + REQUIRE( + parent_blend_tree_resource_loaded.m_nodes[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; + + 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]; - + 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( + 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); + + 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); } } \ No newline at end of file