3
0

EBusHandlerActionMenu.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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 <QEvent>
  9. #include <QLineEdit>
  10. #include <QListView>
  11. #include <QWidgetAction>
  12. #include <QKeyEvent>
  13. #include <GraphCanvas/Components/SceneBus.h>
  14. #include <GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h>
  15. #include "Editor/View/Windows/EBusHandlerActionMenu.h"
  16. #include <Editor/View/Windows/ui_ebushandleractionlistwidget.h>
  17. #include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
  18. #include <Editor/Translation/TranslationHelper.h>
  19. #include <Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h>
  20. #include <Editor/View/Widgets/NodePalette/EBusNodePaletteTreeItemTypes.h>
  21. #include <ScriptCanvas/Bus/RequestBus.h>
  22. namespace ScriptCanvasEditor
  23. {
  24. /////////////////////////////////
  25. // EBusHandlerActionSourceModel
  26. /////////////////////////////////
  27. EBusHandlerActionSourceModel::EBusHandlerActionSourceModel(QObject* parent)
  28. : QAbstractListModel(parent)
  29. {
  30. }
  31. EBusHandlerActionSourceModel::~EBusHandlerActionSourceModel()
  32. {
  33. }
  34. int EBusHandlerActionSourceModel::rowCount([[maybe_unused]] const QModelIndex& parent) const
  35. {
  36. return static_cast<int>(m_actionItems.size());
  37. }
  38. QVariant EBusHandlerActionSourceModel::data(const QModelIndex& index, int role) const
  39. {
  40. int row = index.row();
  41. const EBusHandlerActionItem& actionItem = GetActionItemForRow(row);
  42. switch (role)
  43. {
  44. case Qt::DisplayRole:
  45. return actionItem.m_displayName;
  46. case Qt::CheckStateRole:
  47. if (actionItem.m_active)
  48. {
  49. return Qt::Checked;
  50. }
  51. else
  52. {
  53. return Qt::Unchecked;
  54. }
  55. break;
  56. default:
  57. break;
  58. }
  59. return QVariant();
  60. }
  61. QVariant EBusHandlerActionSourceModel::headerData([[maybe_unused]] int section, [[maybe_unused]] Qt::Orientation orientation, [[maybe_unused]] int role) const
  62. {
  63. return QVariant();
  64. }
  65. Qt::ItemFlags EBusHandlerActionSourceModel::flags([[maybe_unused]] const QModelIndex &index) const
  66. {
  67. return Qt::ItemFlags(Qt::ItemIsUserCheckable
  68. | Qt::ItemIsEnabled
  69. | Qt::ItemIsSelectable);
  70. }
  71. void EBusHandlerActionSourceModel::OnItemClicked(const QModelIndex& index)
  72. {
  73. EBusHandlerActionItem& actionItem = GetActionItemForRow(index.row());
  74. actionItem.m_active = !actionItem.m_active;
  75. UpdateEBusItem(actionItem);
  76. emit dataChanged(index, index);
  77. }
  78. void EBusHandlerActionSourceModel::SetEBusNodeSource(const AZ::EntityId& ebusNode)
  79. {
  80. layoutAboutToBeChanged();
  81. m_actionItems.clear();
  82. m_ebusNode = ebusNode;
  83. EBusHandlerNodeDescriptorRequestBus::EventResult(m_busName, m_ebusNode, &EBusHandlerNodeDescriptorRequests::GetBusName);
  84. AZStd::vector< HandlerEventConfiguration > eventConfigurations;
  85. EBusHandlerNodeDescriptorRequestBus::EventResult(eventConfigurations, m_ebusNode, &EBusHandlerNodeDescriptorRequests::GetEventConfigurations);
  86. m_actionItems.resize(eventConfigurations.size());
  87. for (unsigned int i=0; i < eventConfigurations.size(); ++i)
  88. {
  89. EBusHandlerActionItem& actionItem = m_actionItems[i];
  90. actionItem.m_name = QString(eventConfigurations[i].m_eventName.c_str());
  91. actionItem.m_eventId = eventConfigurations[i].m_eventId;
  92. GraphCanvas::TranslationKey key;
  93. key << "EBusHandler" << m_busName.c_str() << "methods" << eventConfigurations[i].m_eventName << "details";
  94. GraphCanvas::TranslationRequests::Details details;
  95. details.m_name = actionItem.m_name.toUtf8().data();
  96. GraphCanvas::TranslationRequestBus::BroadcastResult(details, &GraphCanvas::TranslationRequests::GetDetails, key, details);
  97. actionItem.m_displayName = QString(details.m_name.c_str());
  98. actionItem.m_index = i;
  99. EBusHandlerNodeDescriptorRequestBus::EventResult(actionItem.m_active, ebusNode, &EBusHandlerNodeDescriptorRequests::ContainsEvent, eventConfigurations[i].m_eventId);
  100. }
  101. layoutChanged();
  102. }
  103. EBusHandlerActionItem& EBusHandlerActionSourceModel::GetActionItemForRow(int row)
  104. {
  105. return const_cast<EBusHandlerActionItem&>(static_cast<const EBusHandlerActionSourceModel*>(this)->GetActionItemForRow(row));
  106. }
  107. const EBusHandlerActionItem& EBusHandlerActionSourceModel::GetActionItemForRow(int row) const
  108. {
  109. if (row >= 0 && row < m_actionItems.size())
  110. {
  111. return m_actionItems[row];
  112. }
  113. else
  114. {
  115. static EBusHandlerActionItem invalidItem;
  116. AZ_Warning("Script Canvas", false, "EBus Handler Action Source model being asked for invalid item.");
  117. return invalidItem;
  118. }
  119. }
  120. void EBusHandlerActionSourceModel::UpdateEBusItem(EBusHandlerActionItem& actionItem)
  121. {
  122. AZ::EntityId graphCanvasGraphId;
  123. GraphCanvas::SceneMemberRequestBus::EventResult(graphCanvasGraphId, m_ebusNode, &GraphCanvas::SceneMemberRequests::GetScene);
  124. ScriptCanvas::EBusEventId eventId(actionItem.m_eventId);
  125. if (actionItem.m_active)
  126. {
  127. AZ::Vector2 dummyPosition(0, 0);
  128. NodeIdPair idPair;
  129. if (ScriptEventReceiverNodeDescriptorRequestBus::FindFirstHandler(m_ebusNode) != nullptr)
  130. {
  131. AZ::Data::AssetId assetId;
  132. ScriptEventReceiverNodeDescriptorRequestBus::EventResult(assetId, m_ebusNode, &ScriptEventReceiverNodeDescriptorRequests::GetAssetId);
  133. AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset = AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(assetId, AZ::Data::AssetLoadBehavior::Default);
  134. asset.BlockUntilLoadComplete();
  135. if (asset.IsReady())
  136. {
  137. const ScriptEvents::ScriptEvent& definition = asset.Get()->m_definition;
  138. ScriptEvents::Method methodDefinition;
  139. if (definition.FindMethod(actionItem.m_name.toUtf8().data(), methodDefinition))
  140. {
  141. eventId = methodDefinition.GetEventId();
  142. CreateScriptEventsReceiverMimeEvent mimeEvent(asset.GetId(), methodDefinition);
  143. idPair = mimeEvent.CreateEventNode(graphCanvasGraphId, dummyPosition);
  144. }
  145. }
  146. }
  147. else
  148. {
  149. CreateEBusHandlerEventMimeEvent mimeEvent(m_busName, actionItem.m_name.toUtf8().data(), actionItem.m_eventId);
  150. idPair = mimeEvent.CreateEventNode(graphCanvasGraphId, dummyPosition);
  151. }
  152. GraphCanvas::WrappedNodeConfiguration configuration;
  153. EBusHandlerNodeDescriptorRequestBus::EventResult(configuration, m_ebusNode, &EBusHandlerNodeDescriptorRequests::GetEventConfiguration, eventId);
  154. GraphCanvas::WrapperNodeRequestBus::Event(m_ebusNode, &GraphCanvas::WrapperNodeRequests::WrapNode, idPair.m_graphCanvasId, configuration);
  155. ScriptCanvas::ScriptCanvasId scriptCanvasId;
  156. GeneralRequestBus::BroadcastResult(scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
  157. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, scriptCanvasId);
  158. }
  159. else
  160. {
  161. AZ::EntityId nodeId;
  162. EBusHandlerNodeDescriptorRequestBus::EventResult(nodeId, m_ebusNode, &EBusHandlerNodeDescriptorRequests::FindEventNodeId, eventId);
  163. if (nodeId.IsValid())
  164. {
  165. AZStd::unordered_set<AZ::EntityId> deleteNodes;
  166. deleteNodes.insert(nodeId);
  167. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, deleteNodes);
  168. actionItem.m_active = false;
  169. }
  170. }
  171. }
  172. //////////////////////////////////////
  173. // EBusHandlerActionFilterProxyModel
  174. //////////////////////////////////////
  175. EBusHandlerActionFilterProxyModel::EBusHandlerActionFilterProxyModel(QObject* parent)
  176. : QSortFilterProxyModel(parent)
  177. {
  178. m_regex.setCaseSensitivity(Qt::CaseInsensitive);
  179. }
  180. void EBusHandlerActionFilterProxyModel::SetFilterSource(QLineEdit* lineEdit)
  181. {
  182. if (lineEdit)
  183. {
  184. QObject::connect(lineEdit, &QLineEdit::textChanged, this, &EBusHandlerActionFilterProxyModel::OnFilterChanged);
  185. }
  186. }
  187. bool EBusHandlerActionFilterProxyModel::filterAcceptsRow(int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const
  188. {
  189. EBusHandlerActionSourceModel* sourceModel = static_cast<EBusHandlerActionSourceModel*>(this->sourceModel());
  190. const EBusHandlerActionItem& actionItem = sourceModel->GetActionItemForRow(sourceRow);
  191. return actionItem.m_name.lastIndexOf(m_regex) >= 0;
  192. }
  193. void EBusHandlerActionFilterProxyModel::OnFilterChanged(const QString& text)
  194. {
  195. m_filter = text;
  196. m_regex.setPattern(text);
  197. invalidate();
  198. layoutChanged();
  199. }
  200. //////////////////////////
  201. // EBusHandlerActionMenu
  202. //////////////////////////
  203. EBusHandlerActionMenu::EBusHandlerActionMenu(QWidget* parent)
  204. : QMenu(parent)
  205. {
  206. QWidgetAction* actionWidget = new QWidgetAction(this);
  207. QWidget* listWidget = new QWidget(this);
  208. m_listWidget = new Ui::EBusHandlerActionListWidget();
  209. m_listWidget->setupUi(listWidget);
  210. actionWidget->setDefaultWidget(listWidget);
  211. addAction(actionWidget);
  212. connect(this, &QMenu::aboutToShow, this, &EBusHandlerActionMenu::ResetFilter);
  213. m_model = aznew EBusHandlerActionSourceModel(this);
  214. m_proxyModel = aznew EBusHandlerActionFilterProxyModel(this);
  215. m_proxyModel->setSourceModel(m_model);
  216. m_proxyModel->SetFilterSource(m_listWidget->searchFilter);
  217. m_listWidget->actionListView->setModel(m_proxyModel);
  218. QObject::connect(m_listWidget->actionListView, &QListView::clicked, this, &EBusHandlerActionMenu::ItemClicked);
  219. }
  220. void EBusHandlerActionMenu::SetEbusHandlerNode(const AZ::EntityId& ebusWrapperNode)
  221. {
  222. m_proxyModel->layoutAboutToBeChanged();
  223. m_model->SetEBusNodeSource(ebusWrapperNode);
  224. m_proxyModel->layoutChanged();
  225. m_proxyModel->invalidate();
  226. }
  227. void EBusHandlerActionMenu::ResetFilter()
  228. {
  229. m_listWidget->actionListView->selectionModel()->clearSelection();
  230. m_listWidget->searchFilter->setText("");
  231. }
  232. void EBusHandlerActionMenu::ItemClicked(const QModelIndex& modelIndex)
  233. {
  234. QModelIndex sourceIndex = m_proxyModel->mapToSource(modelIndex);
  235. m_model->OnItemClicked(sourceIndex);
  236. }
  237. void EBusHandlerActionMenu::keyPressEvent(QKeyEvent* keyEvent)
  238. {
  239. // Only pass along escape keys(don't want any sort of selection state with this menu)
  240. if (keyEvent->key() == Qt::Key_Escape)
  241. {
  242. QMenu::keyPressEvent(keyEvent);
  243. }
  244. }
  245. #include <Editor/View/Windows/moc_EBusHandlerActionMenu.cpp>
  246. }