SkeletonOutlinerTestFixture.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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 <gmock/gmock.h>
  9. #include <gtest/gtest.h>
  10. #include <AzQtComponents/Components/Widgets/SpinBox.h>
  11. #include <AzToolsFramework/UI/PropertyEditor/PropertyDoubleSpinCtrl.hxx>
  12. #include <AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx>
  13. #include <AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx>
  14. #include <Editor/ColliderContainerWidget.h>
  15. #include <Editor/ColliderHelpers.h>
  16. #include <Editor/ObjectEditor.h>
  17. #include <Editor/Plugins/SimulatedObject/SimulatedObjectWidget.h>
  18. #include <Tests/UI/SkeletonOutlinerTestFixture.h>
  19. #include <Tests/TestAssetCode/TestActorAssets.h>
  20. #include <Tests/TestAssetCode/SimpleActors.h>
  21. #include <QApplication>
  22. #include <QTest>
  23. namespace EMotionFX
  24. {
  25. void SkeletonOutlinerTestFixture::SetUpPhysics()
  26. {
  27. EMStudio::GetMainWindow()->ApplicationModeChanged("Physics");
  28. const int numJoints = 6;
  29. AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
  30. AZ::Data::Asset<Integration::ActorAsset> actorAsset =
  31. TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, numJoints, "TestsActor");
  32. m_actor = actorAsset->GetActor();
  33. CreateSkeletonAndModelIndices();
  34. EXPECT_EQ(m_indexList.size(), numJoints);
  35. }
  36. void SkeletonOutlinerTestFixture::SetUpSimulatedObject()
  37. {
  38. const int numJoints = 6;
  39. AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
  40. AZ::Data::Asset<Integration::ActorAsset> actorAsset =
  41. TestActorAssets::CreateActorAssetAndRegister<SimpleJointChainActor>(actorAssetId, numJoints, "TestsActor");
  42. CreateSkeletonAndModelIndices();
  43. EXPECT_EQ(m_indexList.size(), numJoints);
  44. }
  45. void SkeletonOutlinerTestFixture::AddColliderViaAddComponentButton(QString label, QString subLevelLabel)
  46. {
  47. EXPECT_GT(m_indexList.size(), 3) << "Make sure to have a skeleton";
  48. // Find the 3rd joint after the RootJoint in the TreeView and select it
  49. SelectIndexes(m_indexList, m_treeView, 3, 3);
  50. auto* treeView = GetAddCollidersTreeView();
  51. auto* model = treeView->model();
  52. // find indices
  53. QModelIndexList indices = model->match(
  54. model->index(0, 0),
  55. Qt::DisplayRole,
  56. QVariant::fromValue(label),
  57. -1,
  58. Qt::MatchRecursive);
  59. if (subLevelLabel != "")
  60. {
  61. indices = model->match(
  62. model->index(0, 0, indices[0]),
  63. Qt::DisplayRole,
  64. QVariant::fromValue(subLevelLabel),
  65. -1,
  66. Qt::MatchRecursive);
  67. }
  68. // check indices
  69. EXPECT_GE(indices.size(), 1) << "Label not found";
  70. EXPECT_LE(indices.size(), 1) << "Label is not unique";
  71. // click first index
  72. auto index = indices[0];
  73. treeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
  74. treeView->clicked(index);
  75. }
  76. void SkeletonOutlinerTestFixture::ShowJointPropertyWidget()
  77. {
  78. auto* mainwindow = new QMainWindow;
  79. auto* widget = GetJointPropertyWidget();
  80. auto* mainWidget = new QScrollArea;
  81. auto* mainLayout = new QVBoxLayout;
  82. mainLayout->addWidget(widget);
  83. mainWidget->setLayout(mainLayout);
  84. mainwindow->setMinimumHeight(1000);
  85. mainwindow->setCentralWidget(mainWidget);
  86. mainwindow->show();
  87. QApplication::processEvents();
  88. }
  89. //
  90. // Test Cases
  91. //
  92. TEST_F(SkeletonOutlinerTestFixture, AddClothCollider)
  93. {
  94. SetUpPhysics();
  95. AddColliderViaAddComponentButton("Cloth Collider", "Sphere");
  96. ShowJointPropertyWidget();
  97. EXPECT_TRUE(ColliderHelpers::NodeHasClothCollider(m_indexList[3]));
  98. }
  99. TEST_F(SkeletonOutlinerTestFixture, ChangeClothColliderValue)
  100. {
  101. SetUpPhysics();
  102. AddColliderViaAddComponentButton("Cloth Collider", "Capsule");
  103. // Check the node is in the ragdoll
  104. EXPECT_TRUE(ColliderHelpers::NodeHasClothCollider(m_indexList[3]));
  105. // Get the widget
  106. auto* widget = GetJointPropertyWidget();
  107. // Get a value widget
  108. auto propertyEditor = widget->findChild<AzToolsFramework::ReflectedPropertyEditor*>("PropertyEditor");
  109. // Get list of all PropertyRowWidgets (and their InstanceDataNodes)
  110. const auto list = propertyEditor->GetWidgets();
  111. ASSERT_GT(list.size(), 0) << "Did not find any PropertyRowWidgets";
  112. // Look for PropertyRowWidget for "Name"
  113. AzToolsFramework::PropertyRowWidget* propertyRow = nullptr;
  114. for (const auto& item : list)
  115. {
  116. if (item.second->objectName() == "Height")
  117. {
  118. propertyRow = item.second;
  119. }
  120. }
  121. // Change it
  122. auto *lineEdit = static_cast<AzToolsFramework::PropertyDoubleSpinCtrl*>(propertyRow->GetChildWidget());
  123. ASSERT_TRUE(lineEdit) << "Did not find Editing handle";
  124. lineEdit->setValue(3.89);
  125. lineEdit->editingFinished();
  126. // Make sure propertyWidget are created correctly
  127. ShowJointPropertyWidget();
  128. // We did not crash, at least
  129. }
  130. TEST_F(SkeletonOutlinerTestFixture, CopyAndPaste)
  131. {
  132. SetUpPhysics();
  133. // create a cloth collider to copy it
  134. // Find the 3rd joint after the RootJoint in the TreeView and select it
  135. SelectIndexes(m_indexList, m_treeView, 3, 3);
  136. auto selectionIndex = m_treeView->selectionModel()->selectedIndexes().first();
  137. // Add a Cloth Collider to it
  138. ColliderHelpers::AddCollider({selectionIndex}, PhysicsSetup::Cloth, azrtti_typeid<Physics::SphereShapeConfiguration>());
  139. AddColliderViaAddComponentButton("Copy from Cloth to Hit Detection");
  140. ShowJointPropertyWidget();
  141. EXPECT_TRUE(ColliderHelpers::NodeHasHitDetection(selectionIndex));
  142. }
  143. TEST_F(SkeletonOutlinerTestFixture, ClipboardCopyPaste)
  144. {
  145. SetUpPhysics();
  146. // Find the 3rd joint after the RootJoint in the TreeView and select it
  147. SelectIndexes(m_indexList, m_treeView, 3, 3);
  148. auto selectionIndex = m_treeView->selectionModel()->selectedIndexes().first();
  149. // Add a Cloth Collider to it
  150. ColliderHelpers::AddCollider({selectionIndex}, PhysicsSetup::Cloth, azrtti_typeid<Physics::SphereShapeConfiguration>());
  151. // copy it
  152. auto* jointWidget = GetJointPropertyWidget()->findChild<ClothJointWidget*>();
  153. auto* colliderContainerWidget = jointWidget->findChild<ColliderContainerWidget*>();
  154. emit colliderContainerWidget->CopyCollider(0);
  155. AddColliderViaAddComponentButton("Paste as Hit Detection Collider");
  156. ShowJointPropertyWidget();
  157. EXPECT_TRUE(ColliderHelpers::NodeHasHitDetection(selectionIndex));
  158. }
  159. TEST_F(SkeletonOutlinerTestFixture, SimulatedObject)
  160. {
  161. SetUpSimulatedObject();
  162. SelectIndexes(m_indexList, m_treeView, 3, 3);
  163. auto* plugin = EMStudio::GetPluginManager()->FindActivePlugin<SimulatedObjectWidget>();
  164. auto* w = plugin->GetDockWidget();
  165. auto* mw = new QMainWindow;
  166. mw->setCentralWidget(w);
  167. mw->show();
  168. ShowJointPropertyWidget();
  169. }
  170. } // namespace EMotionFX