3
0

VariableDockWidget.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  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 <QAction>
  9. #include <QCompleter>
  10. #include <QEvent>
  11. #include <QGraphicsScene>
  12. #include <QGraphicsView>
  13. #include <QAction>
  14. #include <QMenu>
  15. #include <QMessageBox>
  16. #include <QScopedValueRollback>
  17. #include <QLineEdit>
  18. #include <QTimer>
  19. #include <QPushButton>
  20. #include <QHeaderView>
  21. #include <AzCore/Component/ComponentApplication.h>
  22. #include <AzCore/RTTI/BehaviorContext.h>
  23. #include <AzCore/UserSettings/UserSettings.h>
  24. #include <AzCore/Serialization/SerializeContext.h>
  25. #include <AzCore/Serialization/EditContext.h>
  26. #include <AzToolsFramework/Entity/EditorEntityContextPickingBus.h>
  27. #include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
  28. #include <GraphCanvas/Components/VisualBus.h>
  29. #include <GraphCanvas/Components/SceneBus.h>
  30. #include <GraphCanvas/Components/StyleBus.h>
  31. #include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
  32. #include <Editor/View/Widgets/VariablePanel/ui_VariableDockWidget.h>
  33. #include <Data/Data.h>
  34. #include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
  35. #include <Editor/QtMetaTypes.h>
  36. #include <Editor/Settings.h>
  37. #include <Editor/Translation/TranslationHelper.h>
  38. #include <Editor/View/Widgets/DataTypePalette/DataTypePaletteModel.h>
  39. #include <Editor/View/Widgets/NodePalette/VariableNodePaletteTreeItemTypes.h>
  40. #include <Editor/View/Widgets/PropertyGridBus.h>
  41. #include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
  42. #include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
  43. #include <ScriptCanvas/Core/NodeBus.h>
  44. #include <ScriptCanvas/Data/DataRegistry.h>
  45. #include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
  46. #include <ScriptCanvas/Asset/RuntimeAsset.h>
  47. #include "GraphCanvas/Components/Slots/Data/DataSlotBus.h"
  48. namespace ScriptCanvasEditor
  49. {
  50. ////////////////////////////////
  51. // VariablePropertiesComponent
  52. ////////////////////////////////
  53. void VariablePropertiesComponent::Reflect(AZ::ReflectContext* context)
  54. {
  55. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  56. if (serializeContext)
  57. {
  58. serializeContext->Class<VariablePropertiesComponent, GraphCanvas::GraphCanvasPropertyComponent>()
  59. ->Version(1)
  60. ->Field("VariableName", &VariablePropertiesComponent::m_variableName)
  61. ->Field("VariableDatum", &VariablePropertiesComponent::m_variable)
  62. ;
  63. AZ::EditContext* editContext = serializeContext->GetEditContext();
  64. if (editContext)
  65. {
  66. editContext->Class<VariablePropertiesComponent>("Variable Properties", "")
  67. ->ClassElement(AZ::Edit::ClassElements::EditorData, "Properties")
  68. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  69. ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &VariablePropertiesComponent::GetTitle)
  70. ->DataElement(AZ::Edit::UIHandlers::Default, &VariablePropertiesComponent::m_variableName, "Name", "")
  71. ->Attribute(AZ::Edit::Attributes::StringLineEditingCompleteNotify, &VariablePropertiesComponent::OnNameChanged)
  72. ->DataElement(AZ::Edit::UIHandlers::Default, &VariablePropertiesComponent::m_variable, "Datum", "")
  73. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  74. ;
  75. }
  76. }
  77. }
  78. AZ::Entity* VariablePropertiesComponent::CreateVariablePropertiesEntity()
  79. {
  80. AZ::Entity* entity = aznew AZ::Entity("VariablePropertiesHelper");
  81. entity->CreateComponent<VariablePropertiesComponent>();
  82. return entity;
  83. }
  84. VariablePropertiesComponent::VariablePropertiesComponent()
  85. : m_variableName(AZStd::string())
  86. , m_variable(nullptr)
  87. , m_componentTitle("Variable")
  88. {
  89. }
  90. const char* VariablePropertiesComponent::GetTitle()
  91. {
  92. return m_componentTitle.c_str();
  93. }
  94. void VariablePropertiesComponent::SetVariable(ScriptCanvas::GraphVariable* variable)
  95. {
  96. if (variable)
  97. {
  98. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  99. m_variable = variable;
  100. m_componentTitle.clear();
  101. m_variableName.clear();
  102. m_variableName = m_variable->GetVariableName();
  103. const AZStd::string variableTypeName = TranslationHelper::GetSafeTypeName(m_variable->GetDatum()->GetType());
  104. m_componentTitle = AZStd::string::format("%s Variable", variableTypeName.data());
  105. ScriptCanvas::VariableNotificationBus::Handler::BusConnect(m_variable->GetGraphScopedId());
  106. m_scriptCanvasGraphId = m_variable->GetGraphScopedId().m_scriptCanvasId;
  107. }
  108. }
  109. void VariablePropertiesComponent::OnNameChanged()
  110. {
  111. if (m_variable == nullptr)
  112. {
  113. return;
  114. }
  115. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  116. AZ::Outcome<void, AZStd::string> outcome = AZ::Failure(AZStd::string());
  117. AZStd::string_view oldVariableName = m_variable->GetVariableName();
  118. if (oldVariableName != m_variableName)
  119. {
  120. ScriptCanvas::VariableRequestBus::EventResult(outcome, m_variable->GetGraphScopedId(), &ScriptCanvas::VariableRequests::RenameVariable, m_variableName);
  121. AZ_Warning("VariablePropertiesComponent", outcome.IsSuccess(), "Could not rename variable: %s", outcome.GetError().c_str());
  122. if (!outcome.IsSuccess())
  123. {
  124. // Revert the variable name if we couldn't rename it (e.g. not unique)
  125. m_variableName = oldVariableName;
  126. PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
  127. }
  128. else
  129. {
  130. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasGraphId);
  131. }
  132. }
  133. ScriptCanvas::VariableNotificationBus::Handler::BusConnect(m_variable->GetGraphScopedId());
  134. }
  135. void VariablePropertiesComponent::OnVariableRemoved()
  136. {
  137. ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
  138. m_variableName = AZStd::string();
  139. m_variable = nullptr;
  140. }
  141. void VariablePropertiesComponent::OnVariableValueChanged()
  142. {
  143. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasGraphId);
  144. PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
  145. AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
  146. }
  147. void VariablePropertiesComponent::OnVariableRenamed(AZStd::string_view variableName)
  148. {
  149. m_variableName = variableName;
  150. PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
  151. }
  152. void VariablePropertiesComponent::OnVariableScopeChanged()
  153. {
  154. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasGraphId);
  155. PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
  156. }
  157. /////////////////////////////
  158. // VariablePanelContextMenu
  159. /////////////////////////////
  160. VariablePanelContextMenu::VariablePanelContextMenu(VariableDockWidget* dockWidget, const ScriptCanvas::ScriptCanvasId& scriptCanvasId
  161. , ScriptCanvas::VariableId varId, QPoint position)
  162. : QMenu()
  163. {
  164. AZ::EntityId graphCanvasGraphId;
  165. GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::GetGraphCanvasGraphId, scriptCanvasId);
  166. AZStd::string variableName;
  167. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(variableName, scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::GetVariableName, varId);
  168. QAction* getAction = new QAction(QObject::tr("Get %1").arg(variableName.c_str()), this);
  169. getAction->setToolTip(QObject::tr("Adds a Get %1 variable node onto the active graph.").arg(variableName.c_str()));
  170. getAction->setStatusTip(QObject::tr("Adds a Get %1 variable node onto the active graph.").arg(variableName.c_str()));
  171. QObject::connect(getAction,
  172. &QAction::triggered,
  173. [graphCanvasGraphId, varId](bool)
  174. {
  175. CreateGetVariableNodeMimeEvent mimeEvent(varId);
  176. AZ::EntityId viewId;
  177. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  178. AZ::Vector2 viewCenter;
  179. GraphCanvas::ViewRequestBus::EventResult(viewCenter, viewId, &GraphCanvas::ViewRequests::GetViewSceneCenter);
  180. mimeEvent.ExecuteEvent(viewCenter, viewCenter, graphCanvasGraphId);
  181. });
  182. QAction* setAction = new QAction(QObject::tr("Set %1").arg(variableName.c_str()), this);
  183. setAction->setToolTip(QObject::tr("Adds a Set %1 variable node onto the active graph.").arg(variableName.c_str()));
  184. setAction->setStatusTip(QObject::tr("Adds a Set %1 variable node onto the active graph.").arg(variableName.c_str()));
  185. QObject::connect(setAction,
  186. &QAction::triggered,
  187. [graphCanvasGraphId, varId](bool)
  188. {
  189. CreateSetVariableNodeMimeEvent mimeEvent(varId);
  190. AZ::EntityId viewId;
  191. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  192. AZ::Vector2 viewCenter;
  193. GraphCanvas::ViewRequestBus::EventResult(viewCenter, viewId, &GraphCanvas::ViewRequests::GetViewSceneCenter);
  194. mimeEvent.ExecuteEvent(viewCenter, viewCenter, graphCanvasGraphId);
  195. });
  196. QAction* copyAction = new QAction(QObject::tr("Copy %1").arg(variableName.c_str()), this);
  197. copyAction->setToolTip(QObject::tr("Copies the variable called - %1").arg(variableName.c_str()));
  198. copyAction->setStatusTip(QObject::tr("Copies the variable called - %1").arg(variableName.c_str()));
  199. QObject::connect(copyAction,
  200. &QAction::triggered,
  201. [dockWidget, varId](bool)
  202. {
  203. GraphVariablesTableView::CopyVariableToClipboard(dockWidget->GetActiveScriptCanvasId(), varId);
  204. });
  205. QAction* pasteAction = new QAction(QObject::tr("Paste %1").arg(variableName.c_str()), this);
  206. pasteAction->setToolTip(QObject::tr("Pastes the variable %1 currently on the clipboard").arg(variableName.c_str()));
  207. pasteAction->setStatusTip(QObject::tr("Pastes the variable %1 currently on the clipboard").arg(variableName.c_str()));
  208. pasteAction->setEnabled(GraphVariablesTableView::HasCopyVariableData());
  209. QObject::connect(pasteAction,
  210. &QAction::triggered,
  211. [dockWidget](bool)
  212. {
  213. GraphVariablesTableView::HandleVariablePaste(dockWidget->GetActiveScriptCanvasId());
  214. });
  215. QAction* duplicateAction = new QAction(QObject::tr("Duplicate %1").arg(variableName.c_str()), this);
  216. duplicateAction->setToolTip(QObject::tr("Duplicates the variable called - %1").arg(variableName.c_str()));
  217. duplicateAction->setStatusTip(QObject::tr("Duplicates the variable called - %1").arg(variableName.c_str()));
  218. QObject::connect(duplicateAction,
  219. &QAction::triggered,
  220. [dockWidget, varId](bool)
  221. {
  222. dockWidget->OnDuplicateVariable(varId);
  223. });
  224. QAction* deleteAction = new QAction(QObject::tr("Delete %1").arg(variableName.c_str()), this);
  225. deleteAction->setToolTip(QObject::tr("Deletes the variable called - %1").arg(variableName.c_str()));
  226. deleteAction->setStatusTip(QObject::tr("Deletes the variable called - %1").arg(variableName.c_str()));
  227. QObject::connect(deleteAction,
  228. &QAction::triggered,
  229. [dockWidget, varId](bool)
  230. {
  231. AZStd::unordered_set< ScriptCanvas::VariableId > variableIds = { varId };
  232. dockWidget->OnDeleteVariables(variableIds);
  233. });
  234. QAction* configureAction = new QAction(QObject::tr("Configure %1").arg(variableName.c_str()), this);
  235. configureAction->setToolTip(QObject::tr("Sets the name/type the variable called - %1").arg(variableName.c_str()));
  236. configureAction->setStatusTip(QObject::tr("Sets the name/type the variable called - %1").arg(variableName.c_str()));
  237. QObject::connect(configureAction,
  238. &QAction::triggered,
  239. [dockWidget, varId, position](bool)
  240. {
  241. dockWidget->OnConfigureVariable(varId, position);
  242. });
  243. addAction(getAction);
  244. addAction(setAction);
  245. addSeparator();
  246. addAction(copyAction);
  247. addAction(pasteAction);
  248. addAction(duplicateAction);
  249. addAction(deleteAction);
  250. addAction(configureAction);
  251. }
  252. ///////////////////////
  253. // VariableDockWidget
  254. ///////////////////////
  255. AZStd::string VariableDockWidget::ConstructDefaultVariableName(AZ::u32 variableCounter)
  256. {
  257. return AZStd::string::format("Variable %u", variableCounter);
  258. }
  259. AZStd::string VariableDockWidget::FindDefaultVariableName(const ScriptCanvas::ScriptCanvasId& scriptCanvasExecutionId)
  260. {
  261. ScriptCanvas::VariableValidationOutcome nameAvailable = AZ::Failure(ScriptCanvas::GraphVariableValidationErrorCode::Unknown);
  262. AZStd::string varName;
  263. do
  264. {
  265. AZ::u32 varCounter = 0;
  266. SceneCounterRequestBus::EventResult(varCounter, scriptCanvasExecutionId, &SceneCounterRequests::GetNewVariableCounter);
  267. varName = ConstructDefaultVariableName(varCounter);
  268. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(nameAvailable, scriptCanvasExecutionId, &ScriptCanvas::GraphVariableManagerRequests::IsNameValid, varName);
  269. } while (!nameAvailable);
  270. return varName;
  271. }
  272. VariableDockWidget::VariableDockWidget(QWidget* parent /*= nullptr*/)
  273. : AzQtComponents::StyledDockWidget(parent)
  274. , ui(new Ui::VariableDockWidget())
  275. {
  276. ui->setupUi(this);
  277. ui->graphVariables->setContentsMargins(0, 0, 0, 0);
  278. ui->graphVariables->setContextMenuPolicy(Qt::CustomContextMenu);
  279. QObject::connect(ui->graphVariables, &GraphVariablesTableView::SelectionChanged, this, &VariableDockWidget::OnSelectionChanged);
  280. QObject::connect(ui->graphVariables, &QWidget::customContextMenuRequested, this, &VariableDockWidget::OnContextMenuRequested);
  281. ui->searchFilter->setClearButtonEnabled(true);
  282. QObject::connect(ui->searchFilter, &QLineEdit::textChanged, this, &VariableDockWidget::OnQuickFilterChanged);
  283. QObject::connect(ui->searchFilter, &QLineEdit::returnPressed, this, &VariableDockWidget::OnReturnPressed);
  284. // Tell the widget to auto create our context menu, for now
  285. setContextMenuPolicy(Qt::ActionsContextMenu);
  286. // Add button is disabled by default, since we don't want to switch panels until we have an active scene.
  287. connect(ui->addButton, &QPushButton::clicked, this, &VariableDockWidget::OnAddVariableButton);
  288. ui->addButton->setEnabled(false);
  289. ui->searchFilter->setEnabled(false);
  290. QObject::connect(ui->variablePalette, &VariablePaletteTableView::CreateVariable, this, &VariableDockWidget::OnCreateVariable);
  291. QObject::connect(ui->variablePalette, &VariablePaletteTableView::CreateNamedVariable, this, &VariableDockWidget::OnCreateNamedVariable);
  292. QObject::connect(ui->graphVariables, &GraphVariablesTableView::DeleteVariables, this, &VariableDockWidget::OnDeleteVariables);
  293. m_filterTimer.setInterval(250);
  294. m_filterTimer.setSingleShot(true);
  295. m_filterTimer.stop();
  296. QObject::connect(&m_filterTimer, &QTimer::timeout, this, &VariableDockWidget::UpdateFilter);
  297. GraphCanvas::AssetEditorNotificationBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
  298. ShowGraphVariables();
  299. VariableAutomationRequestBus::Handler::BusConnect();
  300. }
  301. VariableDockWidget::~VariableDockWidget()
  302. {
  303. GraphCanvas::AssetEditorNotificationBus::Handler::BusDisconnect();
  304. VariableAutomationRequestBus::Handler::BusDisconnect();
  305. }
  306. void VariableDockWidget::PopulateVariablePalette(const AZStd::unordered_set< AZ::Uuid >& objectTypes)
  307. {
  308. ui->variablePalette->PopulateVariablePalette(objectTypes);
  309. }
  310. void VariableDockWidget::OnActiveGraphChanged(const GraphCanvas::GraphId& graphCanvasGraphId)
  311. {
  312. ClearFilter();
  313. m_graphCanvasGraphId = graphCanvasGraphId;
  314. m_scriptCanvasId.SetInvalid();
  315. GeneralRequestBus::BroadcastResult(m_scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
  316. ui->graphVariables->SetActiveScene(m_scriptCanvasId);
  317. ui->variablePalette->SetActiveScene(m_scriptCanvasId);
  318. ui->addButton->setEnabled(m_scriptCanvasId.IsValid());
  319. ui->searchFilter->setEnabled(m_scriptCanvasId.IsValid());
  320. ShowGraphVariables();
  321. }
  322. AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetPrimitiveTypes() const
  323. {
  324. AZStd::vector< ScriptCanvas::Data::Type > primitiveTypes;
  325. auto variableTypes = ui->variablePalette->GetVariableTypePaletteModel()->GetVariableTypes();
  326. for (auto variableType : variableTypes)
  327. {
  328. ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(variableType);
  329. if (ScriptCanvas::Data::IsValueType(dataType))
  330. {
  331. primitiveTypes.push_back(dataType);
  332. }
  333. }
  334. return primitiveTypes;
  335. }
  336. AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetBehaviorContextObjectTypes() const
  337. {
  338. AZStd::vector< ScriptCanvas::Data::Type > bcoTypes;
  339. auto variableTypes = ui->variablePalette->GetVariableTypePaletteModel()->GetVariableTypes();
  340. for (auto variableType : variableTypes)
  341. {
  342. ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(variableType);
  343. if (!ScriptCanvas::Data::IsValueType(dataType))
  344. {
  345. if (!ScriptCanvas::Data::IsContainerType(dataType))
  346. {
  347. bcoTypes.emplace_back(dataType);
  348. }
  349. }
  350. }
  351. return bcoTypes;
  352. }
  353. AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetMapTypes() const
  354. {
  355. AZStd::vector< ScriptCanvas::Data::Type > variableDataTypes;
  356. auto mapTypes = ui->variablePalette->GetMapTypes();
  357. for (auto mapType : mapTypes)
  358. {
  359. ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(mapType);
  360. variableDataTypes.emplace_back(dataType);
  361. }
  362. return variableDataTypes;
  363. }
  364. AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetArrayTypes() const
  365. {
  366. AZStd::vector< ScriptCanvas::Data::Type > variableDataTypes;
  367. auto arrayTypes = ui->variablePalette->GetArrayTypes();
  368. for (auto arrayType : arrayTypes)
  369. {
  370. ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(arrayType);
  371. variableDataTypes.emplace_back(dataType);
  372. }
  373. return variableDataTypes;
  374. }
  375. bool VariableDockWidget::IsShowingVariablePalette() const
  376. {
  377. return ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->variablePalettePage);
  378. }
  379. bool VariableDockWidget::IsShowingGraphVariables() const
  380. {
  381. return ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->graphVariablesPage);
  382. }
  383. QPushButton* VariableDockWidget::GetCreateVariableButton() const
  384. {
  385. return ui->addButton;
  386. }
  387. QTableView* VariableDockWidget::GetGraphPaletteTableView() const
  388. {
  389. return ui->graphVariables;
  390. }
  391. QTableView* VariableDockWidget::GetVariablePaletteTableView() const
  392. {
  393. return ui->variablePalette;
  394. }
  395. QLineEdit* VariableDockWidget::GetVariablePaletteFilter() const
  396. {
  397. return ui->searchFilter;
  398. }
  399. QLineEdit* VariableDockWidget::GetGraphVariablesFilter() const
  400. {
  401. return ui->searchFilter;
  402. }
  403. void VariableDockWidget::OnEscape()
  404. {
  405. ShowGraphVariables();
  406. }
  407. void VariableDockWidget::focusOutEvent(QFocusEvent* focusEvent)
  408. {
  409. AzQtComponents::StyledDockWidget::focusOutEvent(focusEvent);
  410. if (ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->variablePalettePage))
  411. {
  412. ShowGraphVariables();
  413. }
  414. }
  415. const ScriptCanvas::ScriptCanvasId& VariableDockWidget::GetActiveScriptCanvasId() const
  416. {
  417. return m_scriptCanvasId;
  418. }
  419. bool VariableDockWidget::IsValidVariableType(const ScriptCanvas::Data::Type& dataType) const
  420. {
  421. bool isValid = false;
  422. AZ::Uuid azType = ScriptCanvas::Data::ToAZType(dataType);
  423. if (ScriptCanvas::Data::IsMapContainerType(dataType))
  424. {
  425. auto mapTypes = ui->variablePalette->GetMapTypes();
  426. auto findIter = AZStd::find(mapTypes.begin(), mapTypes.end(), azType);
  427. isValid = findIter != mapTypes.end();
  428. }
  429. else if (ScriptCanvas::Data::IsVectorContainerType(dataType))
  430. {
  431. auto arrayTypes = ui->variablePalette->GetArrayTypes();
  432. auto findIter = AZStd::find(arrayTypes.begin(), arrayTypes.end(), azType);
  433. isValid = findIter != arrayTypes.end();
  434. }
  435. else
  436. {
  437. const auto& variableTypes = ui->variablePalette->GetVariableTypePaletteModel()->GetVariableTypes();
  438. auto findIter = AZStd::find(variableTypes.begin(), variableTypes.end(), azType);
  439. isValid = findIter != variableTypes.end();
  440. }
  441. return isValid;
  442. }
  443. void VariableDockWidget::ShowVariablePalette()
  444. {
  445. ui->stackedWidget->setCurrentIndex(ui->stackedWidget->indexOf(ui->variablePalettePage));
  446. ClearFilter();
  447. ui->searchFilter->setPlaceholderText("Variable Type...");
  448. FocusOnSearchFilter();
  449. ui->searchFilter->setCompleter(ui->variablePalette->GetVariableCompleter());
  450. AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
  451. }
  452. void VariableDockWidget::ShowGraphVariables()
  453. {
  454. ui->stackedWidget->setCurrentIndex(ui->stackedWidget->indexOf(ui->graphVariablesPage));
  455. ClearFilter();
  456. ui->variablePalette->clearSelection();
  457. ui->searchFilter->setPlaceholderText("Search...");
  458. ui->searchFilter->setCompleter(nullptr);
  459. AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
  460. }
  461. void VariableDockWidget::FocusOnSearchFilter()
  462. {
  463. ui->searchFilter->setFocus(Qt::FocusReason::MouseFocusReason);
  464. }
  465. void VariableDockWidget::ClearFilter()
  466. {
  467. {
  468. QSignalBlocker blocker(ui->searchFilter);
  469. ui->searchFilter->setText("");
  470. }
  471. UpdateFilter();
  472. }
  473. void VariableDockWidget::UpdateFilter()
  474. {
  475. if (IsShowingGraphVariables())
  476. {
  477. ui->graphVariables->SetFilter(ui->searchFilter->text());
  478. }
  479. else if (IsShowingVariablePalette())
  480. {
  481. ui->variablePalette->SetFilter(ui->searchFilter->userInputText());
  482. }
  483. }
  484. void VariableDockWidget::OnReturnPressed()
  485. {
  486. if (IsShowingVariablePalette())
  487. {
  488. ui->variablePalette->TryCreateVariableByTypeName(ui->searchFilter->text().toStdString().c_str());
  489. }
  490. else if (IsShowingGraphVariables())
  491. {
  492. UpdateFilter();
  493. }
  494. }
  495. void VariableDockWidget::OnQuickFilterChanged(const QString& text)
  496. {
  497. if(text.isEmpty())
  498. {
  499. //If field was cleared, update immediately
  500. UpdateFilter();
  501. return;
  502. }
  503. m_filterTimer.stop();
  504. m_filterTimer.start();
  505. }
  506. void VariableDockWidget::RefreshModel()
  507. {
  508. ui->graphVariables->SetActiveScene(m_scriptCanvasId);
  509. }
  510. void VariableDockWidget::OnAddVariableButton()
  511. {
  512. int index = ui->stackedWidget->currentIndex();
  513. // Switch between pages
  514. if (index == ui->stackedWidget->indexOf(ui->graphVariablesPage))
  515. {
  516. ShowVariablePalette();
  517. }
  518. else if(index == ui->stackedWidget->indexOf(ui->variablePalettePage))
  519. {
  520. ShowGraphVariables();
  521. }
  522. }
  523. void VariableDockWidget::OnContextMenuRequested(const QPoint& pos)
  524. {
  525. AzToolsFramework::EditorPickModeRequestBus::Broadcast(&AzToolsFramework::EditorPickModeRequests::StopEntityPickMode);
  526. QModelIndex index = ui->graphVariables->indexAt(pos);
  527. QActionGroup actionGroup(this);
  528. actionGroup.setExclusive(true);
  529. QAction* sortByName = actionGroup.addAction("Sort by name");
  530. sortByName->setCheckable(true);
  531. QAction* sortByType = actionGroup.addAction("Sort by type");
  532. sortByType->setCheckable(true);
  533. AZStd::intrusive_ptr<EditorSettings::ScriptCanvasEditorSettings> settings = AZ::UserSettings::CreateFind<EditorSettings::ScriptCanvasEditorSettings>(AZ_CRC("ScriptCanvasPreviewSettings", 0x1c5a2965), AZ::UserSettings::CT_LOCAL);
  534. if (settings->m_variablePanelSorting == GraphVariablesModel::ColumnIndex::Name)
  535. {
  536. sortByName->setChecked(true);
  537. }
  538. else
  539. {
  540. sortByType->setChecked(true);
  541. }
  542. QAction* cleanupAction = new QAction(QObject::tr("Remove unused variables"), this);
  543. QAction* actionResult = nullptr;
  544. ScriptCanvas::VariableId varId;
  545. // Bring up the context menu if the item is valid
  546. if (index.row() > -1)
  547. {
  548. varId = index.data(GraphVariablesModel::VarIdRole).value<ScriptCanvas::VariableId>();
  549. VariablePanelContextMenu menu(this, m_scriptCanvasId, varId, pos);
  550. menu.addSeparator();
  551. menu.addAction(cleanupAction);
  552. menu.addSeparator();
  553. menu.addAction(sortByName);
  554. menu.addAction(sortByType);
  555. actionResult = menu.exec(ui->graphVariables->mapToGlobal(pos));
  556. }
  557. else
  558. {
  559. QMenu menu;
  560. menu.addAction(cleanupAction);
  561. menu.addSeparator();
  562. menu.addAction(sortByName);
  563. menu.addAction(sortByType);
  564. actionResult = menu.exec(ui->graphVariables->mapToGlobal(pos));
  565. }
  566. // Very likely the actions are dangling pointers here. Do not dereference them.
  567. if (actionResult == sortByName)
  568. {
  569. settings->m_variablePanelSorting = GraphVariablesModel::ColumnIndex::Name;
  570. ui->graphVariables->ApplyPreferenceSort();
  571. }
  572. else if (actionResult == sortByType)
  573. {
  574. settings->m_variablePanelSorting = GraphVariablesModel::ColumnIndex::Type;
  575. ui->graphVariables->ApplyPreferenceSort();
  576. }
  577. else if (actionResult == cleanupAction)
  578. {
  579. OnRemoveUnusedVariables();
  580. }
  581. }
  582. void VariableDockWidget::OnSelectionChanged(const AZStd::unordered_set< ScriptCanvas::VariableId>& variableIds)
  583. {
  584. if (!variableIds.empty())
  585. {
  586. GraphCanvas::SceneRequestBus::Event(m_graphCanvasGraphId, &GraphCanvas::SceneRequests::ClearSelection);
  587. AZStd::vector<ScriptCanvas::VariableId> deselectedVariableIds;
  588. for (auto pair : m_usedElements)
  589. {
  590. if (variableIds.count(pair.first) == 0)
  591. {
  592. deselectedVariableIds.emplace_back(pair.first);
  593. m_unusedPool.emplace_back(pair.second);
  594. }
  595. }
  596. for (auto variableId : deselectedVariableIds)
  597. {
  598. ReleaseComponent(variableId);
  599. }
  600. }
  601. else
  602. {
  603. ResetPool();
  604. }
  605. AZStd::vector<AZ::EntityId> selection;
  606. auto owningGraph = ScriptCanvas::GraphRequestBus::FindFirstHandler(m_scriptCanvasId);
  607. if (owningGraph == nullptr)
  608. {
  609. return;
  610. }
  611. for (const ScriptCanvas::VariableId& varId : variableIds)
  612. {
  613. VariablePropertiesComponent* propertiesComponent = AllocateComponent(varId);
  614. if (propertiesComponent)
  615. {
  616. ScriptCanvas::GraphVariable* graphVariable = owningGraph->FindVariableById(varId);;
  617. propertiesComponent->SetVariable(graphVariable);
  618. selection.push_back(propertiesComponent->GetEntityId());
  619. }
  620. }
  621. OnHighlightVariables(variableIds);
  622. Q_EMIT OnVariableSelectionChanged(selection);
  623. }
  624. void VariableDockWidget::OnDuplicateVariable(const ScriptCanvas::VariableId& variableId)
  625. {
  626. ScriptCanvas::GraphVariable* graphVariable = nullptr;
  627. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, variableId);
  628. if (graphVariable == nullptr)
  629. {
  630. return;
  631. }
  632. ScriptCanvas::GraphVariableManagerRequestBus::Event(m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::CloneVariable, (*graphVariable));
  633. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
  634. }
  635. void VariableDockWidget::OnCreateVariable(ScriptCanvas::Data::Type varType)
  636. {
  637. AZStd::string varName = FindDefaultVariableName(m_scriptCanvasId);
  638. OnCreateNamedVariable(varName, varType);
  639. }
  640. void VariableDockWidget::OnCreateNamedVariable(const AZStd::string& variableName, ScriptCanvas::Data::Type varType)
  641. {
  642. ShowGraphVariables();
  643. ScriptCanvas::Datum datum(varType, ScriptCanvas::Datum::eOriginality::Original);
  644. AZ::Outcome<ScriptCanvas::VariableId, AZStd::string> outcome = AZ::Failure(AZStd::string());
  645. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum, false);
  646. AZ_Warning("VariablePanel", outcome.IsSuccess(), "Could not create new variable: %s", outcome.GetError().c_str());
  647. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
  648. // We already provide a naming hook for container types so we don't need to do re-force them into it.
  649. if (outcome.IsSuccess() && !ScriptCanvas::Data::IsContainerType(varType))
  650. {
  651. ui->graphVariables->EditVariableName(outcome.GetValue());
  652. }
  653. }
  654. void VariableDockWidget::OnDeleteVariables(const AZStd::unordered_set< ScriptCanvas::VariableId>& variableIds)
  655. {
  656. PropertyGridRequestBus::Broadcast(&PropertyGridRequests::ClearSelection);
  657. GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate);
  658. bool result = false;
  659. for (const ScriptCanvas::VariableId& variableId : variableIds)
  660. {
  661. if (CanDeleteVariable(variableId))
  662. {
  663. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(result, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::RemoveVariable, variableId);
  664. AZ_Warning("VariablePanel", result, "Could not delete Variable Id (%s).", variableId.ToString().data());
  665. if (result)
  666. {
  667. ReleaseComponent(variableId);
  668. }
  669. }
  670. }
  671. ui->graphVariables->ResizeColumns();
  672. GeneralRequestBus::Broadcast(&GeneralRequests::PopPreventUndoStateUpdate);
  673. if (result)
  674. {
  675. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
  676. }
  677. }
  678. void VariableDockWidget::OnHighlightVariables(const AZStd::unordered_set< ScriptCanvas::VariableId>& variableIds)
  679. {
  680. EditorGraphRequestBus::Event(m_scriptCanvasId, &EditorGraphRequests::HighlightVariables, variableIds);
  681. }
  682. void VariableDockWidget::OnConfigureVariable([[maybe_unused]] const ScriptCanvas::VariableId& variableId, [[maybe_unused]] QPoint position)
  683. {
  684. ScriptCanvas::GraphVariable* graphVariable = nullptr;
  685. ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, variableId);
  686. if (graphVariable)
  687. {
  688. VariablePaletteRequests::VariableConfigurationInput input;
  689. input.m_graphVariable = graphVariable;
  690. input.m_changeVariableName = true;
  691. input.m_changeVariableType = true;
  692. VariablePaletteRequests::VariableConfigurationOutput output;
  693. VariablePaletteRequestBus::BroadcastResult(output, &VariablePaletteRequests::ShowVariableConfigurationWidget, input, position);
  694. if (output.m_actionIsValid)
  695. {
  696. if ((output.m_nameChanged && !output.m_name.empty()) || (output.m_typeChanged && output.m_type.IsValid()))
  697. {
  698. GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
  699. GraphCanvas::ScopedGraphUndoBlocker undoBlocker(m_graphCanvasGraphId);
  700. if ((output.m_nameChanged && !output.m_name.empty()))
  701. {
  702. graphVariable->SetVariableName(output.m_name);
  703. }
  704. if (output.m_typeChanged && output.m_type.IsValid())
  705. {
  706. graphVariable->ModDatum().SetType(output.m_type, ScriptCanvas::Datum::TypeChange::Forced);
  707. ScriptCanvas::GraphRequestBus::Event(m_scriptCanvasId, &ScriptCanvas::GraphRequests::RefreshVariableReferences
  708. , graphVariable->GetVariableId());
  709. }
  710. }
  711. }
  712. }
  713. }
  714. void VariableDockWidget::OnRemoveUnusedVariables()
  715. {
  716. EditorGraphRequestBus::Event(m_scriptCanvasId, &EditorGraphRequests::RemoveUnusedVariables);
  717. }
  718. bool VariableDockWidget::CanDeleteVariable(const ScriptCanvas::VariableId& variableId)
  719. {
  720. bool canDeleteVariable = false;
  721. AZStd::vector< NodeIdPair > nodeIds;
  722. EditorGraphRequestBus::EventResult(nodeIds, m_scriptCanvasId, &EditorGraphRequests::GetVariableNodes, variableId);
  723. if (!nodeIds.empty())
  724. {
  725. AZStd::string variableName;
  726. ScriptCanvas::VariableRequestBus::EventResult(variableName, ScriptCanvas::GraphScopedVariableId(m_scriptCanvasId, variableId), &ScriptCanvas::VariableRequests::GetName);
  727. int result = QMessageBox::warning(this, QString("Delete %1 and References").arg(variableName.c_str()), QString("The variable \"%1\" has %2 active references.\nAre you sure you want to delete the variable and its references from the graph?").arg(variableName.c_str()).arg(nodeIds.size()), QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::Cancel);
  728. if (result == QMessageBox::StandardButton::Yes)
  729. {
  730. canDeleteVariable = true;
  731. AZStd::unordered_set< AZ::EntityId > memberIds;
  732. memberIds.reserve(nodeIds.size());
  733. AZStd::unordered_set< ScriptCanvas::VariableId > variableIds = { variableId };
  734. for (auto memberPair : nodeIds)
  735. {
  736. bool removedReferences = false;
  737. ScriptCanvas::NodeRequestBus::EventResult(removedReferences, memberPair.m_scriptCanvasId, &ScriptCanvas::NodeRequests::RemoveVariableReferences, variableIds);
  738. // If we didn't remove the references. Just delete the node.
  739. if (!removedReferences)
  740. {
  741. memberIds.insert(memberPair.m_graphCanvasId);
  742. }
  743. }
  744. GraphCanvas::SceneRequestBus::Event(m_graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, memberIds);
  745. }
  746. }
  747. else
  748. {
  749. canDeleteVariable = true;
  750. }
  751. return canDeleteVariable;
  752. }
  753. VariablePropertiesComponent* VariableDockWidget::AllocateComponent(const ScriptCanvas::VariableId& variableId)
  754. {
  755. auto elementIter = m_usedElements.find(variableId);
  756. if (elementIter != m_usedElements.end())
  757. {
  758. return elementIter->second;
  759. }
  760. if (!m_unusedPool.empty())
  761. {
  762. VariablePropertiesComponent* component = m_unusedPool.back();
  763. m_unusedPool.pop_back();
  764. m_usedElements[variableId] = component;
  765. return component;
  766. }
  767. else
  768. {
  769. m_propertyHelpers.emplace_back(AZStd::unique_ptr<AZ::Entity>(VariablePropertiesComponent::CreateVariablePropertiesEntity()));
  770. AZ::Entity* entity = m_propertyHelpers.back().get();
  771. entity->Init();
  772. entity->Activate();
  773. VariablePropertiesComponent* component = AZ::EntityUtils::FindFirstDerivedComponent<VariablePropertiesComponent>(entity);
  774. if (component)
  775. {
  776. m_usedElements[variableId] = component;
  777. return component;
  778. }
  779. }
  780. return nullptr;
  781. }
  782. void VariableDockWidget::ReleaseComponent(const ScriptCanvas::VariableId& variableId)
  783. {
  784. auto mapIter = m_usedElements.find(variableId);
  785. if (mapIter != m_usedElements.end())
  786. {
  787. m_unusedPool.emplace_back(mapIter->second);
  788. m_usedElements.erase(mapIter);
  789. }
  790. }
  791. void VariableDockWidget::ResetPool()
  792. {
  793. for (auto pair : m_usedElements)
  794. {
  795. m_unusedPool.emplace_back(pair.second);
  796. }
  797. m_usedElements.clear();
  798. }
  799. #include <Editor/View/Widgets/VariablePanel/moc_VariableDockWidget.cpp>
  800. }