ScriptCanvasVariableDataInterface.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  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. #pragma once
  9. #include <AzCore/PlatformDef.h>
  10. AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option")
  11. #include <QString>
  12. AZ_POP_DISABLE_WARNING
  13. #include <GraphCanvas/Components/Connections/ConnectionBus.h>
  14. #include <GraphCanvas/Components/NodePropertyDisplay/ComboBoxDataInterface.h>
  15. #include <GraphCanvas/Components/Nodes/NodeTitleBus.h>
  16. #include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
  17. #include <GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h>
  18. #include <GraphCanvas/Utils/QtMimeUtils.h>
  19. #include <Editor/Include/ScriptCanvas/Bus/EditorSceneVariableManagerBus.h>
  20. #include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
  21. #include <Editor/Include/ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
  22. #include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
  23. #include "ScriptCanvasDataInterface.h"
  24. #include <ScriptCanvas/Core/Slot.h>
  25. #include <ScriptCanvas/Core/Node.h>
  26. #include <ScriptCanvas/Variable/VariableBus.h>
  27. #include <ScriptCanvas/Utils/DataUtils.h>
  28. namespace ScriptCanvasEditor
  29. {
  30. class VariableComboBoxDataModel
  31. : public GraphCanvas::GraphCanvasListComboBoxModel<ScriptCanvas::VariableId>
  32. , public ScriptCanvas::GraphVariableManagerNotificationBus::Handler
  33. , public GeneralEditorNotificationBus::Handler
  34. {
  35. public:
  36. AZ_CLASS_ALLOCATOR(VariableComboBoxDataModel, AZ::SystemAllocator);
  37. VariableComboBoxDataModel()
  38. {
  39. }
  40. ~VariableComboBoxDataModel() override
  41. {
  42. ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusDisconnect();
  43. GeneralEditorNotificationBus::Handler::BusDisconnect();
  44. }
  45. void Activate(const ScriptCanvas::ScriptCanvasId& scriptCanvasId)
  46. {
  47. m_scriptCanvasId = scriptCanvasId;
  48. if (m_scriptCanvasId.IsValid())
  49. {
  50. GeneralEditorNotificationBus::Handler::BusConnect(m_scriptCanvasId);
  51. if (!IsInUndo())
  52. {
  53. FinalizeActivation();
  54. }
  55. }
  56. }
  57. // ScriptCanvas::GraphVariableManagerNotifications
  58. void OnVariableAddedToGraph(const ScriptCanvas::VariableId& variableId, AZStd::string_view variableName) override
  59. {
  60. QString displayName = QString::fromUtf8(variableName.data(), static_cast<int>(variableName.size()));
  61. AddElement(variableId, displayName);
  62. }
  63. void OnVariableRemovedFromGraph(const ScriptCanvas::VariableId& variableId, [[maybe_unused]] AZStd::string_view variableName) override
  64. {
  65. RemoveElement(variableId);
  66. }
  67. void OnVariableNameChangedInGraph(const ScriptCanvas::VariableId& variableId, AZStd::string_view variableName) override
  68. {
  69. RemoveElement(variableId);
  70. OnVariableAddedToGraph(variableId, variableName);
  71. }
  72. ////
  73. // GeneralEditorNotifications
  74. void OnUndoRedoBegin() override
  75. {
  76. ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusDisconnect();
  77. }
  78. void OnUndoRedoEnd() override
  79. {
  80. FinalizeActivation();
  81. }
  82. ////
  83. const ScriptCanvas::GraphVariable* GetGraphVariable(const ScriptCanvas::VariableId& variableId) const
  84. {
  85. const ScriptCanvas::GraphVariable* graphVariable = nullptr;
  86. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, variableId);
  87. return graphVariable;
  88. }
  89. const ScriptCanvas::GraphVariable* GetGraphVariableForIndex(const QModelIndex& index) const
  90. {
  91. return GetGraphVariable(GetValueForIndex(index));
  92. }
  93. private:
  94. void FinalizeActivation()
  95. {
  96. if (m_scriptCanvasId.IsValid())
  97. {
  98. ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusConnect(m_scriptCanvasId);
  99. const ScriptCanvas::GraphVariableMapping* graphVariables = nullptr;
  100. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariables, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::GetVariables);
  101. if (graphVariables)
  102. {
  103. ClearElements();
  104. for (auto variablePair : (*graphVariables))
  105. {
  106. OnVariableAddedToGraph(variablePair.first, variablePair.second.GetVariableName());
  107. }
  108. }
  109. }
  110. }
  111. bool IsInUndo() const
  112. {
  113. bool isInUndo = false;
  114. GeneralRequestBus::BroadcastResult(isInUndo, &GeneralRequests::IsScriptCanvasInUndoRedo, m_scriptCanvasId);
  115. return isInUndo;
  116. }
  117. ScriptCanvas::ScriptCanvasId m_scriptCanvasId;
  118. };
  119. class VariableTypeComboBoxFilterModel
  120. : public GraphCanvas::GraphCanvasSortFilterComboBoxProxyModel
  121. {
  122. public:
  123. AZ_CLASS_ALLOCATOR(VariableTypeComboBoxFilterModel, AZ::SystemAllocator);
  124. VariableTypeComboBoxFilterModel(const VariableComboBoxDataModel* sourceModel, ScriptCanvas::Slot* slot = nullptr)
  125. : m_sourceModel(sourceModel)
  126. , m_slotFilter(slot)
  127. {
  128. SetModelInterface(const_cast<VariableComboBoxDataModel*>(sourceModel));
  129. }
  130. void SetSlotFilter(ScriptCanvas::Slot* slotFilter)
  131. {
  132. if (m_slotFilter != slotFilter)
  133. {
  134. m_slotFilter = slotFilter;
  135. if (sourceModel())
  136. {
  137. QSortFilterProxyModel::invalidateFilter();
  138. }
  139. }
  140. }
  141. void RefreshFilter()
  142. {
  143. if (sourceModel())
  144. {
  145. QSortFilterProxyModel::invalidateFilter();
  146. }
  147. }
  148. bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
  149. {
  150. if (m_slotFilter == nullptr)
  151. {
  152. return true;
  153. }
  154. QModelIndex sourceIndex = m_sourceModel->index(sourceRow, VariableComboBoxDataModel::ColumnIndex::Name, sourceParent);
  155. const ScriptCanvas::GraphVariable* variable = m_sourceModel->GetGraphVariableForIndex(sourceIndex);
  156. if (variable)
  157. {
  158. auto dataType = variable->GetDatum()->GetType();
  159. return m_slotFilter->GetNode()->IsValidTypeForSlot(m_slotFilter->GetId(), dataType).IsSuccess();
  160. }
  161. return false;
  162. }
  163. ScriptCanvas::VariableId GetValueForIndex(const QModelIndex& modelIndex) const
  164. {
  165. return m_sourceModel->GetValueForIndex(RemapToSourceIndex(modelIndex));
  166. }
  167. QModelIndex GetIndexForValue(const ScriptCanvas::VariableId& variableId) const
  168. {
  169. return RemapFromSourceIndex(m_sourceModel->GetIndexForValue(variableId));
  170. }
  171. const QString& GetDisplayName(const ScriptCanvas::VariableId& variableId) const
  172. {
  173. return m_sourceModel->GetNameForValue(variableId);
  174. }
  175. const ScriptCanvas::GraphVariable* GetGraphVariable(const ScriptCanvas::VariableId& variableId) const
  176. {
  177. return m_sourceModel->GetGraphVariable(variableId);
  178. }
  179. private:
  180. const VariableComboBoxDataModel* m_sourceModel;
  181. ScriptCanvas::Slot* m_slotFilter;
  182. };
  183. class ScriptCanvasGraphScopedVariableDataInterface
  184. : public ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>
  185. , public ScriptCanvas::VariableNotificationBus::Handler
  186. , public AZ::SystemTickBus::Handler
  187. {
  188. public:
  189. AZ_CLASS_ALLOCATOR(ScriptCanvasGraphScopedVariableDataInterface, AZ::SystemAllocator);
  190. ScriptCanvasGraphScopedVariableDataInterface(const VariableComboBoxDataModel* variableDataModel, const AZ::EntityId& scriptCanvasGraphId, const AZ::EntityId& scriptCanvasNodeId, const ScriptCanvas::SlotId& scriptCanvasSlotId)
  191. : ScriptCanvasDataInterface(scriptCanvasNodeId, scriptCanvasSlotId)
  192. , m_scriptCanvasGraphId(scriptCanvasGraphId)
  193. , m_variableTypeModel(variableDataModel)
  194. {
  195. RegisterBus();
  196. }
  197. ~ScriptCanvasGraphScopedVariableDataInterface()
  198. {
  199. AZ::SystemTickBus::Handler::BusDisconnect();
  200. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  201. }
  202. // SystemTickBus
  203. void OnSystemTick() override
  204. {
  205. AZ::SystemTickBus::Handler::BusDisconnect();
  206. AssignIndex(m_variableTypeModel.GetDefaultIndex());
  207. SignalValueChanged();
  208. }
  209. ////
  210. // VariableNotificationBus
  211. void OnVariableRenamed([[maybe_unused]] AZStd::string_view newName) override
  212. {
  213. SignalValueChanged();
  214. }
  215. void OnVariableRemoved() override
  216. {
  217. // Delay this since its possible the model hasn't updated yet
  218. AZ::SystemTickBus::Handler::BusConnect();
  219. }
  220. ////
  221. // ScriptCanvas::NodeNotificationsBus::Handler
  222. void OnSlotInputChanged(const ScriptCanvas::SlotId& slotId) override
  223. {
  224. if (slotId == GetSlotId())
  225. {
  226. RegisterBus();
  227. }
  228. ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>::OnSlotInputChanged(slotId);
  229. }
  230. ////
  231. // GraphCanvas::ComboBoxModelInterface
  232. GraphCanvas::ComboBoxItemModelInterface* GetItemInterface() override
  233. {
  234. return &m_variableTypeModel;
  235. }
  236. void AssignIndex(const QModelIndex& index) override
  237. {
  238. if (!index.isValid())
  239. {
  240. return;
  241. }
  242. ScriptCanvas::VariableId variableId = m_variableTypeModel.GetValueForIndex(index);
  243. SetVariableId(variableId);
  244. }
  245. QModelIndex GetAssignedIndex() const override
  246. {
  247. const ScriptCanvas::Datum* datum = GetSlotObject();
  248. const ScriptCanvas::GraphScopedVariableId* variableId = (datum ? datum->GetAs<ScriptCanvas::GraphScopedVariableId>() : nullptr);
  249. if (variableId)
  250. {
  251. return m_variableTypeModel.GetIndexForValue(variableId->m_identifier);
  252. }
  253. return QModelIndex();
  254. }
  255. // Returns the string used to display the currently selected value[Used in the non-editable format]
  256. QString GetDisplayString() const override
  257. {
  258. const ScriptCanvas::Datum* datum = GetSlotObject();
  259. const ScriptCanvas::GraphScopedVariableId* variableId = (datum ? datum->GetAs<ScriptCanvas::GraphScopedVariableId>() : nullptr);
  260. if (variableId)
  261. {
  262. return m_variableTypeModel.GetDisplayName(variableId->m_identifier);
  263. }
  264. return ComboBoxDataInterface::GetDisplayString();
  265. }
  266. void SetVariableId(const ScriptCanvas::VariableId& variableId)
  267. {
  268. ScriptCanvas::GraphScopedVariableId scopedVariableId;
  269. scopedVariableId.m_identifier = variableId;
  270. ScriptCanvas::ModifiableDatumView datumView;
  271. ModifySlotObject(datumView);
  272. datumView.SetAs<ScriptCanvas::GraphScopedVariableId>(scopedVariableId);
  273. if (ScriptCanvas::VariableNotificationBus::Handler::BusIsConnected())
  274. {
  275. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  276. }
  277. scopedVariableId.m_scriptCanvasId = GetScriptCanvasId();
  278. ScriptCanvas::VariableNotificationBus::Handler::BusConnect(scopedVariableId);
  279. PostUndoPoint();
  280. PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
  281. }
  282. // DataInterfaceOverrides
  283. bool EnableDropHandling() const override
  284. {
  285. return true;
  286. }
  287. AZ::Outcome<GraphCanvas::DragDropState> ShouldAcceptMimeData(const QMimeData* mimeData) override
  288. {
  289. if (mimeData->hasFormat(GraphCanvas::k_ReferenceMimeType))
  290. {
  291. return AZ::Success(GraphCanvas::DragDropState::Valid);
  292. }
  293. return AZ::Failure();
  294. }
  295. bool HandleMimeData(const QMimeData* mimeData) override
  296. {
  297. ScriptCanvas::VariableId variableId = GraphCanvas::QtMimeUtils::ExtractTypeFromMimeData<ScriptCanvas::VariableId>(mimeData, GraphCanvas::k_ReferenceMimeType);
  298. SetVariableId(variableId);
  299. return true;
  300. }
  301. //
  302. private:
  303. void RegisterBus()
  304. {
  305. if (ScriptCanvas::VariableNotificationBus::Handler::BusIsConnected())
  306. {
  307. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  308. }
  309. const ScriptCanvas::Datum* datum = GetSlotObject();
  310. const ScriptCanvas::GraphScopedVariableId* variableId = (datum ? datum->GetAs<ScriptCanvas::GraphScopedVariableId>() : nullptr);
  311. if (variableId)
  312. {
  313. ScriptCanvas::GraphScopedVariableId scopedVariableId = (*variableId);
  314. scopedVariableId.m_scriptCanvasId = GetScriptCanvasId();
  315. ScriptCanvas::VariableNotificationBus::Handler::BusConnect(scopedVariableId);
  316. }
  317. }
  318. VariableTypeComboBoxFilterModel m_variableTypeModel;
  319. AZ::EntityId m_scriptCanvasGraphId;
  320. };
  321. class ScriptCanvasVariableReferenceDataInterface
  322. : public ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>
  323. , public ScriptCanvas::VariableNotificationBus::Handler
  324. , public ScriptCanvas::EndpointNotificationBus::Handler
  325. , public AZ::SystemTickBus::Handler
  326. {
  327. public:
  328. AZ_CLASS_ALLOCATOR(ScriptCanvasVariableReferenceDataInterface, AZ::SystemAllocator);
  329. ScriptCanvasVariableReferenceDataInterface(const VariableComboBoxDataModel* variableDataModel, const AZ::EntityId& scriptCanvasGraphId, const AZ::EntityId& scriptCanvasNodeId, const ScriptCanvas::SlotId& scriptCanvasSlotId)
  330. : ScriptCanvasDataInterface(scriptCanvasNodeId, scriptCanvasSlotId)
  331. , m_scriptCanvasGraphId(scriptCanvasGraphId)
  332. , m_variableTypeModel(variableDataModel)
  333. {
  334. ScriptCanvas::Slot* slot = GetSlot();
  335. if (slot)
  336. {
  337. m_variableTypeModel.SetSlotFilter(slot);
  338. ScriptCanvas::VariableId variableId = slot->GetVariableReference();
  339. if (variableId.IsValid())
  340. {
  341. ScriptCanvas::VariableNotificationBus::Handler::BusConnect(ScriptCanvas::GraphScopedVariableId(m_scriptCanvasGraphId, variableId));
  342. }
  343. }
  344. ScriptCanvas::EndpointNotificationBus::Handler::BusConnect(ScriptCanvas::Endpoint(scriptCanvasNodeId, scriptCanvasSlotId));
  345. }
  346. ~ScriptCanvasVariableReferenceDataInterface()
  347. {
  348. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  349. ScriptCanvas::EndpointNotificationBus::Handler::BusDisconnect();
  350. }
  351. // SystemTickBus
  352. void OnSystemTick() override
  353. {
  354. AZ::SystemTickBus::Handler::BusDisconnect();
  355. AssignIndex(m_variableTypeModel.GetDefaultIndex());
  356. SignalValueChanged();
  357. }
  358. ////
  359. // NodeNotificationBus
  360. void OnSlotDisplayTypeChanged(const ScriptCanvas::SlotId& slotId, [[maybe_unused]] const ScriptCanvas::Data::Type& slotType) override
  361. {
  362. if (slotId == GetSlotId())
  363. {
  364. m_variableTypeModel.RefreshFilter();
  365. }
  366. }
  367. void OnSlotInputChanged(const ScriptCanvas::SlotId& slotId) override
  368. {
  369. if (slotId == GetSlotId())
  370. {
  371. RegisterBus();
  372. }
  373. ScriptCanvasDataInterface<GraphCanvas::ComboBoxDataInterface>::OnSlotInputChanged(slotId);
  374. }
  375. ////
  376. // VariableNotificationBus
  377. void OnVariableRenamed([[maybe_unused]] AZStd::string_view newName) override
  378. {
  379. SignalValueChanged();
  380. }
  381. void OnVariableRemoved() override
  382. {
  383. // Delay this since its possible the model hasn't updated yet
  384. AZ::SystemTickBus::Handler::BusConnect();
  385. }
  386. ////
  387. // EndpointNotificationBus
  388. void OnEndpointReferenceChanged(const ScriptCanvas::VariableId& variableId) override
  389. {
  390. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  391. ScriptCanvas::VariableNotificationBus::Handler::BusConnect(ScriptCanvas::GraphScopedVariableId(GetScriptCanvasId(), variableId));
  392. SignalValueChanged();
  393. }
  394. void OnSlotRecreated() override
  395. {
  396. ScriptCanvas::Slot* slot = GetSlot();
  397. if (slot)
  398. {
  399. m_variableTypeModel.SetSlotFilter(slot);
  400. }
  401. }
  402. ////
  403. // GraphCanvas::ComboBoxModelInterface
  404. GraphCanvas::ComboBoxItemModelInterface* GetItemInterface() override
  405. {
  406. return &m_variableTypeModel;
  407. }
  408. void AssignIndex(const QModelIndex& index) override
  409. {
  410. ScriptCanvas::Slot* slot = GetSlot();
  411. if (slot)
  412. {
  413. if (slot->IsVariableReference())
  414. {
  415. // This will trigger an ebus call regarding the modification, which will trigger the value changed.
  416. ScriptCanvas::VariableId variableId = m_variableTypeModel.GetValueForIndex(index);
  417. slot->SetVariableReference(variableId);
  418. PostUndoPoint();
  419. }
  420. }
  421. }
  422. QModelIndex GetAssignedIndex() const override
  423. {
  424. ScriptCanvas::Slot* slot = GetSlot();
  425. if (slot)
  426. {
  427. if (slot->IsVariableReference())
  428. {
  429. return m_variableTypeModel.GetIndexForValue(slot->GetVariableReference());
  430. }
  431. }
  432. return QModelIndex();
  433. }
  434. // Returns the string used to display the currently selected value[Used in the non-editable format]
  435. QString GetDisplayString() const override
  436. {
  437. ScriptCanvas::Slot* slot = GetSlot();
  438. if (slot)
  439. {
  440. if (slot->IsVariableReference())
  441. {
  442. const ScriptCanvas::GraphVariable* variable = m_variableTypeModel.GetGraphVariable(slot->GetVariableReference());
  443. if (variable)
  444. {
  445. return m_variableTypeModel.GetDisplayName(variable->GetVariableId());
  446. }
  447. }
  448. }
  449. return ComboBoxDataInterface::GetDisplayString();
  450. }
  451. private:
  452. void RegisterBus()
  453. {
  454. ScriptCanvas::Slot* slot = GetSlot();
  455. if (slot)
  456. {
  457. ScriptCanvas::VariableId variableId = slot->GetVariableReference();
  458. if (ScriptCanvas::VariableNotificationBus::Handler::BusIsConnected())
  459. {
  460. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  461. }
  462. if (variableId.IsValid())
  463. {
  464. ScriptCanvas::VariableNotificationBus::Handler::BusConnect(ScriptCanvas::GraphScopedVariableId(m_scriptCanvasGraphId, variableId));
  465. }
  466. }
  467. }
  468. ScriptCanvas::Slot* GetSlot() const
  469. {
  470. ScriptCanvas::Slot* slot = nullptr;
  471. ScriptCanvas::NodeRequestBus::EventResult(slot, GetNodeId(), &ScriptCanvas::NodeRequests::GetSlot, GetSlotId());
  472. return slot;
  473. }
  474. VariableTypeComboBoxFilterModel m_variableTypeModel;
  475. ScriptCanvas::Data::Type m_displayType = ScriptCanvas::Data::Type::Invalid();
  476. AZ::EntityId m_scriptCanvasGraphId;
  477. };
  478. }