You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/EMotionFX/Code/Tests/BlendTreeFloatConditionNode...

208 lines
9.8 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <EMotionFX/Source/AnimGraph.h>
#include <EMotionFX/Source/AnimGraphBindPoseNode.h>
#include <EMotionFX/Source/AnimGraphNode.h>
#include <EMotionFX/Source/AnimGraphStateMachine.h>
#include <EMotionFX/Source/BlendTree.h>
#include <EMotionFX/Source/BlendTreeBlend2Node.h>
#include <EMotionFX/Source/BlendTreeFloatConditionNode.h>
#include <EMotionFX/Source/BlendTreeFloatConstantNode.h>
#include <EMotionFX/Source/EMotionFXManager.h>
#include <limits.h>
#include <Tests/AnimGraphFixture.h>
namespace EMotionFX
{
struct BlendTreeFloatConditionNodeTestData
{
float m_xInputFloat;
float m_yInputFloat;
bool m_expectedOutputForOneInputX[6];
bool m_expectedOutputForOneInputY[6];
bool m_expectedOutputForTwoInput[6];
};
class BlendTreeFloatConditionNodeFixture
: public AnimGraphFixture
, public ::testing::WithParamInterface<testing::tuple<bool, BlendTreeFloatConditionNodeTestData>>
{
public:
void ConstructGraph() override
{
m_useBoolOutput = testing::get<0>(GetParam());
m_param = testing::get<1>(GetParam());
AnimGraphFixture::ConstructGraph();
m_blendTreeAnimGraph = AnimGraphFactory::Create<OneBlendTreeNodeAnimGraph>();
m_rootStateMachine = m_blendTreeAnimGraph->GetRootStateMachine();
m_blendTree = m_blendTreeAnimGraph->GetBlendTreeNode();
// Add nodes to blend tree.
BlendTreeFinalNode* finalNode = aznew BlendTreeFinalNode();
m_blendTree->AddChildNode(finalNode);
BlendTreeBlend2Node* blend2Node = aznew BlendTreeBlend2Node();
m_blendTree->AddChildNode(blend2Node);
m_floatConditionNode = aznew BlendTreeFloatConditionNode();
m_floatConditionNode->SetDefaultValue(0.0f);
m_floatConditionNode->SetTrueResult(1.0f);
m_floatConditionNode->SetFalseResult(0.0f);
m_blendTree->AddChildNode(m_floatConditionNode);
m_floatConstantNodeOne = aznew BlendTreeFloatConstantNode();
m_blendTree->AddChildNode(m_floatConstantNodeOne);
m_floatConstantNodeOne->SetValue(m_param.m_xInputFloat);
m_floatConstantNodeTwo = aznew BlendTreeFloatConstantNode();
m_blendTree->AddChildNode(m_floatConstantNodeTwo);
m_floatConstantNodeTwo->SetValue(m_param.m_yInputFloat);
AnimGraphBindPoseNode* bindPoseNode = aznew AnimGraphBindPoseNode();
m_blendTree->AddChildNode(bindPoseNode);
// Connect the nodes.
blend2Node->AddConnection(bindPoseNode, AnimGraphBindPoseNode::PORTID_OUTPUT_POSE, BlendTreeBlend2Node::INPUTPORT_POSE_A);
blend2Node->AddConnection(bindPoseNode, AnimGraphBindPoseNode::PORTID_OUTPUT_POSE, BlendTreeBlend2Node::INPUTPORT_POSE_B);
blend2Node->AddConnection(m_floatConditionNode,
m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE,
BlendTreeBlend2Node::INPUTPORT_WEIGHT);
finalNode->AddConnection(blend2Node, BlendTreeBlend2Node::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE);
m_blendTreeAnimGraph->InitAfterLoading();
}
void SetUp() override
{
AnimGraphFixture::SetUp();
m_animGraphInstance->Destroy();
m_animGraphInstance = m_blendTreeAnimGraph->GetAnimGraphInstance(m_actorInstance, m_motionSet);
}
protected:
AZStd::unique_ptr<OneBlendTreeNodeAnimGraph> m_blendTreeAnimGraph;
BlendTree* m_blendTree = nullptr;
BlendTreeFloatConstantNode* m_floatConstantNodeOne = nullptr;
BlendTreeFloatConstantNode* m_floatConstantNodeTwo = nullptr;
BlendTreeFloatConditionNode* m_floatConditionNode = nullptr;
BlendTreeFloatConditionNodeTestData m_param;
bool m_useBoolOutput;
const std::vector <BlendTreeFloatConditionNode::EFunction> m_eFuncs
{
BlendTreeFloatConditionNode::FUNCTION_EQUAL,
BlendTreeFloatConditionNode::FUNCTION_NOTEQUAL,
BlendTreeFloatConditionNode::FUNCTION_GREATER,
BlendTreeFloatConditionNode::FUNCTION_LESS,
BlendTreeFloatConditionNode::FUNCTION_GREATEROREQUAL,
BlendTreeFloatConditionNode::FUNCTION_LESSOREQUAL
};
};
std::vector<BlendTreeFloatConditionNodeTestData> blendTreeConditionNodeConditionTestData
{
/*
* {
* X input node value,
* Y input node value,
* {expected outputs with respect to eFuncs for only x input},
* {expected outputs with respect to eFuncs for only y input},
* {expected outputs with respect to eFuncs for two inputs}
* }
*/
{
1.0f,
5.0f,
{false, true, true, false, true, false},
{false, true, false, true, false, true},
{false, true, false, true, false, true}
},
{
1.0f,
1.0f,
{false, true, true, false, true, false},
{false, true, false, true, false, true},
{true, false, false, false, true, true}
},
{
1.0f,
-1.0f,
{false, true, true, false, true, false},
{false, true, true, false, true, false},
{false, true, true, false, true, false}
}
};
TEST_P(BlendTreeFloatConditionNodeFixture, BlendTreeFloatConditionNode_NoInputNodeConditionTest)
{
// Node output correct value/bool under different condition functions without any input node connection
for (AZ::u32 i = 0; i < 6; ++i)
{
m_floatConditionNode->SetFunction(m_eFuncs[i]);
GetEMotionFX().Update(1.0f / 60.0f);
// Default output for no input is false
EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
GetValue(), 0.0f) << "(No input) Expected output: false";
}
};
TEST_P(BlendTreeFloatConditionNodeFixture, BlendTreeFloatConditionNode_OneInputNodeConditionTest)
{
// Node output correct value/bool under different condition functions with one input node connection
BlendTreeConnection* xInputPortConnection = m_floatConditionNode->
AddConnection(m_floatConstantNodeOne, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_X);
// Test with only X input node
for (AZ::u32 i = 0; i < 6; ++i)
{
m_floatConditionNode->SetFunction(m_eFuncs[i]);
GetEMotionFX().Update(1.0f / 60.0f);
EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
GetValue(), m_param.m_expectedOutputForOneInputX[i] ? 1.0f : 0.0f)
<< "(With only X input) expected ouput: " << m_param.m_expectedOutputForOneInputX[i];
}
m_floatConditionNode->RemoveConnection(xInputPortConnection);
BlendTreeConnection* yInputPortConnection = m_floatConditionNode->
AddConnection(m_floatConstantNodeTwo, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_Y);
// Test with only Y input node
for (AZ::u32 i = 0; i < 6; ++i)
{
m_floatConditionNode->SetFunction(m_eFuncs[i]);
GetEMotionFX().Update(1.0f / 60.0f);
EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
GetValue(), m_param.m_expectedOutputForOneInputY[i] ? 1.0f : 0.0f)
<< "(With only Y input) expected ouput: " << m_param.m_expectedOutputForOneInputY[i];
}
m_floatConditionNode->RemoveConnection(yInputPortConnection);
};
TEST_P(BlendTreeFloatConditionNodeFixture, BlendTreeFloatConditionNode_TwoInputNodeConditionTest)
{
// Node output correct value/bool under different condition functions with two input node connection
m_floatConditionNode->AddConnection(m_floatConstantNodeOne, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_X);
m_floatConditionNode->AddConnection(m_floatConstantNodeTwo, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeFloatConditionNode::PORTID_INPUT_Y);
for (AZ::u32 i = 0; i < 6; ++i)
{
m_floatConditionNode->SetFunction(m_eFuncs[i]);
GetEMotionFX().Update(1.0f / 60.0f);
EXPECT_FLOAT_EQ(m_floatConditionNode->GetOutputFloat(m_animGraphInstance,
m_useBoolOutput ? BlendTreeFloatConditionNode::PORTID_OUTPUT_BOOL : BlendTreeFloatConditionNode::PORTID_OUTPUT_VALUE)->
GetValue(), m_param.m_expectedOutputForTwoInput[i] ? 1.0f : 0.0f)
<< "(With X and Y input) expected ouput: " << m_param.m_expectedOutputForTwoInput[i];
}
};
INSTANTIATE_TEST_CASE_P(BlendTreeFloatConditionNode_ConditionTest,
BlendTreeFloatConditionNodeFixture,
::testing::Combine(
::testing::Bool(),
::testing::ValuesIn(blendTreeConditionNodeConditionTestData)
)
);
} // end namespace EMotionFX