SimulatedObjectCommandTests.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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 "ActorFixture.h"
  9. #include <MCore/Source/CommandGroup.h>
  10. #include <EMotionFX/Source/Actor.h>
  11. #include <EMotionFX/CommandSystem/Source/CommandManager.h>
  12. #include <EMotionFX/CommandSystem/Source/SimulatedObjectCommands.h>
  13. #include <EMotionFX/Source/SimulatedObjectSetup.h>
  14. namespace EMotionFX
  15. {
  16. class SimulatedObjectCommandTests
  17. : public ActorFixture
  18. {
  19. public:
  20. size_t CountSimulatedObjects(const Actor* actor)
  21. {
  22. return actor->GetSimulatedObjectSetup()->GetNumSimulatedObjects();
  23. }
  24. size_t CountSimulatedJoints(const Actor* actor, size_t objectIndex)
  25. {
  26. const AZStd::shared_ptr<SimulatedObjectSetup>& simulatedObjectSetup = actor->GetSimulatedObjectSetup();
  27. const SimulatedObject* object = simulatedObjectSetup->GetSimulatedObject(objectIndex);
  28. return object->GetNumSimulatedJoints();
  29. }
  30. size_t CountChildJoints(const Actor* actor, size_t objectIndex, size_t jointIndex)
  31. {
  32. const AZStd::shared_ptr<SimulatedObjectSetup>& simulatedObjectSetup = actor->GetSimulatedObjectSetup();
  33. const SimulatedObject* object = simulatedObjectSetup->GetSimulatedObject(objectIndex);
  34. const SimulatedJoint* joint = object->FindSimulatedJointBySkeletonJointIndex(jointIndex);
  35. return joint->CalculateNumChildSimulatedJoints();
  36. }
  37. size_t CountRootJoints(const Actor* actor, size_t objectIndex)
  38. {
  39. const AZStd::shared_ptr<SimulatedObjectSetup>& simulatedObjectSetup = actor->GetSimulatedObjectSetup();
  40. const SimulatedObject* object = simulatedObjectSetup->GetSimulatedObject(objectIndex);
  41. return object->GetNumSimulatedRootJoints();
  42. }
  43. };
  44. TEST_F(SimulatedObjectCommandTests, EvaluateSimulatedObjectCommands)
  45. {
  46. AZStd::string result;
  47. CommandSystem::CommandManager commandManager;
  48. MCore::CommandGroup commandGroup;
  49. const uint32 actorId = GetActor()->GetID();
  50. const AZStd::vector<AZStd::string> jointNames = GetTestJointNames();
  51. // 1. Add simulated object.
  52. const AZStd::string serializedBeforeAdd = SerializeSimulatedObjectSetup(GetActor());
  53. CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
  54. CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
  55. CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
  56. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  57. const AZStd::string serializedAfterAdd = SerializeSimulatedObjectSetup(GetActor());
  58. EXPECT_EQ(3, CountSimulatedObjects(GetActor()));
  59. EXPECT_TRUE(commandManager.Undo(result));
  60. EXPECT_EQ(0, CountSimulatedObjects(GetActor()));
  61. EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor()));
  62. EXPECT_TRUE(commandManager.Redo(result));
  63. EXPECT_EQ(3, CountSimulatedObjects(GetActor()));
  64. EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(GetActor()));
  65. // 2. Remove simulated object.
  66. commandGroup.RemoveAllCommands();
  67. CommandSimulatedObjectHelpers::RemoveSimulatedObject(actorId, 2, &commandGroup);
  68. CommandSimulatedObjectHelpers::RemoveSimulatedObject(actorId, 0, &commandGroup);
  69. CommandSimulatedObjectHelpers::RemoveSimulatedObject(actorId, 0, &commandGroup);
  70. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  71. EXPECT_EQ(0, CountSimulatedObjects(GetActor()));
  72. EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor()));
  73. EXPECT_TRUE(commandManager.Undo(result));
  74. EXPECT_EQ(3, CountSimulatedObjects(GetActor()));
  75. EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(GetActor()));
  76. EXPECT_TRUE(commandManager.Redo(result));
  77. EXPECT_EQ(0, CountSimulatedObjects(GetActor()));
  78. EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor()));
  79. // 3. Add simulated joints.
  80. // 3.1 Add a simulated object first to put in the simulated joints.
  81. commandGroup.RemoveAllCommands();
  82. CommandSimulatedObjectHelpers::AddSimulatedObject(actorId);
  83. const AZStd::string serialized3_1 = SerializeSimulatedObjectSetup(GetActor());
  84. // 3.2 Add simulated joints.
  85. // Joint hierarchy as follow:
  86. // l_upLeg
  87. // --l_upLegRoll
  88. // --l_loLeg
  89. // --l_ankle
  90. // --l_ball
  91. const Skeleton* skeleton = GetActor()->GetSkeleton();
  92. const size_t l_upLegIdx = skeleton->FindNodeByName("l_upLeg")->GetNodeIndex();
  93. const size_t l_upLegRollIdx = skeleton->FindNodeByName("l_upLegRoll")->GetNodeIndex();
  94. const size_t l_loLegIdx = skeleton->FindNodeByName("l_loLeg")->GetNodeIndex();
  95. const size_t l_ankleIdx = skeleton->FindNodeByName("l_ankle")->GetNodeIndex();
  96. const size_t l_ballIdx = skeleton->FindNodeByName("l_ball")->GetNodeIndex();
  97. CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, {l_upLegIdx, l_upLegRollIdx, l_loLegIdx, l_ankleIdx, l_ballIdx}, 0, false, &commandGroup);
  98. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  99. const AZStd::string serialized3_2 = SerializeSimulatedObjectSetup(GetActor());
  100. EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
  101. EXPECT_EQ(2, CountChildJoints(GetActor(), 0, l_upLegIdx));
  102. EXPECT_EQ(0, CountChildJoints(GetActor(), 0, l_upLegRollIdx));
  103. EXPECT_EQ(1, CountChildJoints(GetActor(), 0, l_loLegIdx));
  104. EXPECT_TRUE(commandManager.Undo(result));
  105. EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
  106. EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor()));
  107. EXPECT_TRUE(commandManager.Redo(result));
  108. EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
  109. EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor()));
  110. // 4 Remove simulated joints.
  111. // 4.1 Test sparse chain.
  112. EXPECT_EQ(1, CountRootJoints(GetActor(), 0));
  113. commandGroup.RemoveAllCommands();
  114. CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, {l_loLegIdx}, 0, false, &commandGroup);
  115. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  116. EXPECT_EQ(2, CountRootJoints(GetActor(), 0));
  117. EXPECT_TRUE(commandManager.Undo(result));
  118. EXPECT_EQ(1, CountRootJoints(GetActor(), 0));
  119. EXPECT_TRUE(commandManager.Redo(result));
  120. EXPECT_EQ(2, CountRootJoints(GetActor(), 0));
  121. EXPECT_TRUE(commandManager.Undo(result));
  122. // 4.2 Test removing all the joints.
  123. commandGroup.RemoveAllCommands();
  124. CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { l_upLegIdx, l_upLegRollIdx, l_loLegIdx, l_ankleIdx, l_ballIdx }, 0, false, &commandGroup);
  125. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  126. EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
  127. EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor()));
  128. EXPECT_TRUE(commandManager.Undo(result));
  129. EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
  130. EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor()));
  131. // 4.3 Test removing the root joint and children.
  132. commandGroup.RemoveAllCommands();
  133. CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { l_upLegIdx }, 0, true, &commandGroup);
  134. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  135. EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
  136. EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor()));
  137. EXPECT_TRUE(commandManager.Undo(result));
  138. EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0));
  139. EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor()));
  140. }
  141. TEST_F(SimulatedObjectCommandTests, SimulatedObjectCommands_UndoRemoveJointTest)
  142. {
  143. AZStd::string result;
  144. CommandSystem::CommandManager commandManager;
  145. MCore::CommandGroup commandGroup;
  146. const uint32 actorId = GetActor()->GetID();
  147. const AZStd::vector<AZStd::string> jointNames = GetTestJointNames();
  148. // 1. Add simulated object
  149. CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup);
  150. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  151. const AZStd::string serializedBase = SerializeSimulatedObjectSetup(GetActor());
  152. const size_t simulatedObjectIndex = 0;
  153. // 2. Add r_upLeg simulated joints
  154. const Skeleton* skeleton = GetActor()->GetSkeleton();
  155. const size_t r_upLegIdx = skeleton->FindNodeByName("r_upLeg")->GetNodeIndex();
  156. const size_t r_loLegIdx = skeleton->FindNodeByName("r_loLeg")->GetNodeIndex();
  157. CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, { r_upLegIdx, r_loLegIdx }, 0, false);
  158. EXPECT_EQ(2, CountSimulatedJoints(GetActor(), 0));
  159. const AZStd::string serializedUpLeg = SerializeSimulatedObjectSetup(GetActor());
  160. // 3. Remove the r_loLeg simulated joint
  161. AZStd::vector<SimulatedJoint*> jointsToBeRemoved;
  162. commandGroup.RemoveAllCommands();
  163. CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { r_upLegIdx }, simulatedObjectIndex, true, &commandGroup);
  164. EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result));
  165. EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0));
  166. EXPECT_EQ(serializedBase, SerializeSimulatedObjectSetup(GetActor()));
  167. // 4. Undo
  168. // This recreates r_loLeg and r_loLeg but won't add all other children recursively as only these two joints got aded in step 3.
  169. EXPECT_TRUE(commandManager.Undo(result));
  170. EXPECT_EQ(2, CountSimulatedJoints(GetActor(), 0));
  171. EXPECT_EQ(serializedUpLeg, SerializeSimulatedObjectSetup(GetActor()));
  172. }
  173. } // namespace EMotionFX