EventDataHandler.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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/QtMetaTypes.h>
  9. #include <Editor/PropertyWidgets/EventDataHandler.h>
  10. #include <QAbstractListModel>
  11. #include <QVBoxLayout>
  12. namespace EMotionFX
  13. {
  14. AZ_CLASS_ALLOCATOR_IMPL(EventDataTypeSelectionWidget, EditorAllocator)
  15. AZ_CLASS_ALLOCATOR_IMPL(EventDataHandler, EditorAllocator)
  16. class EventDataTypeSelectionWidget::EventDataTypesModel
  17. : public QAbstractListModel
  18. {
  19. public:
  20. enum
  21. {
  22. UuidRole = Qt::UserRole
  23. };
  24. EventDataTypesModel();
  25. EventDataTypesModel(const EventDataTypesModel&) = delete;
  26. EventDataTypesModel(EventDataTypesModel&&) = delete;
  27. static AZStd::shared_ptr<EventDataTypesModel> Get();
  28. int rowCount(const QModelIndex& parent) const override;
  29. QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
  30. private:
  31. static AZStd::weak_ptr<EventDataTypesModel> dataTypesModel;
  32. AZStd::vector<AZStd::pair<QString, AZ::Uuid> > m_eventDataClassNames;
  33. };
  34. AZStd::weak_ptr<EventDataTypeSelectionWidget::EventDataTypesModel> EventDataTypeSelectionWidget::EventDataTypesModel::dataTypesModel;
  35. EventDataTypeSelectionWidget::EventDataTypesModel::EventDataTypesModel()
  36. {
  37. AZ::SerializeContext* context;
  38. AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
  39. m_eventDataClassNames.emplace_back("<none>", AZ::Uuid::CreateNull());
  40. context->EnumerateDerived<EventData>(
  41. [this](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&)
  42. {
  43. // Only add this type if it has the "Creatable" class attribute
  44. // set to true
  45. const AZ::Edit::ClassData* editData = classData->m_editData;
  46. if (!editData)
  47. {
  48. return true;
  49. }
  50. for (const AZ::Edit::ElementData& element : editData->m_elements)
  51. {
  52. if (element.m_elementId == AZ::Edit::ClassElements::EditorData)
  53. {
  54. const AZ::Attribute* attribute = AZ::FindAttribute(AZ_CRC("Creatable", 0x47bff8c4), element.m_attributes);
  55. if (!attribute)
  56. {
  57. continue;
  58. }
  59. const AZ::AttributeContainerType<bool>* typedAttribute = static_cast<const AZ::AttributeContainerType<bool>*>(attribute);
  60. // instance is nullptr because this is a class-level
  61. // attribute and not one on a specific instance
  62. if (typedAttribute->Get(/*instance =*/ nullptr))
  63. {
  64. m_eventDataClassNames.emplace_back(editData->m_name, classData->m_typeId);
  65. break;
  66. }
  67. }
  68. }
  69. return true;
  70. }
  71. );
  72. }
  73. AZStd::shared_ptr<EventDataTypeSelectionWidget::EventDataTypesModel> EventDataTypeSelectionWidget::EventDataTypesModel::Get()
  74. {
  75. AZStd::shared_ptr<EventDataTypesModel> model;
  76. if (dataTypesModel.expired())
  77. {
  78. model = AZStd::make_shared<EventDataTypesModel>();
  79. }
  80. else
  81. {
  82. model = dataTypesModel.lock();
  83. }
  84. return model;
  85. }
  86. int EventDataTypeSelectionWidget::EventDataTypesModel::rowCount(const QModelIndex& parent) const
  87. {
  88. if (parent.isValid())
  89. {
  90. return 0;
  91. }
  92. return static_cast<int>(m_eventDataClassNames.size());
  93. }
  94. QVariant EventDataTypeSelectionWidget::EventDataTypesModel::data(const QModelIndex& index, int role) const
  95. {
  96. if (!index.isValid())
  97. {
  98. return QVariant();
  99. }
  100. if (role == Qt::DisplayRole)
  101. {
  102. return m_eventDataClassNames[index.row()].first;
  103. }
  104. else if (role == UuidRole)
  105. {
  106. return QVariant::fromValue(m_eventDataClassNames[index.row()].second);
  107. }
  108. return QVariant();
  109. }
  110. EventDataTypeSelectionWidget::EventDataTypeSelectionWidget(QWidget* parent)
  111. : QWidget(parent)
  112. {
  113. m_comboBox = new QComboBox(this);
  114. m_model = EventDataTypesModel::Get();
  115. m_comboBox->setModel(m_model.get());
  116. QVBoxLayout* layout = new QVBoxLayout(this);
  117. layout->addWidget(m_comboBox);
  118. layout->setContentsMargins(0, 0, 0, 0);
  119. layout->setSpacing(0);
  120. connect(
  121. m_comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
  122. this, &EventDataTypeSelectionWidget::currentIndexChanged
  123. );
  124. }
  125. const AZ::Uuid EventDataTypeSelectionWidget::GetSelectedClass() const
  126. {
  127. return m_comboBox->currentData(EventDataTypesModel::UuidRole).value<AZ::Uuid>();
  128. }
  129. void EventDataTypeSelectionWidget::SetSelectedClass(const AZ::Uuid& classId)
  130. {
  131. const int newRow = m_comboBox->findData(
  132. QVariant::fromValue(classId),
  133. EventDataTypesModel::UuidRole,
  134. Qt::MatchExactly
  135. );
  136. m_comboBox->setCurrentIndex(newRow);
  137. }
  138. AZ::u32 EventDataHandler::GetHandlerName() const
  139. {
  140. return AZ_CRC("EMotionFX::EventData", 0xca242382);
  141. }
  142. QWidget* EventDataHandler::CreateGUI(QWidget* parent)
  143. {
  144. EventDataTypeSelectionWidget* widget = aznew EventDataTypeSelectionWidget(parent);
  145. connect(widget, &EventDataTypeSelectionWidget::currentIndexChanged, this, [widget]()
  146. {
  147. AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestWrite, widget);
  148. });
  149. return widget;
  150. }
  151. void EventDataHandler::ConsumeAttribute([[maybe_unused]] EventDataTypeSelectionWidget* widget, [[maybe_unused]] AZ::u32 attrib, [[maybe_unused]] AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
  152. {
  153. }
  154. void EventDataHandler::WriteGUIValuesIntoProperty(size_t /*index*/, EventDataTypeSelectionWidget* selectionWidget, AZStd::shared_ptr<const EventData>& instance, AzToolsFramework::InstanceDataNode* /*node*/)
  155. {
  156. const AZ::Uuid& newTypeId = selectionWidget->GetSelectedClass();
  157. if (azrtti_typeid(instance.get()) == newTypeId)
  158. {
  159. return;
  160. }
  161. if (newTypeId == AZ::Uuid::CreateNull())
  162. {
  163. instance = nullptr;
  164. }
  165. else
  166. {
  167. AZ::SerializeContext* context;
  168. AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
  169. const AZ::SerializeContext::ClassData* classData = context->FindClassData(newTypeId);
  170. instance.reset(static_cast<EMotionFX::EventData*>(classData->m_factory->Create(classData->m_name)));
  171. // Deduplicate the event data
  172. instance = GetEMotionFX().GetEventManager()->FindEventData(instance);
  173. }
  174. AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::Bus::Events::RequestRefresh, AzToolsFramework::Refresh_EntireTree);
  175. }
  176. bool EventDataHandler::ReadValuesIntoGUI(size_t /*index*/, EventDataTypeSelectionWidget* selectionWidget, const AZStd::shared_ptr<const EventData>& instance, AzToolsFramework::InstanceDataNode* /*node*/)
  177. {
  178. if (instance)
  179. {
  180. selectionWidget->SetSelectedClass(azrtti_typeid(instance.get()));
  181. }
  182. return true;
  183. }
  184. } // namespace EMotionFX
  185. #include <Source/Editor/PropertyWidgets/moc_EventDataHandler.cpp>