ClothSystemTest.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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 <AZTestShared/Math/MathTestHelpers.h>
  9. #include <AzCore/Interface/Interface.h>
  10. #include <AzCore/Component/TickBus.h>
  11. #include <UnitTestHelper.h>
  12. #include <TriangleInputHelper.h>
  13. #include <NvCloth/IClothSystem.h>
  14. #include <NvCloth/ISolver.h>
  15. #include <NvCloth/ICloth.h>
  16. #include <NvCloth/IFabricCooker.h>
  17. #include <System/Cloth.h>
  18. #include <System/Solver.h>
  19. namespace UnitTest
  20. {
  21. TEST(NvClothSystem, ClothSystem_DefaultSolver_Exists)
  22. {
  23. NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
  24. EXPECT_TRUE(defaultSolver != nullptr);
  25. EXPECT_TRUE(defaultSolver->GetName() == NvCloth::DefaultSolverName);
  26. }
  27. TEST(NvClothSystem, ClothSystem_FindOrCreateSolverDefaultName_ReturnsDefaultSolver)
  28. {
  29. NvCloth::ISolver* defaultSolverFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
  30. NvCloth::ISolver* defaultSolverFromFindOrCreateFunc = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(NvCloth::DefaultSolverName);
  31. EXPECT_EQ(defaultSolverFromGetter, defaultSolverFromFindOrCreateFunc);
  32. }
  33. TEST(NvClothSystem, ClothSystem_FindOrCreateSolverEmptyName_ReturnsNull)
  34. {
  35. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver("");
  36. EXPECT_TRUE(solver == nullptr);
  37. }
  38. TEST(NvClothSystem, ClothSystem_FindOrCreateSolver_ReturnsValidSolver)
  39. {
  40. const AZStd::string solverName = "Solver_FindOrCreateSolver";
  41. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
  42. EXPECT_TRUE(solver != nullptr);
  43. EXPECT_TRUE(solver->GetName() == solverName);
  44. // NOTE: IClothSystem is persistent as it's part of the test environment.
  45. // Destroying solver to avoid leaving it in the environment.
  46. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
  47. }
  48. TEST(NvClothSystem, ClothSystem_FindOrCreateSolverTwice_ReturnsSameSolver)
  49. {
  50. const AZStd::string solverName = "Solver_FindOrCreateSolverTwice";
  51. NvCloth::ISolver* solverA = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
  52. NvCloth::ISolver* solverB = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
  53. EXPECT_EQ(solverA, solverB);
  54. // NOTE: IClothSystem is persistent as it's part of the test environment.
  55. // Destroying solver to avoid leaving it in the environment.
  56. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solverA);
  57. }
  58. TEST(NvClothSystem, ClothSystem_DestroySolverNullptr_DoesNotFail)
  59. {
  60. NvCloth::ISolver* solver = nullptr;
  61. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
  62. EXPECT_TRUE(solver == nullptr);
  63. }
  64. TEST(NvClothSystem, ClothSystem_DestroySolver_SolverIsDestroyed)
  65. {
  66. const AZStd::string solverName = "Solver_DestroySolver";
  67. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
  68. EXPECT_TRUE(solver != nullptr);
  69. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
  70. EXPECT_TRUE(solver == nullptr);
  71. }
  72. TEST(NvClothSystem, ClothSystem_GetSolverEmpyName_ReturnsNull)
  73. {
  74. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver("");
  75. EXPECT_TRUE(solver == nullptr);
  76. }
  77. TEST(NvClothSystem, ClothSystem_GetSolverUnknownName_ReturnsNull)
  78. {
  79. const AZStd::string solverName = "Solver_GetSolverUnknownName";
  80. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(solverName);
  81. EXPECT_TRUE(solver == nullptr);
  82. }
  83. TEST(NvClothSystem, ClothSystem_GetSolver_ReturnsSolver)
  84. {
  85. const AZStd::string solverName = "Solver_GetSolver";
  86. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver(solverName);
  87. NvCloth::ISolver* solverFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(solverName);
  88. EXPECT_TRUE(solver != nullptr);
  89. EXPECT_EQ(solver, solverFromGetter);
  90. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
  91. solverFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(solverName);
  92. EXPECT_TRUE(solverFromGetter == nullptr);
  93. }
  94. TEST(NvClothSystem, ClothSystem_CreateClothNoInitialParticles_ReturnsNull)
  95. {
  96. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth({}, {});
  97. EXPECT_TRUE(cloth == nullptr);
  98. }
  99. TEST(NvClothSystem, ClothSystem_CreateClothInvalidFabric_ReturnsNull)
  100. {
  101. const float width = 1.0f;
  102. const float height = 1.0f;
  103. const AZ::u32 segmentsX = 5;
  104. const AZ::u32 segmentsY = 5;
  105. const TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
  106. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(planeXY.m_vertices, {});
  107. EXPECT_TRUE(cloth == nullptr);
  108. }
  109. TEST(NvClothSystem, ClothSystem_CreateClothInitialParticlesMismatchFabricNumParticles_ReturnsNull)
  110. {
  111. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  112. auto otherVertices = fabricCookedData.m_particles;
  113. otherVertices.resize(otherVertices.size() / 2);
  114. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(
  115. otherVertices, // otherVertices has a different number of vertices than FabricCookedData
  116. fabricCookedData);
  117. EXPECT_TRUE(cloth == nullptr);
  118. }
  119. TEST(NvClothSystem, ClothSystem_CreateCloth_ReturnsValidCloth)
  120. {
  121. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  122. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  123. EXPECT_TRUE(cloth != nullptr);
  124. EXPECT_TRUE(cloth->GetId().IsValid());
  125. EXPECT_THAT(cloth->GetInitialParticles(), ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), fabricCookedData.m_particles));
  126. EXPECT_EQ(cloth->GetInitialIndices(), fabricCookedData.m_indices);
  127. EXPECT_THAT(cloth->GetParticles(), ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), fabricCookedData.m_particles));
  128. EXPECT_NE(cloth->GetClothConfigurator(), nullptr);
  129. ExpectEq(cloth->GetFabricCookedData(), fabricCookedData);
  130. // NOTE: IClothSystem is persistent as it's part of the test environment.
  131. // Destroying cloth to avoid leaving it in the environment.
  132. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  133. }
  134. TEST(NvClothSystem, ClothSystem_DestroyClothNullptr_DoesNotFail)
  135. {
  136. NvCloth::ICloth* cloth = nullptr;
  137. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  138. EXPECT_TRUE(cloth == nullptr);
  139. }
  140. TEST(NvClothSystem, ClothSystem_DestroyCloth_ClothIsDestroyed)
  141. {
  142. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  143. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  144. EXPECT_TRUE(cloth != nullptr);
  145. EXPECT_TRUE(cloth->GetId().IsValid());
  146. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  147. EXPECT_TRUE(cloth == nullptr);
  148. }
  149. TEST(NvClothSystem, ClothSystem_GetClothInvalidId_ReturnsNull)
  150. {
  151. const NvCloth::ClothId clothId;
  152. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->GetCloth(clothId);
  153. EXPECT_TRUE(cloth == nullptr);
  154. }
  155. TEST(NvClothSystem, ClothSystem_GetClothUnknownId_ReturnsNull)
  156. {
  157. const NvCloth::ClothId clothId(5);
  158. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->GetCloth(clothId);
  159. EXPECT_TRUE(cloth == nullptr);
  160. }
  161. TEST(NvClothSystem, ClothSystem_GetCloth_ReturnsCloth)
  162. {
  163. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  164. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  165. EXPECT_TRUE(cloth != nullptr);
  166. EXPECT_TRUE(cloth->GetId().IsValid());
  167. NvCloth::ICloth* clothFromGetter = AZ::Interface<NvCloth::IClothSystem>::Get()->GetCloth(cloth->GetId());
  168. EXPECT_TRUE(clothFromGetter != nullptr);
  169. // NOTE: IClothSystem is persistent as it's part of the test environment.
  170. // Destroying cloth to avoid leaving it in the environment.
  171. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  172. }
  173. TEST(NvClothSystem, ClothSystem_AddClothNull_ReturnsFalse)
  174. {
  175. NvCloth::ICloth* cloth = nullptr;
  176. bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
  177. EXPECT_FALSE(clothAdded);
  178. }
  179. TEST(NvClothSystem, ClothSystem_AddClothToInvalidSolver_ReturnsFalse)
  180. {
  181. const AZStd::string solverName = "";
  182. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  183. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  184. bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solverName);
  185. EXPECT_FALSE(clothAdded);
  186. // NOTE: IClothSystem is persistent as it's part of the test environment.
  187. // Destroying cloth to avoid leaving it in the environment.
  188. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  189. }
  190. TEST(NvClothSystem, ClothSystem_AddClothToNonExistentSolver_ReturnsFalse)
  191. {
  192. const AZStd::string solverName = "Solver_AddClothToNonExistentSolver";
  193. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  194. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  195. bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solverName);
  196. EXPECT_FALSE(clothAdded);
  197. // NOTE: IClothSystem is persistent as it's part of the test environment.
  198. // Destroying cloth to avoid leaving it in the environment.
  199. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  200. }
  201. TEST(NvClothSystem, ClothSystem_AddClothToDefaultSolver_ReturnsTrue)
  202. {
  203. NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
  204. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
  205. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  206. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  207. bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
  208. EXPECT_TRUE(clothAdded);
  209. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
  210. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
  211. // NOTE: IClothSystem is persistent as it's part of the test environment.
  212. // Destroying cloth to avoid leaving it in the environment.
  213. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  214. }
  215. TEST(NvClothSystem, ClothSystem_AddClothToSolver_ReturnsTrue)
  216. {
  217. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver("Solver_AddClothToSolver");
  218. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(solver)->GetNumCloths() == 0);
  219. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  220. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  221. bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solver->GetName());
  222. EXPECT_TRUE(clothAdded);
  223. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == solver->GetName());
  224. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(solver)->GetNumCloths() == 1);
  225. // NOTE: IClothSystem is persistent as it's part of the test environment.
  226. // Destroying cloth and solver to avoid leaving it in the environment.
  227. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  228. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
  229. }
  230. TEST(NvClothSystem, ClothSystem_AddClothTwice_NothingHappensSecondTime)
  231. {
  232. NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
  233. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
  234. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  235. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  236. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver() == nullptr);
  237. bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
  238. EXPECT_TRUE(clothAdded);
  239. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
  240. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
  241. clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
  242. EXPECT_TRUE(clothAdded);
  243. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
  244. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
  245. // NOTE: IClothSystem is persistent as it's part of the test environment.
  246. // Destroying cloth to avoid leaving it in the environment.
  247. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  248. }
  249. TEST(NvClothSystem, ClothSystem_RemoveClothNull_NothingHappens)
  250. {
  251. NvCloth::ICloth* cloth = nullptr;
  252. AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth);
  253. EXPECT_TRUE(cloth == nullptr);
  254. }
  255. TEST(NvClothSystem, ClothSystem_RemoveClothTwice_NothingHappensSecondTime)
  256. {
  257. NvCloth::ISolver* defaultSolver = AZ::Interface<NvCloth::IClothSystem>::Get()->GetSolver(NvCloth::DefaultSolverName);
  258. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
  259. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  260. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  261. bool clothAdded = AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth);
  262. EXPECT_TRUE(clothAdded);
  263. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver()->GetName() == NvCloth::DefaultSolverName);
  264. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 1);
  265. AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth);
  266. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver() == nullptr);
  267. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
  268. AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth);
  269. EXPECT_TRUE(azrtti_cast<NvCloth::Cloth*>(cloth)->GetSolver() == nullptr);
  270. EXPECT_TRUE(azrtti_cast<NvCloth::Solver*>(defaultSolver)->GetNumCloths() == 0);
  271. // NOTE: IClothSystem is persistent as it's part of the test environment.
  272. // Destroying cloth to avoid leaving it in the environment.
  273. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  274. }
  275. TEST(NvClothSystem, ClothSystem_Tick_SolverAndClothIsUpdated)
  276. {
  277. const float deltaTimeSim = 1.0f / 60.0f;
  278. NvCloth::ISolver* solver = AZ::Interface<NvCloth::IClothSystem>::Get()->FindOrCreateSolver("Solver_Tick");
  279. const NvCloth::FabricCookedData fabricCookedData = CreateTestFabricCookedData();
  280. NvCloth::ICloth* cloth = AZ::Interface<NvCloth::IClothSystem>::Get()->CreateCloth(fabricCookedData.m_particles, fabricCookedData);
  281. bool solverPreSimulationEventSignaled = false;
  282. NvCloth::ISolver::PreSimulationEvent::Handler solverPreSimulationEventHandler(
  283. [&solverPreSimulationEventSignaled](const AZStd::string&, float)
  284. {
  285. solverPreSimulationEventSignaled = true;
  286. });
  287. bool solverPostSimulationEventSignaled = false;
  288. NvCloth::ISolver::PostSimulationEvent::Handler solverPostSimulationEventHandler(
  289. [&solverPostSimulationEventSignaled](const AZStd::string&, float)
  290. {
  291. solverPostSimulationEventSignaled = true;
  292. });
  293. bool clothPreSimulationEventSignaled = false;
  294. NvCloth::ICloth::PreSimulationEvent::Handler clothPreSimulationEventHandler(
  295. [&clothPreSimulationEventSignaled](NvCloth::ClothId, float)
  296. {
  297. clothPreSimulationEventSignaled = true;
  298. });
  299. bool clothPostSimulationEventSignaled = false;
  300. NvCloth::ICloth::PostSimulationEvent::Handler clothPostSimulationEventHandler(
  301. [&clothPostSimulationEventSignaled](NvCloth::ClothId, float, const AZStd::vector<NvCloth::SimParticleFormat>&)
  302. {
  303. clothPostSimulationEventSignaled = true;
  304. });
  305. solver->ConnectPreSimulationEventHandler(solverPreSimulationEventHandler);
  306. solver->ConnectPostSimulationEventHandler(solverPostSimulationEventHandler);
  307. cloth->ConnectPreSimulationEventHandler(clothPreSimulationEventHandler);
  308. cloth->ConnectPostSimulationEventHandler(clothPostSimulationEventHandler);
  309. AZ::Interface<NvCloth::IClothSystem>::Get()->AddCloth(cloth, solver->GetName()); // It needs at least one cloth in the solver to simulate
  310. // Ticking Cloth System to update all its solvers
  311. AZ::TickBus::Broadcast(&AZ::TickEvents::OnTick,
  312. deltaTimeSim,
  313. AZ::ScriptTimePoint(AZStd::chrono::steady_clock::now()));
  314. EXPECT_TRUE(solverPreSimulationEventSignaled);
  315. EXPECT_TRUE(solverPostSimulationEventSignaled);
  316. EXPECT_TRUE(clothPreSimulationEventSignaled);
  317. EXPECT_TRUE(clothPostSimulationEventSignaled);
  318. solverPreSimulationEventSignaled = false;
  319. solverPostSimulationEventSignaled = false;
  320. clothPreSimulationEventSignaled = false;
  321. clothPostSimulationEventSignaled = false;
  322. AZ::Interface<NvCloth::IClothSystem>::Get()->RemoveCloth(cloth); // Leave solver without have any cloths
  323. // Ticking Cloth System to update all its solvers
  324. AZ::TickBus::Broadcast(&AZ::TickEvents::OnTick,
  325. deltaTimeSim,
  326. AZ::ScriptTimePoint(AZStd::chrono::steady_clock::now()));
  327. EXPECT_FALSE(solverPreSimulationEventSignaled);
  328. EXPECT_FALSE(solverPostSimulationEventSignaled);
  329. EXPECT_FALSE(clothPreSimulationEventSignaled);
  330. EXPECT_FALSE(clothPostSimulationEventSignaled);
  331. // NOTE: IClothSystem is persistent as it's part of the test environment.
  332. // Destroying cloth and solver to avoid leaving it in the environment.
  333. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroyCloth(cloth);
  334. AZ::Interface<NvCloth::IClothSystem>::Get()->DestroySolver(solver);
  335. }
  336. } // namespace UnitTest