3
0

AnimGraphParameterHandler.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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 <Editor/PropertyWidgets/AnimGraphParameterHandler.h>
  9. #include <EMotionFX/Source/AnimGraphNode.h>
  10. #include <EMotionFX/Source/EventManager.h>
  11. #include <EMotionFX/Source/ObjectAffectedByParameterChanges.h>
  12. #include <EMotionFX/Source/Parameter/BoolParameter.h>
  13. #include <EMotionFX/Source/Parameter/FloatSliderParameter.h>
  14. #include <EMotionFX/Source/Parameter/FloatSpinnerParameter.h>
  15. #include <EMotionFX/Source/Parameter/IntSliderParameter.h>
  16. #include <EMotionFX/Source/Parameter/IntSpinnerParameter.h>
  17. #include <EMotionFX/Source/Parameter/TagParameter.h>
  18. #include <EMotionFX/Source/Parameter/Vector2Parameter.h>
  19. #include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
  20. #include <EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h>
  21. #include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
  22. #include <QHBoxLayout>
  23. #include <QMessageBox>
  24. namespace EMotionFX
  25. {
  26. AZ_CLASS_ALLOCATOR_IMPL(AnimGraphParameterPicker, EditorAllocator);
  27. AZ_CLASS_ALLOCATOR_IMPL(AnimGraphSingleParameterHandler, EditorAllocator);
  28. AZ_CLASS_ALLOCATOR_IMPL(AnimGraphMultipleParameterHandler, EditorAllocator);
  29. AnimGraphParameterPicker::AnimGraphParameterPicker(QWidget* parent, bool singleSelection, bool parameterMaskMode)
  30. : QWidget(parent)
  31. , m_animGraph(nullptr)
  32. , m_affectedByParameterChanges(nullptr)
  33. , m_pickButton(nullptr)
  34. , m_resetButton(nullptr)
  35. , m_shrinkButton(nullptr)
  36. , m_singleSelection(singleSelection)
  37. , m_parameterMaskMode(parameterMaskMode)
  38. {
  39. QHBoxLayout* hLayout = new QHBoxLayout();
  40. hLayout->setMargin(0);
  41. m_pickButton = new QPushButton(this);
  42. connect(m_pickButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnPickClicked);
  43. hLayout->addWidget(m_pickButton);
  44. m_resetButton = new QPushButton(this);
  45. EMStudio::EMStudioManager::MakeTransparentButton(m_resetButton, "Images/Icons/Clear.svg", "Reset selection");
  46. connect(m_resetButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnResetClicked);
  47. hLayout->addWidget(m_resetButton);
  48. if (m_parameterMaskMode)
  49. {
  50. m_shrinkButton = new QPushButton();
  51. EMStudio::EMStudioManager::MakeTransparentButton(m_shrinkButton, "Images/Icons/Cut.svg", "Shrink the parameter mask to the ports that are actually connected.");
  52. connect(m_shrinkButton, &QPushButton::clicked, this, &AnimGraphParameterPicker::OnShrinkClicked);
  53. hLayout->addWidget(m_shrinkButton);
  54. }
  55. setLayout(hLayout);
  56. UpdateInterface();
  57. }
  58. void AnimGraphParameterPicker::OnResetClicked()
  59. {
  60. if (m_parameterNames.empty())
  61. {
  62. return;
  63. }
  64. UpdateParameterNames(AZStd::vector<AZStd::string>());
  65. }
  66. void AnimGraphParameterPicker::OnShrinkClicked()
  67. {
  68. if (!m_affectedByParameterChanges)
  69. {
  70. AZ_Error("EMotionFX", false, "Cannot shrink parameter mask. No valid parameter picker rule.");
  71. return;
  72. }
  73. AZStd::vector<AZStd::string> parameterNames;
  74. if (m_affectedByParameterChanges)
  75. {
  76. m_affectedByParameterChanges->AddRequiredParameters(parameterNames);
  77. }
  78. UpdateParameterNames(parameterNames);
  79. }
  80. void AnimGraphParameterPicker::UpdateInterface()
  81. {
  82. // Set the picker button name based on the number of nodes.
  83. const size_t numParameters = m_parameterNames.size();
  84. if (numParameters == 0)
  85. {
  86. if (m_singleSelection)
  87. {
  88. m_pickButton->setText("Select parameter");
  89. }
  90. else
  91. {
  92. m_pickButton->setText("Select parameters");
  93. }
  94. m_resetButton->setVisible(false);
  95. }
  96. else if (numParameters == 1)
  97. {
  98. m_pickButton->setText(m_parameterNames[0].c_str());
  99. m_resetButton->setVisible(true);
  100. }
  101. else
  102. {
  103. m_pickButton->setText(QString("%1 parameters").arg(numParameters));
  104. m_resetButton->setVisible(true);
  105. }
  106. // Build and set the tooltip containing all nodes.
  107. QString tooltip;
  108. for (size_t i = 0; i < numParameters; ++i)
  109. {
  110. tooltip += m_parameterNames[i].c_str();
  111. if (i != numParameters - 1)
  112. {
  113. tooltip += "\n";
  114. }
  115. }
  116. m_pickButton->setToolTip(tooltip);
  117. }
  118. void AnimGraphParameterPicker::SetObjectAffectedByParameterChanges(ObjectAffectedByParameterChanges* affectedObject)
  119. {
  120. m_affectedByParameterChanges = affectedObject;
  121. m_parameterNames = m_affectedByParameterChanges->GetParameters();
  122. UpdateInterface();
  123. }
  124. void AnimGraphParameterPicker::InitializeParameterNames(const AZStd::vector<AZStd::string>& parameterNames)
  125. {
  126. if (m_parameterNames != parameterNames)
  127. {
  128. m_parameterNames = parameterNames;
  129. UpdateInterface();
  130. }
  131. }
  132. void AnimGraphParameterPicker::UpdateParameterNames(const AZStd::vector<AZStd::string>& parameterNames)
  133. {
  134. if (m_parameterNames != parameterNames)
  135. {
  136. m_parameterNames = parameterNames;
  137. if (m_affectedByParameterChanges)
  138. {
  139. m_affectedByParameterChanges->ParameterMaskChanged(m_parameterNames);
  140. }
  141. emit ParametersChanged(m_parameterNames);
  142. UpdateInterface();
  143. }
  144. }
  145. const AZStd::vector<AZStd::string>& AnimGraphParameterPicker::GetParameterNames() const
  146. {
  147. return m_parameterNames;
  148. }
  149. void AnimGraphParameterPicker::SetSingleParameterName(const AZStd::string& parameterName)
  150. {
  151. AZStd::vector<AZStd::string> parameterNames;
  152. if (!parameterName.empty())
  153. {
  154. parameterNames.emplace_back(parameterName);
  155. }
  156. InitializeParameterNames(parameterNames);
  157. }
  158. const AZStd::string AnimGraphParameterPicker::GetSingleParameterName() const
  159. {
  160. if (m_parameterNames.empty())
  161. {
  162. return AZStd::string();
  163. }
  164. return m_parameterNames[0];
  165. }
  166. void AnimGraphParameterPicker::OnPickClicked()
  167. {
  168. AnimGraph* animGraph = m_animGraph;
  169. if (m_affectedByParameterChanges)
  170. {
  171. animGraph = m_affectedByParameterChanges->GetParameterAnimGraph();
  172. }
  173. if (!animGraph)
  174. {
  175. AZ_Error("EMotionFX", false, "Cannot open anim graph parameter selection window. No valid anim graph.");
  176. return;
  177. }
  178. // Create and show the node picker window
  179. EMStudio::ParameterSelectionWindow selectionWindow(this, m_singleSelection);
  180. selectionWindow.GetParameterWidget()->SetFilterTypes(m_filterTypes);
  181. selectionWindow.Update(animGraph, m_parameterNames);
  182. selectionWindow.setModal(true);
  183. if (selectionWindow.exec() != QDialog::Rejected)
  184. {
  185. AZStd::vector<AZStd::string> parameterNames = selectionWindow.GetParameterWidget()->GetSelectedParameters();
  186. if (m_parameterMaskMode)
  187. {
  188. if (m_affectedByParameterChanges)
  189. {
  190. m_affectedByParameterChanges->AddRequiredParameters(parameterNames);
  191. }
  192. }
  193. UpdateParameterNames(parameterNames);
  194. }
  195. }
  196. //---------------------------------------------------------------------------------------------------------------------------------------------------------
  197. AnimGraphSingleParameterHandler::AnimGraphSingleParameterHandler()
  198. : QObject()
  199. , AzToolsFramework::PropertyHandler<AZStd::string, AnimGraphParameterPicker>()
  200. , m_animGraph(nullptr)
  201. {
  202. }
  203. AZ::u32 AnimGraphSingleParameterHandler::GetHandlerName() const
  204. {
  205. return AZ_CRC("AnimGraphParameter", 0x778af55a);
  206. }
  207. QWidget* AnimGraphSingleParameterHandler::CreateGUI(QWidget* parent)
  208. {
  209. AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, true);
  210. connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker]([[maybe_unused]] const AZStd::vector<AZStd::string>& newParameters)
  211. {
  212. AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(
  213. &AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestWrite, picker);
  214. });
  215. return picker;
  216. }
  217. void AnimGraphSingleParameterHandler::ConsumeAttribute(AnimGraphParameterPicker* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
  218. {
  219. if (attrib == AZ::Edit::Attributes::ReadOnly)
  220. {
  221. bool value;
  222. if (attrValue->Read<bool>(value))
  223. {
  224. GUI->setEnabled(!value);
  225. }
  226. }
  227. if (attrib == AZ_CRC("AnimGraph", 0x0d53d4b3))
  228. {
  229. attrValue->Read<AnimGraph*>(m_animGraph);
  230. GUI->SetAnimGraph(m_animGraph);
  231. }
  232. }
  233. void AnimGraphSingleParameterHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, AnimGraphParameterPicker* GUI, property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
  234. {
  235. instance = GUI->GetSingleParameterName();
  236. }
  237. bool AnimGraphSingleParameterHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, AnimGraphParameterPicker* GUI, const property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
  238. {
  239. QSignalBlocker signalBlocker(GUI);
  240. GUI->SetSingleParameterName(instance);
  241. return true;
  242. }
  243. //---------------------------------------------------------------------------------------------------------------------------------------------------------
  244. AZ_CLASS_ALLOCATOR_IMPL(AnimGraphSingleNumberParameterHandler, EditorAllocator);
  245. AnimGraphSingleNumberParameterHandler::AnimGraphSingleNumberParameterHandler()
  246. : AnimGraphSingleParameterHandler()
  247. {
  248. }
  249. AZ::u32 AnimGraphSingleNumberParameterHandler::GetHandlerName() const
  250. {
  251. return AZ_CRC("AnimGraphNumberParameter", 0x8023eba9);
  252. }
  253. QWidget* AnimGraphSingleNumberParameterHandler::CreateGUI(QWidget* parent)
  254. {
  255. AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, true);
  256. picker->SetFilterTypes({
  257. azrtti_typeid<BoolParameter>(),
  258. azrtti_typeid<FloatSliderParameter>(),
  259. azrtti_typeid<FloatSpinnerParameter>(),
  260. azrtti_typeid<IntSliderParameter>(),
  261. azrtti_typeid<IntSpinnerParameter>(),
  262. azrtti_typeid<TagParameter>()});
  263. connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker]([[maybe_unused]] const AZStd::vector<AZStd::string>& newParameters)
  264. {
  265. AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(
  266. &AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestWrite, picker);
  267. });
  268. return picker;
  269. }
  270. //---------------------------------------------------------------------------------------------------------------------------------------------------------
  271. AZ_CLASS_ALLOCATOR_IMPL(AnimGraphSingleVector2ParameterHandler, EditorAllocator);
  272. AnimGraphSingleVector2ParameterHandler::AnimGraphSingleVector2ParameterHandler()
  273. : AnimGraphSingleParameterHandler()
  274. {
  275. }
  276. AZ::u32 AnimGraphSingleVector2ParameterHandler::GetHandlerName() const
  277. {
  278. return AZ_CRC("AnimGraphVector2Parameter", 0x151dfae7);
  279. }
  280. QWidget* AnimGraphSingleVector2ParameterHandler::CreateGUI(QWidget* parent)
  281. {
  282. AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, true);
  283. picker->SetFilterTypes({azrtti_typeid<Vector2Parameter>()});
  284. connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker]([[maybe_unused]] const AZStd::vector<AZStd::string>& newParameters) {
  285. AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(
  286. &AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestWrite, picker);
  287. });
  288. return picker;
  289. }
  290. //---------------------------------------------------------------------------------------------------------------------------------------------------------
  291. AnimGraphMultipleParameterHandler::AnimGraphMultipleParameterHandler()
  292. : QObject()
  293. , AzToolsFramework::PropertyHandler<AZStd::vector<AZStd::string>, AnimGraphParameterPicker>()
  294. , m_animGraph(nullptr)
  295. {
  296. }
  297. AZ::u32 AnimGraphMultipleParameterHandler::GetHandlerName() const
  298. {
  299. return AZ_CRC("AnimGraphMultipleParameter", 0x4d5e082c);
  300. }
  301. QWidget* AnimGraphMultipleParameterHandler::CreateGUI(QWidget* parent)
  302. {
  303. AnimGraphParameterPicker* picker = aznew AnimGraphParameterPicker(parent, false);
  304. connect(picker, &AnimGraphParameterPicker::ParametersChanged, this, [picker]([[maybe_unused]] const AZStd::vector<AZStd::string>& newParameters)
  305. {
  306. AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(
  307. &AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestWrite, picker);
  308. });
  309. return picker;
  310. }
  311. void AnimGraphMultipleParameterHandler::ConsumeAttribute(AnimGraphParameterPicker* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
  312. {
  313. if (attrib == AZ::Edit::Attributes::ReadOnly)
  314. {
  315. bool value;
  316. if (attrValue->Read<bool>(value))
  317. {
  318. GUI->setEnabled(!value);
  319. }
  320. }
  321. if (attrib == AZ_CRC("AnimGraph", 0x0d53d4b3))
  322. {
  323. attrValue->Read<AnimGraph*>(m_animGraph);
  324. GUI->SetAnimGraph(m_animGraph);
  325. }
  326. }
  327. void AnimGraphMultipleParameterHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, AnimGraphParameterPicker* GUI, property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
  328. {
  329. instance = GUI->GetParameterNames();
  330. }
  331. bool AnimGraphMultipleParameterHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, AnimGraphParameterPicker* GUI, const property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
  332. {
  333. QSignalBlocker signalBlocker(GUI);
  334. GUI->InitializeParameterNames(instance);
  335. return true;
  336. }
  337. } // namespace EMotionFX