3
0

EditTransition.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 <gtest/gtest.h>
  9. #include <iostream>
  10. #include <cstdlib>
  11. #include <QAction>
  12. #include <QtTest>
  13. #include <QWidget>
  14. #include <QRect>
  15. #include <QComboBox>
  16. #include <EMotionFX/Source/AnimGraphMotionNode.h>
  17. #include <EMotionFX/Source/AnimGraphManager.h>
  18. #include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h>
  19. #include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
  20. #include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h>
  21. #include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h>
  22. #include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h>
  23. #include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h>
  24. #include <EMotionFX/Source/AnimGraphStateMachine.h>
  25. #include <Tests/UI/AnimGraphUIFixture.h>
  26. #include <AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx>
  27. #include <Source/Editor/ObjectEditor.h>
  28. #include <AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx>
  29. #include <AzToolsFramework/UI/PropertyEditor/GenericComboBoxCtrl.h>
  30. namespace QTest
  31. {
  32. extern int Q_TESTLIB_EXPORT defaultMouseDelay();
  33. } // namespace QTest
  34. namespace EMotionFX
  35. {
  36. TEST_F(AnimGraphUIFixture, CanEditTransition)
  37. {
  38. // This test checks that you can edit a transition between nodes of an animgraph
  39. RecordProperty("test_case_id", "C21948785");
  40. // Set up animgraph
  41. EMotionFX::AnimGraph* animGraph = AnimGraphUIFixture::CreateAnimGraph();
  42. {
  43. // Place two motion nodes
  44. MCore::CommandGroup group;
  45. // Create empty anim graph, add a motion, entry, hub, and blend tree node.
  46. group.AddCommandString(AZStd::string::format("AnimGraphCreateNode -animGraphID %d -type %s -parentName Root -xPos 200 -yPos 200 -name motionNodeA",
  47. animGraph->GetID(), azrtti_typeid<AnimGraphMotionNode>().ToString<AZStd::string>().c_str()));
  48. group.AddCommandString(AZStd::string::format("AnimGraphCreateNode -animGraphID %d -type %s -parentName Root -xPos 0 -yPos 0 -name motionNodeB",
  49. animGraph->GetID(), azrtti_typeid<AnimGraphMotionNode>().ToString<AZStd::string>().c_str()));
  50. // Run Commands
  51. AZStd::string commandResult;
  52. EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommandGroup(group, commandResult)) << commandResult.c_str();
  53. }
  54. // Create Needed Objects
  55. AnimGraphMotionNode* motionNodeA = static_cast<AnimGraphMotionNode*>(animGraph->RecursiveFindNodeByName("motionNodeA"));
  56. AnimGraphMotionNode* motionNodeB = static_cast<AnimGraphMotionNode*>(animGraph->RecursiveFindNodeByName("motionNodeB"));
  57. EMStudio::NodeGraph* nodeGraph = AnimGraphUIFixture::GetActiveNodeGraph();
  58. const EMStudio::GraphNode* graphNodeForMotionNode0 = nodeGraph->FindGraphNode(motionNodeA);
  59. const EMStudio::GraphNode* graphNodeForMotionNode1 = nodeGraph->FindGraphNode(motionNodeB);
  60. EMStudio::AnimGraphModel& model = m_animGraphPlugin->GetAnimGraphModel();
  61. EMStudio::AttributesWindow* attributesWindow = m_animGraphPlugin->GetAttributesWindow();
  62. // Add transition between two nodes
  63. m_blendGraphWidget->resize(500, 500);
  64. m_animGraphPlugin->GetViewWidget()->ZoomSelected();
  65. const QPoint begin(graphNodeForMotionNode0->GetFinalRect().topRight() + QPoint(-2, 2));
  66. const QPoint end(graphNodeForMotionNode1->GetFinalRect().topLeft() + QPoint(2, 2));
  67. QTest::mousePress(static_cast<QWidget*>(m_blendGraphWidget), Qt::LeftButton, Qt::NoModifier, begin);
  68. {
  69. // QTest::mouseMove uses QCursor::setPos to generate a MouseMove
  70. // event to send to the resulting widget. This won't happen if the
  71. // widget isn't visible. So we need to send the event directly.
  72. QMouseEvent moveEvent(QMouseEvent::MouseMove, end, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
  73. moveEvent.setTimestamp(QTest::lastMouseTimestamp += QTest::defaultMouseDelay());
  74. QApplication::instance()->notify(m_blendGraphWidget, &moveEvent);
  75. }
  76. QTest::mouseRelease(static_cast<QWidget*>(m_blendGraphWidget), Qt::LeftButton, Qt::NoModifier, end);
  77. // Ensure the transition was added to the root state machine
  78. ASSERT_EQ(animGraph->GetRootStateMachine()->GetNumTransitions(), 1);
  79. // Ensure the transition is in the AnimGraphModel
  80. AnimGraphStateTransition* transition = animGraph->GetRootStateMachine()->GetTransition(0);
  81. const QModelIndexList matches = model.match(
  82. /* starting index = */ model.index(0, 0, model.index(0, 0)),
  83. /* role = */ EMStudio::AnimGraphModel::ROLE_POINTER,
  84. /* value = */ QVariant::fromValue(static_cast<void*>(transition)),
  85. /* hits =*/ 1,
  86. Qt::MatchExactly
  87. );
  88. ASSERT_EQ(matches.size(), 1);
  89. // Select Transition
  90. QPoint transitionCenter;
  91. transitionCenter.setX((((end.x() - begin.x()) / 2) + begin.x()));
  92. transitionCenter.setY((((end.y() - begin.y()) / 2) + begin.y()));
  93. QTest::mouseClick(static_cast<QWidget*>(m_blendGraphWidget), Qt::LeftButton, Qt::NoModifier, transitionCenter);
  94. // Make sure transition was selected
  95. ASSERT_EQ(nodeGraph->GetSelectedNodeConnections().size(), 1) << "Transition was not selected";
  96. ASSERT_EQ(transition->GetSyncMode(), 0) << "Transition did not start with the expected sync mode";
  97. ASSERT_EQ(transition->GetInterpolationType(), 0) << "Transition did not start with the expected interpolation type";
  98. using WidgetListItem = AZStd::pair<AzToolsFramework::InstanceDataNode*, AzToolsFramework::PropertyRowWidget*>;
  99. using WidgetList = AZStd::unordered_map<AzToolsFramework::InstanceDataNode*, AzToolsFramework::PropertyRowWidget*>;
  100. auto objectEditor = attributesWindow->findChild<ObjectEditor*>("EMFX.AttributesWindow.ObjectEditor");
  101. auto propertyEditor = objectEditor->findChild<AzToolsFramework::ReflectedPropertyEditor*>("PropertyEditor");
  102. const WidgetList& list = propertyEditor->GetWidgets();
  103. // Look for PropertyRowWidget for "Sync mode"
  104. AzToolsFramework::PropertyRowWidget* syncPropertyRow = nullptr;
  105. for (const WidgetListItem& item : list) {
  106. if (item.second->objectName() == "Sync mode")
  107. {
  108. syncPropertyRow = item.second;
  109. }
  110. }
  111. ASSERT_TRUE(syncPropertyRow) << "Could not find the 'Sync mode' PropertyRowWidget";
  112. // Edit value in property combo box
  113. auto comboBox = reinterpret_cast<QComboBox*>(syncPropertyRow->GetChildWidget()->children()[1]);
  114. ASSERT_TRUE(comboBox) << "Sync Mode Combo box not found";
  115. comboBox->setCurrentIndex(1);
  116. // Look for PropertyRowWidget for "Interpolation"
  117. AzToolsFramework::PropertyRowWidget* interpolationPropertyRow = nullptr;
  118. for (const WidgetListItem& item : list) {
  119. if (item.second->objectName() == "Interpolation")
  120. {
  121. interpolationPropertyRow = item.second;
  122. }
  123. }
  124. ASSERT_TRUE(interpolationPropertyRow) << "Could not find the 'Interpolation' PropertyRowWidget";
  125. // Edit value in property combo box
  126. auto comboBox2 = reinterpret_cast<QComboBox*>(interpolationPropertyRow->GetChildWidget()->children()[1]);
  127. ASSERT_TRUE(comboBox2) << "Sync Mode Combo box not found";
  128. comboBox2->setCurrentIndex(1);
  129. //Check that the transition has been edited properly
  130. ASSERT_EQ(transition->GetSyncMode(), 1) << "Transition did not start with the expected sync mode";
  131. ASSERT_EQ(transition->GetInterpolationType(), 1) << "Transition did not start with the expected interpolation type";
  132. QApplication::processEvents();
  133. }
  134. } // namespace EMotionFX