|  |  | @ -12,6 +12,225 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "ozz/base/io/stream.h" |  |  |  | #include "ozz/base/io/stream.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "ozz/base/log.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<AnimData>( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         "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<AnimData>( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         "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<AnimData>( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         "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<AnimGraphResource*>( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         parent_blend_tree_resource->m_nodes.back()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     embedded_graph->m_name = "EmbeddedBlendTree"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     embedded_graph->m_node_type_name = "BlendTree"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     embedded_graph->m_graph_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<AnimData>( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         "AnimOutput", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         nullptr); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // Embedded: inputs
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     AnimNodeResource* embedded_inputs = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         embedded_blend_tree_resource->GetGraphInputNode(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     embedded_inputs->m_socket_accessor->RegisterOutput<AnimData>( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         "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_speed_scale_resource->m_socket_accessor->SetInputValue("SpeedScale", 0.1f); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // 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) { |  |  |  | bool load_skeleton(ozz::animation::Skeleton& skeleton, const char* filename) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   assert(filename); |  |  |  |   assert(filename); | 
			
		
	
		
		
			
				
					
					|  |  |  |   ozz::io::File file(filename, "rb"); |  |  |  |   ozz::io::File file(filename, "rb"); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -52,40 +271,62 @@ TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   CHECK(output_index == parsed_output_index); |  |  |  |   CHECK(output_index == parsed_output_index); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | TEST_CASE("AnimSamplerGraph", "[AnimGraphResource]") { |  |  |  | TEST_CASE_METHOD( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphResource graph_resource; |  |  |  |     SimpleAnimSamplerGraphResource, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource.m_name = "AnimSamplerBlendTree"; |  |  |  |     "SimpleAnimSamplerGraphResource saving and loading results in same " | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource.m_graph_type_name = "BlendTree"; |  |  |  |     "resource", | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |     "[SimpleAnimSamplerGraphResource]") { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   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<AnimData>("GraphOutput", nullptr); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   blend_tree_resource.ConnectSockets( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       walk_node, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       "Output", |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       blend_tree_resource.GetGraphOutputNode(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       "GraphOutput"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   graph_resource.SaveToFile("TestGraphAnimSamplerBlendTree.json"); |  |  |  |   graph_resource.SaveToFile("TestGraphAnimSamplerBlendTree.json"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphResource graph_resource_loaded; |  |  |  |   AnimGraphResource graph_resource_loaded; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_loaded.LoadFromFile("TestGraphAnimSamplerBlendTree.json"); |  |  |  |   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; |  |  |  |   AnimGraphBlendTree anim_graph_blend_tree; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_loaded.CreateBlendTreeInstance(anim_graph_blend_tree); |  |  |  |   graph_resource.CreateBlendTreeInstance(anim_graph_blend_tree); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphContext graph_context; |  |  |  |   AnimGraphContext graph_context; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   ozz::animation::Skeleton skeleton; |  |  |  |   ozz::animation::Skeleton skeleton; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -95,8 +336,10 @@ TEST_CASE("AnimSamplerGraph", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE(anim_graph_blend_tree.Init(graph_context)); |  |  |  |   REQUIRE(anim_graph_blend_tree.Init(graph_context)); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE(anim_graph_blend_tree.m_nodes.size() == 3); |  |  |  |   REQUIRE(anim_graph_blend_tree.m_nodes.size() == 3); | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE(anim_graph_blend_tree.m_nodes[0]->m_node_type_name == "BlendTreeSockets"); |  |  |  |   REQUIRE( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE(anim_graph_blend_tree.m_nodes[1]->m_node_type_name == "BlendTreeSockets"); |  |  |  |       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"); |  |  |  |   REQUIRE(anim_graph_blend_tree.m_nodes[2]->m_node_type_name == "AnimSampler"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // connections within the graph
 |  |  |  |   // connections within the graph
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -107,11 +350,15 @@ TEST_CASE("AnimSamplerGraph", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |       dynamic_cast<BlendTreeNode*>(anim_graph_blend_tree.m_nodes[0]); |  |  |  |       dynamic_cast<BlendTreeNode*>(anim_graph_blend_tree.m_nodes[0]); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // check node input dependencies
 |  |  |  |   // 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( |  |  |  |   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); |  |  |  |       == graph_output_node); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Ensure animation sampler nodes use the correct files
 |  |  |  |   // Ensure animation sampler nodes use the correct files
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -166,9 +413,12 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |       speed_scale_value); |  |  |  |       speed_scale_value); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimNodeResource* graph_node = blend_tree_resource.GetGraphOutputNode(); |  |  |  |   AnimNodeResource* graph_node = blend_tree_resource.GetGraphOutputNode(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_node->m_socket_accessor->RegisterInput<AnimData>("GraphOutput", nullptr); |  |  |  |   graph_node->m_socket_accessor->RegisterInput<AnimData>( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       "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( |  |  |  |   blend_tree_resource.ConnectSockets( | 
			
		
	
		
		
			
				
					
					|  |  |  |       speed_scale_node, |  |  |  |       speed_scale_node, | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -176,15 +426,18 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |       blend_tree_resource.GetGraphOutputNode(), |  |  |  |       blend_tree_resource.GetGraphOutputNode(), | 
			
		
	
		
		
			
				
					
					|  |  |  |       "GraphOutput"); |  |  |  |       "GraphOutput"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource.SaveToFile("TestGraphAnimSamplerSpeedScaleGraph.animgraph.json"); |  |  |  |   graph_resource.SaveToFile( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       "TestGraphAnimSamplerSpeedScaleGraph.animgraph.json"); | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphResource graph_resource_loaded; |  |  |  |   AnimGraphResource graph_resource_loaded; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_loaded.LoadFromFile( |  |  |  |   graph_resource_loaded.LoadFromFile( | 
			
		
	
		
		
			
				
					
					|  |  |  |       "TestGraphAnimSamplerSpeedScaleGraph.animgraph.json"); |  |  |  |       "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 = |  |  |  |   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(speed_scale_resource_loaded_input != nullptr); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE_THAT( |  |  |  |   REQUIRE_THAT( | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -194,64 +447,80 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphBlendTree blend_tree; |  |  |  |   AnimGraphBlendTree blend_tree; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_loaded.CreateBlendTreeInstance(blend_tree); |  |  |  |   graph_resource_loaded.CreateBlendTreeInstance(blend_tree); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE_THAT(*dynamic_cast<SpeedScaleNode*>(blend_tree.m_nodes[speed_scale_node_index])->i_speed_scale, |  |  |  |   REQUIRE_THAT( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       *dynamic_cast<SpeedScaleNode*>(blend_tree.m_nodes[speed_scale_node_index]) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |            ->i_speed_scale, | 
			
		
	
		
		
			
				
					
					|  |  |  |       Catch::Matchers::WithinAbs(speed_scale_value, 0.1)); |  |  |  |       Catch::Matchers::WithinAbs(speed_scale_value, 0.1)); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | TEST_CASE("Blend2Graph", "[AnimGraphResource]") { |  |  |  | TEST_CASE_METHOD( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphResource graph_resource; |  |  |  |     Blend2GraphResource, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource.m_name = "WalkRunBlendGraph"; |  |  |  |     "Blend2GraphResource saving and loading results in same resource", | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource.m_graph_type_name = "BlendTree"; |  |  |  |     "[Blend2GraphResource]") { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   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<AnimData>("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"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   graph_resource.SaveToFile("TestGraphBlend2Graph.animgraph.json"); |  |  |  |   graph_resource.SaveToFile("TestGraphBlend2Graph.animgraph.json"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphResource graph_resource_loaded; |  |  |  |   AnimGraphResource graph_resource_loaded; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_loaded.LoadFromFile("TestGraphBlend2Graph.animgraph.json"); |  |  |  |   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<Blend2Node>* blend2_node_descriptor_loaded = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       dynamic_cast<NodeDescriptor<Blend2Node>*>( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           blend_tree_resource_loaded->m_nodes[blend_node_index] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               ->m_socket_accessor); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   REQUIRE_THAT( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       blend_node->m_socket_accessor->GetInputValue<float>("Weight"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       Catch::Matchers::WithinAbs( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           blend2_node_descriptor_loaded->GetInputValue<float>("Weight"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           0.01)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | TEST_CASE_METHOD( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     Blend2GraphResource, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     "Blend2GraphResource graph unsynced evaluation", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     "[Blend2GraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphBlendTree blend_tree_graph; |  |  |  |   AnimGraphBlendTree blend_tree_graph; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_loaded.CreateBlendTreeInstance(blend_tree_graph); |  |  |  |   graph_resource.CreateBlendTreeInstance(blend_tree_graph); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphContext graph_context; |  |  |  |   AnimGraphContext graph_context; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   ozz::animation::Skeleton skeleton; |  |  |  |   ozz::animation::Skeleton skeleton; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -272,11 +541,14 @@ TEST_CASE("Blend2Graph", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |       dynamic_cast<AnimSamplerNode*>(blend_tree_graph.m_nodes[2]); |  |  |  |       dynamic_cast<AnimSamplerNode*>(blend_tree_graph.m_nodes[2]); | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimSamplerNode* anim_sampler_run = |  |  |  |   AnimSamplerNode* anim_sampler_run = | 
			
		
	
		
		
			
				
					
					|  |  |  |       dynamic_cast<AnimSamplerNode*>(blend_tree_graph.m_nodes[3]); |  |  |  |       dynamic_cast<AnimSamplerNode*>(blend_tree_graph.m_nodes[3]); | 
			
		
	
		
		
			
				
					
					|  |  |  |   Blend2Node* blend2_instance = dynamic_cast<Blend2Node*>(blend_tree_graph.m_nodes[4]); |  |  |  |   Blend2Node* blend2_instance = | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       dynamic_cast<Blend2Node*>(blend_tree_graph.m_nodes[4]); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // check node input dependencies
 |  |  |  |   // check node input dependencies
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   size_t anim_sampler_index0 = blend_tree_graph.GetAnimNodeIndex(anim_sampler_walk); |  |  |  |   size_t anim_sampler_index0 = | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   size_t anim_sampler_index1 = blend_tree_graph.GetAnimNodeIndex(anim_sampler_run); |  |  |  |       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); |  |  |  |   size_t blend_index = blend_tree_graph.GetAnimNodeIndex(blend2_instance); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE(blend_tree_graph.m_node_input_connections[blend_index].size() == 2); |  |  |  |   REQUIRE(blend_tree_graph.m_node_input_connections[blend_index].size() == 2); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -288,15 +560,19 @@ TEST_CASE("Blend2Graph", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |       == anim_sampler_run); |  |  |  |       == anim_sampler_run); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE( |  |  |  |   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( |  |  |  |   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); |  |  |  |       == blend2_instance); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE( |  |  |  |   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( |  |  |  |   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); |  |  |  |       == blend2_instance); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Ensure animation sampler nodes use the correct files
 |  |  |  |   // Ensure animation sampler nodes use the correct files
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -349,12 +625,14 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_origin.m_name = "TestInputOutputGraph"; |  |  |  |   graph_resource_origin.m_name = "TestInputOutputGraph"; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_origin.m_graph_type_name = "BlendTree"; |  |  |  |   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.Reset(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   blend_tree_resource.InitGraphConnectors(); |  |  |  |   blend_tree_resource.InitGraphConnectors(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Prepare graph inputs and outputs
 |  |  |  |   // 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; |  |  |  |   size_t float_to_vec3_node_index = blend_tree_resource.m_nodes.size() - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimNodeResource* graph_output_node = |  |  |  |   AnimNodeResource* graph_output_node = | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -366,8 +644,7 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |       "GraphVec3Output", |  |  |  |       "GraphVec3Output", | 
			
		
	
		
		
			
				
					
					|  |  |  |       nullptr); |  |  |  |       nullptr); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimNodeResource* graph_input_node = |  |  |  |   AnimNodeResource* graph_input_node = blend_tree_resource.GetGraphInputNode(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       blend_tree_resource.GetGraphInputNode(); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   graph_input_node->m_socket_accessor->RegisterOutput<float>( |  |  |  |   graph_input_node->m_socket_accessor->RegisterOutput<float>( | 
			
		
	
		
		
			
				
					
					|  |  |  |       "GraphFloatInput", |  |  |  |       "GraphFloatInput", | 
			
		
	
		
		
			
				
					
					|  |  |  |       nullptr); |  |  |  |       nullptr); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -411,7 +688,8 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |     AnimGraphResource graph_resource_loaded; |  |  |  |     AnimGraphResource graph_resource_loaded; | 
			
		
	
		
		
			
				
					
					|  |  |  |     graph_resource_loaded.LoadFromFile(filename); |  |  |  |     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 = |  |  |  |     const AnimNodeResource* graph_loaded_output_node = | 
			
		
	
		
		
			
				
					
					|  |  |  |         graph_blend_tree_loaded.m_nodes[0]; |  |  |  |         graph_blend_tree_loaded.m_nodes[0]; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -461,7 +739,8 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           // GraphFloatOutput is directly connected to GraphFloatInput therefore
 |  |  |  |           // GraphFloatOutput is directly connected to GraphFloatInput therefore
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           // we need to get the pointer here.
 |  |  |  |           // we need to get the pointer here.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           float* graph_float_ptr = blend_tree_node.GetOutputPtr<float>("GraphFloatOutput"); |  |  |  |           float* graph_float_ptr = | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               blend_tree_node.GetOutputPtr<float>("GraphFloatOutput"); | 
			
		
	
		
		
			
				
					
					|  |  |  |           Vec3 graph_vec3_output; |  |  |  |           Vec3 graph_vec3_output; | 
			
		
	
		
		
			
				
					
					|  |  |  |           blend_tree_node.SetOutput("GraphVec3Output", &graph_vec3_output); |  |  |  |           blend_tree_node.SetOutput("GraphVec3Output", &graph_vec3_output); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -482,13 +761,13 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { |  |  |  | TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphResource graph_resource_origin; |  |  |  |   AnimGraphResource graph_resource_origin; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_origin.m_name = "TestSimpleMathGraph"; |  |  |  |   graph_resource_origin.m_name = "TestSimpleMathGraph"; | 
			
		
	
		
		
			
				
					
					|  |  |  |   graph_resource_origin.m_graph_type_name = "BlendTree"; |  |  |  |   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.Reset(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   blend_tree_resource.InitGraphConnectors(); |  |  |  |   blend_tree_resource.InitGraphConnectors(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -512,8 +791,7 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |       "GraphFloat2Output", |  |  |  |       "GraphFloat2Output", | 
			
		
	
		
		
			
				
					
					|  |  |  |       nullptr); |  |  |  |       nullptr); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimNodeResource* graph_input_node = |  |  |  |   AnimNodeResource* graph_input_node = blend_tree_resource.GetGraphInputNode(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       blend_tree_resource.GetGraphInputNode(); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   graph_input_node->m_socket_accessor->RegisterOutput<float>( |  |  |  |   graph_input_node->m_socket_accessor->RegisterOutput<float>( | 
			
		
	
		
		
			
				
					
					|  |  |  |       "GraphFloatInput", |  |  |  |       "GraphFloatInput", | 
			
		
	
		
		
			
				
					
					|  |  |  |       nullptr); |  |  |  |       nullptr); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -594,7 +872,8 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // float0 output is directly connected to the graph input, therefore
 |  |  |  |         // float0 output is directly connected to the graph input, therefore
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // we have to get a ptr to the input data here.
 |  |  |  |         // we have to get a ptr to the input data here.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         float* float0_output_ptr = blend_tree.GetOutputPtr<float>("GraphFloat0Output"); |  |  |  |         float* float0_output_ptr = | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             blend_tree.GetOutputPtr<float>("GraphFloat0Output"); | 
			
		
	
		
		
			
				
					
					|  |  |  |         float float1_output = -1.f; |  |  |  |         float float1_output = -1.f; | 
			
		
	
		
		
			
				
					
					|  |  |  |         float float2_output = -1.f; |  |  |  |         float float2_output = -1.f; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -618,7 +897,6 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | //
 |  |  |  | //
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // Tests whether BlendTree within a BlendTree can be saved and loaded
 |  |  |  | // Tests whether BlendTree within a BlendTree can be saved and loaded
 | 
			
		
	
		
		
			
				
					
					|  |  |  | //
 |  |  |  | //
 | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -631,139 +909,152 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  | //   |                                        |
 |  |  |  | //   |                                        |
 | 
			
		
	
		
		
			
				
					
					|  |  |  | //   +----------------------------------------+
 |  |  |  | //   +----------------------------------------+
 | 
			
		
	
		
		
			
				
					
					|  |  |  | //
 |  |  |  | //
 | 
			
		
	
		
		
			
				
					
					|  |  |  | TEST_CASE("EmbeddedBlendTreeSaveLoad", "[AnimGraphResource]") { |  |  |  | TEST_CASE_METHOD( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   const char* parent_graph_filename = "TestGraphEmbeddedBlendTree.json"; |  |  |  |     EmbeddedBlendTreeGraphResource, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   AnimGraphResource parent_graph_resource; |  |  |  |     "EmbeddedBlendTreeGraphResource saving and loading results in same " | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   parent_graph_resource.m_name = "ParentBlendTree"; |  |  |  |     "resource", | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   parent_graph_resource.m_graph_type_name = "BlendTree"; |  |  |  |     "[EmbeddedBlendTreeGraphResource]") { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   parent_graph_resource.m_node_type_name = "BlendTree"; |  |  |  |   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<AnimData>("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<AnimGraphResource*>(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<AnimData>( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       "AnimOutput", |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       nullptr); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Embedded: inputs
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   AnimNodeResource* embedded_inputs = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       embedded_blend_tree_resource->GetGraphInputNode(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   embedded_inputs->m_socket_accessor->RegisterOutput<AnimData>( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       "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; |  |  |  |   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 the loaded parent graph
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   //
 |  |  |  |   //
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   CHECK(parent_graph_resource.m_name == parent_graph_resource_loaded.m_name); |  |  |  |   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( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   CHECK(parent_graph_resource.m_node_type_name |  |  |  |       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); |  |  |  |       == parent_graph_resource_loaded.m_node_type_name); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   const BlendTreeResource& parent_blend_tree_resource_loaded = parent_graph_resource_loaded.m_blend_tree_resource;  |  |  |  |   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()); |  |  |  |   CHECK( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   for (size_t i = 0; i < parent_blend_tree_resource.m_nodes.size(); i++) { |  |  |  |       parent_blend_tree_resource->m_nodes.size() | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     const AnimNodeResource* parent_node = parent_blend_tree_resource.m_nodes[i]; |  |  |  |       == parent_blend_tree_resource_loaded.m_nodes.size()); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     const AnimNodeResource* parent_node_loaded = parent_blend_tree_resource_loaded.m_nodes[i]; |  |  |  |   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_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()); |  |  |  |   CHECK( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   for (size_t i = 0; i < parent_blend_tree_resource.m_connections.size(); i++) { |  |  |  |       parent_blend_tree_resource->m_connections.size() | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     const BlendTreeConnectionResource& parent_connection = parent_blend_tree_resource.m_connections[i]; |  |  |  |       == parent_blend_tree_resource_loaded.m_connections.size()); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     const BlendTreeConnectionResource& parent_connection_loaded = parent_blend_tree_resource_loaded.m_connections[i]; |  |  |  |   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( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     CHECK(parent_connection.source_socket_name == parent_connection_loaded.source_socket_name); |  |  |  |         parent_connection.source_node_index | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     CHECK(parent_connection.target_node_index == parent_connection_loaded.target_node_index); |  |  |  |         == parent_connection_loaded.source_node_index); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     CHECK(parent_connection.target_socket_name == parent_connection_loaded.target_socket_name); |  |  |  |     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
 |  |  |  |   // Check the loaded embedded graph
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   //
 |  |  |  |   //
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   REQUIRE(parent_blend_tree_resource_loaded.m_nodes[3]->m_node_type_name == "BlendTree"); |  |  |  |   REQUIRE( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       parent_blend_tree_resource_loaded.m_nodes[3]->m_node_type_name | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       == "BlendTree"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   const AnimGraphResource* embedded_graph_loaded = dynamic_cast<AnimGraphResource*>(parent_blend_tree_resource_loaded.m_nodes[3]); |  |  |  |   const AnimGraphResource* embedded_graph_loaded = | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   const BlendTreeResource& embedded_blend_tree_resource_loaded = embedded_graph_loaded->m_blend_tree_resource; |  |  |  |       dynamic_cast<AnimGraphResource*>( | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           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( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   CHECK(embedded_blend_tree_resource->m_connections.size() == embedded_blend_tree_resource_loaded.m_connections.size()); |  |  |  |       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++) { |  |  |  |   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 = | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     const AnimNodeResource* parent_node_loaded = embedded_blend_tree_resource_loaded.m_nodes[i]; |  |  |  |         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_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()); |  |  |  |   CHECK( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   for (size_t i = 0; i < embedded_blend_tree_resource->m_connections.size(); i++) { |  |  |  |       embedded_blend_tree_resource->m_connections.size() | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     const BlendTreeConnectionResource& embedded_connection = embedded_blend_tree_resource->m_connections[i]; |  |  |  |       == embedded_blend_tree_resource_loaded.m_connections.size()); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     const BlendTreeConnectionResource& embedded_connection_loaded = embedded_blend_tree_resource_loaded.m_connections[i]; |  |  |  |   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( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     CHECK(embedded_connection.source_socket_name == embedded_connection_loaded.source_socket_name); |  |  |  |         embedded_connection.source_node_index | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     CHECK(embedded_connection.target_node_index == embedded_connection_loaded.target_node_index); |  |  |  |         == embedded_connection_loaded.source_node_index); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     CHECK(embedded_connection.target_socket_name == embedded_connection_loaded.target_socket_name); |  |  |  |     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); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | TEST_CASE_METHOD( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     EmbeddedBlendTreeGraphResource, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     "EmbeddedBlendTreeGraphResource instantiation", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     "[EmbeddedBlendTreeGraphResource]") { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   AnimGraphBlendTree blend_tree; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   parent_graph_resource.CreateBlendTreeInstance(blend_tree); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   AnimGraphContext graph_context; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ozz::animation::Skeleton skeleton; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   REQUIRE(load_skeleton(skeleton, "media/skeleton.ozz")); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   graph_context.m_skeleton = &skeleton; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   blend_tree.Init(graph_context); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // Marking of active inputs is not properly working as we do not properly
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // populate AnimNode::m_inputs.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   //
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // Here comes an iffy problem: How to mark nodes in a parent blend tree
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   //   as active?
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   //
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // - Simplest would be if the AnimNodes don't distinguish between nodes within
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   //   the tree they are contained or in a possible parent (or nested) tree.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // - But then how to propagate active connections across multiple layers?
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // - Therefore probably better to have a blend tree store which sockets are
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   //   active and use that within the graph.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // - But then: AnimGraphConnection already stores raw AnimNode pointers of the
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   //   connected nodes. Still... populating them accross layers could be messy.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   blend_tree.MarkActiveInputs(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   blend_tree.UpdateTime(0.f, 0.1f); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   blend_tree.Evaluate(graph_context); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   graph_context.freeAnimations(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } |