BlendTreeFloatConditionNodeTests.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <EMotionFX/Source/AnimGraph.h>
  9. #include <EMotionFX/Source/AnimGraphBindPoseNode.h>
  10. #include <EMotionFX/Source/AnimGraphNode.h>
  11. #include <EMotionFX/Source/AnimGraphStateMachine.h>
  12. #include <EMotionFX/Source/BlendTree.h>
  13. #include <EMotionFX/Source/BlendTreeBlend2Node.h>
  14. #include <EMotionFX/Source/BlendTreeFloatConditionNode.h>
  15. #include <EMotionFX/Source/BlendTreeFloatConstantNode.h>
  16. #include <EMotionFX/Source/EMotionFXManager.h>
  17. #include <limits.h>
  18. #include <Tests/AnimGraphFixture.h>
  19. namespace EMotionFX
  20. {
  21. struct BlendTreeFloatConditionNodeTestData
  22. {
  23. float m_xInputFloat;
  24. float m_yInputFloat;
  25. bool m_expectedOutputForOneInputX[6];
  26. bool m_expectedOutputForOneInputY[6];
  27. bool m_expectedOutputForTwoInput[6];
  28. };
  29. class BlendTreeFloatConditionNodeFixture
  30. : public AnimGraphFixture
  31. , public ::testing::WithParamInterface<testing::tuple<bool, BlendTreeFloatConditionNodeTestData>>
  32. {
  33. public:
  34. void ConstructGraph() override
  35. {
  36. m_useBoolOutput = testing::get<0>(GetParam());
  37. m_param = testing::get<1>(GetParam());
  38. AnimGraphFixture::ConstructGraph();
  39. m_blendTreeAnimGraph = AnimGraphFactory::Create<OneBlendTreeNodeAnimGraph>();
  40. m_rootStateMachine = m_blendTreeAnimGraph->GetRootStateMachine();
  41. m_blendTree = m_blendTreeAnimGraph->GetBlendTreeNode();
  42. // Add nodes to blend tree.
  43. BlendTreeFinalNode* finalNode = aznew BlendTreeFinalNode();
  44. m_blendTree->AddChildNode(finalNode);
  45. BlendTreeBlend2Node* blend2Node = aznew BlendTreeBlend2Node();
  46. m_blendTree->AddChildNode(blend2Node);
  47. m_floatConditionNode = aznew BlendTreeFloatConditionNode();
  48. m_floatConditionNode->SetDefaultValue(0.0f);
  49. m_floatConditionNode->SetTrueResult(1.0f);
  50. m_floatConditionNode->SetFalseResult(0.0f);
  51. m_blendTree->AddChildNode(m_floatConditionNode);
  52. m_floatConstantNodeOne = aznew BlendTreeFloatConstantNode();
  53. m_blendTree->AddChildNode(m_floatConstantNodeOne);
  54. m_floatConstantNodeOne->SetValue(m_param.m_xInputFloat);
  55. m_floatConstantNodeTwo = aznew BlendTreeFloatConstantNode();
  56. m_blendTree->AddChildNode(m_floatConstantNodeTwo);
  57. m_floatConstantNodeTwo->SetValue(m_param.m_yInputFloat);
  58. AnimGraphBindPoseNode* bindPoseNode = aznew AnimGraphBindPoseNode();
  59. m_blendTree->AddChildNode(bindPoseNode);
  60. // Connect the nodes.
  61. blend2Node->AddConnection(bindPoseNode, AnimGraphBindPoseNode::PORTID_OUTPUT_POSE, BlendTreeBlend2Node::INPUTPORT_POSE_A);
  62. blend2Node->AddConnection(bindPoseNode, AnimGraphBindPoseNode::PORTID_OUTPUT_POSE, BlendTreeBlend2Node::INPUTPORT_POSE_B);
  63. blend2Node->AddConnection(m_floatConditionNode,
  64. m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE,
  65. BlendTreeBlend2Node::INPUTPORT_WEIGHT);
  66. finalNode->AddConnection(blend2Node, BlendTreeBlend2Node::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE);
  67. m_blendTreeAnimGraph->InitAfterLoading();
  68. }
  69. void SetUp() override
  70. {
  71. AnimGraphFixture::SetUp();
  72. m_animGraphInstance->Destroy();
  73. m_animGraphInstance = m_blendTreeAnimGraph->GetAnimGraphInstance(m_actorInstance, m_motionSet);
  74. }
  75. protected:
  76. BlendTree* m_blendTree = nullptr;
  77. BlendTreeFloatConstantNode* m_floatConstantNodeOne = nullptr;
  78. BlendTreeFloatConstantNode* m_floatConstantNodeTwo = nullptr;
  79. BlendTreeFloatConditionNode* m_floatConditionNode = nullptr;
  80. BlendTreeFloatConditionNodeTestData m_param;
  81. bool m_useBoolOutput;
  82. const std::vector <BlendTreeFloatConditionNode::EFunction> m_eFuncs
  83. {
  84. BlendTreeFloatConditionNode::FUNCTION_EQUAL,
  85. BlendTreeFloatConditionNode::FUNCTION_NOTEQUAL,
  86. BlendTreeFloatConditionNode::FUNCTION_GREATER,
  87. BlendTreeFloatConditionNode::FUNCTION_LESS,
  88. BlendTreeFloatConditionNode::FUNCTION_GREATEROREQUAL,
  89. BlendTreeFloatConditionNode::FUNCTION_LESSOREQUAL
  90. };
  91. };
  92. std::vector<BlendTreeFloatConditionNodeTestData> blendTreeConditionNodeConditionTestData
  93. {
  94. /*
  95. * {
  96. * X input node value,
  97. * Y input node value,
  98. * {expected outputs with respect to eFuncs for only x input},
  99. * {expected outputs with respect to eFuncs for only y input},
  100. * {expected outputs with respect to eFuncs for two inputs}
  101. * }
  102. */
  103. {
  104. 1.0f,
  105. 5.0f,
  106. {false, true, true, false, true, false},
  107. {false, true, false, true, false, true},
  108. {false, true, false, true, false, true}
  109. },
  110. {
  111. 1.0f,
  112. 1.0f,
  113. {false, true, true, false, true, false},
  114. {false, true, false, true, false, true},
  115. {true, false, false, false, true, true}
  116. },
  117. {
  118. 1.0f,
  119. -1.0f,
  120. {false, true, true, false, true, false},
  121. {false, true, true, false, true, false},
  122. {false, true, true, false, true, false}
  123. }
  124. };
  125. TEST_P(BlendTreeFloatConditionNodeFixture, BlendTreeFloatConditionNode_NoInputNodeConditionTest)
  126. {
  127. // Node output correct value/bool under different condition functions without any input node connection
  128. for (AZ::u32 i = 0; i < 6; ++i)
  129. {
  130. m_floatConditionNode->SetFunction(m_eFuncs[i]);
  131. GetEMotionFX().Update(1.0f / 60.0f);
  132. // Default output for no input is false
  133. EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
  134. m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
  135. GetValue(), 0.0f) << "(No input) Expected output: false";
  136. }
  137. };
  138. TEST_P(BlendTreeFloatConditionNodeFixture, BlendTreeFloatConditionNode_OneInputNodeConditionTest)
  139. {
  140. // Node output correct value/bool under different condition functions with one input node connection
  141. BlendTreeConnection* xInputPortConnection = m_floatConditionNode->
  142. AddConnection(m_floatConstantNodeOne, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_X);
  143. // Test with only X input node
  144. for (AZ::u32 i = 0; i < 6; ++i)
  145. {
  146. m_floatConditionNode->SetFunction(m_eFuncs[i]);
  147. GetEMotionFX().Update(1.0f / 60.0f);
  148. EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
  149. m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
  150. GetValue(), m_param.m_expectedOutputForOneInputX[i] ? 1.0f : 0.0f)
  151. << "(With only X input) expected ouput: " << m_param.m_expectedOutputForOneInputX[i];
  152. }
  153. m_floatConditionNode->RemoveConnection(xInputPortConnection);
  154. BlendTreeConnection* yInputPortConnection = m_floatConditionNode->
  155. AddConnection(m_floatConstantNodeTwo, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_Y);
  156. // Test with only Y input node
  157. for (AZ::u32 i = 0; i < 6; ++i)
  158. {
  159. m_floatConditionNode->SetFunction(m_eFuncs[i]);
  160. GetEMotionFX().Update(1.0f / 60.0f);
  161. EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
  162. m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
  163. GetValue(), m_param.m_expectedOutputForOneInputY[i] ? 1.0f : 0.0f)
  164. << "(With only Y input) expected ouput: " << m_param.m_expectedOutputForOneInputY[i];
  165. }
  166. m_floatConditionNode->RemoveConnection(yInputPortConnection);
  167. };
  168. TEST_P(BlendTreeFloatConditionNodeFixture, BlendTreeFloatConditionNode_TwoInputNodeConditionTest)
  169. {
  170. // Node output correct value/bool under different condition functions with two input node connection
  171. m_floatConditionNode->AddConnection(m_floatConstantNodeOne, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_X);
  172. m_floatConditionNode->AddConnection(m_floatConstantNodeTwo, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_Y);
  173. for (AZ::u32 i = 0; i < 6; ++i)
  174. {
  175. m_floatConditionNode->SetFunction(m_eFuncs[i]);
  176. GetEMotionFX().Update(1.0f / 60.0f);
  177. EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
  178. m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
  179. GetValue(), m_param.m_expectedOutputForTwoInput[i] ? 1.0f : 0.0f)
  180. << "(With X and Y input) expected ouput: " << m_param.m_expectedOutputForTwoInput[i];
  181. }
  182. };
  183. INSTANTIATE_TEST_CASE_P(BlendTreeFloatConditionNode_ConditionTest,
  184. BlendTreeFloatConditionNodeFixture,
  185. ::testing::Combine(
  186. ::testing::Bool(),
  187. ::testing::ValuesIn(blendTreeConditionNodeConditionTestData)
  188. )
  189. );
  190. } // end namespace EMotionFX