3
0

ScriptCanvasStatisticsDialog.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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 <AzCore/Asset/AssetManagerBus.h>
  9. #include <AzQtComponents/Components/StyleManager.h>
  10. #include <Editor/View/Widgets/StatisticsDialog/ScriptCanvasStatisticsDialog.h>
  11. #include <Editor/View/Widgets/StatisticsDialog/ui_ScriptCanvasStatisticsDialog.h>
  12. #include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
  13. #include <ScriptCanvas/Bus/RequestBus.h>
  14. namespace
  15. {
  16. ScriptCanvasEditor::NodePaletteNodeUsageRootItem* ExternalCreatePaletteRoot(const ScriptCanvasEditor::NodePaletteModel& nodePaletteModel, AZStd::unordered_map< ScriptCanvas::NodeTypeIdentifier, GraphCanvas::GraphCanvasTreeItem* >& leafMap)
  17. {
  18. ScriptCanvasEditor::NodePaletteNodeUsageRootItem* root = aznew ScriptCanvasEditor::NodePaletteNodeUsageRootItem(nodePaletteModel);
  19. const ScriptCanvasEditor::NodePaletteModel::NodePaletteRegistry& nodeRegistry = nodePaletteModel.GetNodeRegistry();
  20. for (const auto& registryPair : nodeRegistry)
  21. {
  22. const ScriptCanvasEditor::NodePaletteModelInformation* modelInformation = registryPair.second;
  23. GraphCanvas::GraphCanvasTreeItem* parentItem = root->GetCategoryNode(modelInformation->m_categoryPath.c_str());
  24. GraphCanvas::NodePaletteTreeItem* createdItem = nullptr;
  25. createdItem = parentItem->CreateChildNode<ScriptCanvasEditor::NodePaletteNodeUsagePaletteItem>(modelInformation->m_nodeIdentifier, modelInformation->m_displayName);
  26. if (createdItem)
  27. {
  28. modelInformation->PopulateTreeItem((*createdItem));
  29. leafMap[modelInformation->m_nodeIdentifier] = createdItem;
  30. }
  31. }
  32. root->PruneEmptyNodes();
  33. return root;
  34. }
  35. }
  36. namespace ScriptCanvasEditor
  37. {
  38. //////////////////////////////////////////
  39. // ScriptCanvasAssetNodeUsageFilterModel
  40. //////////////////////////////////////////
  41. ScriptCanvasAssetNodeUsageFilterModel::ScriptCanvasAssetNodeUsageFilterModel()
  42. : m_nodeIdentifier(0)
  43. {
  44. }
  45. bool ScriptCanvasAssetNodeUsageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
  46. {
  47. // Never want to show something if we don't have a node type identifier
  48. if (m_nodeIdentifier == 0)
  49. {
  50. return false;
  51. }
  52. QAbstractItemModel* model = sourceModel();
  53. QModelIndex index = model->index(sourceRow, 0, sourceParent);
  54. ScriptCanvasAssetNodeUsageTreeItem* treeItem = static_cast<ScriptCanvasAssetNodeUsageTreeItem*>(index.internalPointer());
  55. if (!treeItem->GetAssetId().IsValid())
  56. {
  57. for (int i = 0; i < treeItem->GetChildCount(); ++i)
  58. {
  59. if (filterAcceptsRow(i, index))
  60. {
  61. return true;
  62. }
  63. }
  64. }
  65. else
  66. {
  67. treeItem->SetActiveNodeType(m_nodeIdentifier);
  68. if (treeItem->GetNodeCount() == 0)
  69. {
  70. return false;
  71. }
  72. bool showRow = m_filter.isEmpty();
  73. if (!showRow)
  74. {
  75. const QString& name = treeItem->GetName();
  76. int regexIndex = name.lastIndexOf(m_regex);
  77. showRow = regexIndex >= 0;
  78. if (!showRow)
  79. {
  80. ScriptCanvasAssetNodeUsageTreeItem* parentItem = static_cast<ScriptCanvasAssetNodeUsageTreeItem*>(treeItem->GetParent());
  81. while (!showRow && parentItem)
  82. {
  83. ScriptCanvasAssetNodeUsageTreeItem* nextItem = static_cast<ScriptCanvasAssetNodeUsageTreeItem*>(parentItem->GetParent());
  84. // This means we are the root element. And we don't want to match based on it.
  85. if (nextItem == nullptr)
  86. {
  87. break;
  88. }
  89. const QString& parentName = parentItem->GetName();
  90. int regexIndex2 = parentName.lastIndexOf(m_regex);
  91. if (regexIndex2 >= 0)
  92. {
  93. showRow = true;
  94. }
  95. parentItem = nextItem;
  96. }
  97. }
  98. }
  99. return showRow;
  100. }
  101. return false;
  102. }
  103. void ScriptCanvasAssetNodeUsageFilterModel::SetFilter(const QString& filterName)
  104. {
  105. m_filter = filterName;
  106. m_regex = QRegExp(m_filter, Qt::CaseInsensitive);
  107. invalidate();
  108. }
  109. void ScriptCanvasAssetNodeUsageFilterModel::SetNodeTypeFilter(const ScriptCanvas::NodeTypeIdentifier& nodeType)
  110. {
  111. m_nodeIdentifier = nodeType;
  112. invalidate();
  113. }
  114. /////////////////////
  115. // StatisticsDialog
  116. /////////////////////
  117. StatisticsDialog::StatisticsDialog(const NodePaletteModel& nodePaletteModel, AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* scriptCanvasAssetBrowserModel, QWidget* widget)
  118. : QDialog(widget)
  119. , m_nodePaletteModel(nodePaletteModel)
  120. , m_ui(new Ui::ScriptCanvasStatisticsDialog())
  121. , m_treeRoot(nullptr)
  122. , m_scriptCanvasAssetBrowserModel(scriptCanvasAssetBrowserModel)
  123. , m_scriptCanvasAssetTreeRoot(nullptr)
  124. , m_scriptCanvasAssetTree(nullptr)
  125. , m_scriptCanvasAssetFilterModel(nullptr)
  126. {
  127. setWindowFlags(Qt::WindowFlags::enum_type::WindowCloseButtonHint);
  128. m_ui->setupUi(this);
  129. AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("style:Editor.qss"));
  130. }
  131. StatisticsDialog::~StatisticsDialog()
  132. {
  133. }
  134. void StatisticsDialog::OnCatalogAssetChanged(const AZ::Data::AssetId& /*assetId*/)
  135. {
  136. // #sc_editor_asset_redux cut or update
  137. // AZ::Data::AssetInfo assetInfo;
  138. // AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, assetId);
  139. // if (assetInfo.m_assetType == azrtti_typeid<OldAssetType())
  140. // {
  141. // m_scriptCanvasAssetTreeRoot->RegisterAsset(assetId, assetInfo.m_assetType);
  142. // }
  143. }
  144. void StatisticsDialog::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
  145. {
  146. OnCatalogAssetChanged(assetId);
  147. }
  148. void StatisticsDialog::OnCatalogAssetRemoved(const AZ::Data::AssetId& /*assetId*/, const AZ::Data::AssetInfo& /*assetInfo*/)
  149. {
  150. // #sc_editor_asset_redux cut or update
  151. // AZ::Data::AssetInfo assetInfo;
  152. // AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, assetId);
  153. // if (assetInfo.m_assetType == azrtti_typeid<OldAssetType>())
  154. // {
  155. // m_scriptCanvasAssetTreeRoot->RemoveAsset(assetId);
  156. // }
  157. }
  158. void StatisticsDialog::OnAssetModelRepopulated()
  159. {
  160. ResetModel();
  161. }
  162. void StatisticsDialog::OnAssetNodeAdded(NodePaletteModelInformation* modelInformation)
  163. {
  164. auto leafIter = m_leafMap.find(modelInformation->m_nodeIdentifier);
  165. if (leafIter != m_leafMap.end())
  166. {
  167. // Duplicate Id. Ignore for now.
  168. return;
  169. }
  170. GraphCanvas::GraphCanvasTreeItem* parentItem = m_treeRoot->GetCategoryNode(modelInformation->m_categoryPath.c_str());
  171. GraphCanvas::NodePaletteTreeItem* createdItem = nullptr;
  172. createdItem = parentItem->CreateChildNode<ScriptCanvasEditor::NodePaletteNodeUsagePaletteItem>(modelInformation->m_nodeIdentifier, modelInformation->m_displayName);
  173. if (createdItem)
  174. {
  175. modelInformation->PopulateTreeItem((*createdItem));
  176. m_leafMap[modelInformation->m_nodeIdentifier] = createdItem;
  177. }
  178. else
  179. {
  180. m_treeRoot->PruneEmptyNodes();
  181. }
  182. }
  183. void StatisticsDialog::OnAssetNodeRemoved(NodePaletteModelInformation* modelInformation)
  184. {
  185. auto leafIter = m_leafMap.find(modelInformation->m_nodeIdentifier);
  186. if (leafIter != m_leafMap.end())
  187. {
  188. leafIter->second->DetachItem();
  189. delete leafIter->second;
  190. m_leafMap.erase(leafIter);
  191. m_treeRoot->PruneEmptyNodes();
  192. }
  193. }
  194. void StatisticsDialog::OnScriptCanvasAssetClicked(const QModelIndex& index)
  195. {
  196. if (index.isValid())
  197. {
  198. if (index.column() == ScriptCanvasAssetNodeUsageTreeItem::Column::OpenIcon)
  199. {
  200. QModelIndex sourceIndex = m_scriptCanvasAssetFilterModel->mapToSource(index);
  201. ScriptCanvasAssetNodeUsageTreeItem* treeItem = static_cast<ScriptCanvasAssetNodeUsageTreeItem*>(sourceIndex.internalPointer());
  202. if (treeItem->GetAssetId().IsValid())
  203. {
  204. GeneralRequestBus::Broadcast
  205. ( &GeneralRequests::OpenScriptCanvasAssetId
  206. , SourceHandle(nullptr, treeItem->GetAssetId().m_guid)
  207. , Tracker::ScriptCanvasFileState::UNMODIFIED);
  208. }
  209. }
  210. }
  211. }
  212. void StatisticsDialog::showEvent(QShowEvent* showEvent)
  213. {
  214. InitStatisticsWindow();
  215. QDialog::showEvent(showEvent);
  216. }
  217. void StatisticsDialog::OnSelectionCleared()
  218. {
  219. m_scriptCanvasAssetFilterModel->SetNodeTypeFilter(0);
  220. m_ui->statDisplayName->setText("N/A");
  221. m_ui->totalUsageCount->setText(QString::number(0));
  222. m_ui->uniqueGraphsCount->setText(QString::number(0));
  223. m_ui->averageGraphUsages->setText(QString::number(0));
  224. }
  225. void StatisticsDialog::OnItemSelected(const GraphCanvas::GraphCanvasTreeItem* treeItem)
  226. {
  227. const NodePaletteNodeUsagePaletteItem* usageItem = azrtti_cast<const NodePaletteNodeUsagePaletteItem*>(treeItem);
  228. if (usageItem)
  229. {
  230. m_scriptCanvasAssetFilterModel->SetNodeTypeFilter(usageItem->GetNodeTypeIdentifier());
  231. m_ui->scriptCanvasAssetTree->expandAll();
  232. const ScriptCanvasAssetNodeUsageTreeItemRoot::ScriptCanvasAssetMap& assetMapping = m_scriptCanvasAssetTreeRoot->GetAssetTreeItems();
  233. int totalNodeCount = 0;
  234. int uniqueGraphs = 0;
  235. for (auto itemPair : assetMapping)
  236. {
  237. int nodeCount = itemPair.second->GetNodeCount();
  238. if (nodeCount > 0)
  239. {
  240. totalNodeCount += nodeCount;
  241. uniqueGraphs++;
  242. }
  243. }
  244. m_ui->statDisplayName->setText(usageItem->GetName());
  245. m_ui->totalUsageCount->setText(QString::number(totalNodeCount));
  246. m_ui->uniqueGraphsCount->setText(QString::number(uniqueGraphs));
  247. float averageUses = 0;
  248. if (uniqueGraphs != 0)
  249. {
  250. averageUses = static_cast<float>(totalNodeCount) / static_cast<float>(uniqueGraphs);
  251. }
  252. m_ui->averageGraphUsages->setText(QString::number(averageUses, 'g', 2));
  253. }
  254. else
  255. {
  256. OnSelectionCleared();
  257. }
  258. }
  259. void StatisticsDialog::OnFilterUpdated(const QString& filterText)
  260. {
  261. m_scriptCanvasAssetFilterModel->SetFilter(filterText);
  262. m_ui->scriptCanvasAssetTree->expandAll();
  263. }
  264. void StatisticsDialog::OnScriptCanvasAssetRowsInserted(QModelIndex parentIndex, int first, int last)
  265. {
  266. for (int i = first; i <= last; ++i)
  267. {
  268. QModelIndex modelIndex = m_scriptCanvasAssetBrowserModel->index(first, 0, parentIndex);
  269. QModelIndex sourceIndex = m_scriptCanvasAssetBrowserModel->mapToSource(modelIndex);
  270. const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry = reinterpret_cast<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>(sourceIndex.internalPointer());
  271. ProcessAsset(entry);
  272. }
  273. }
  274. void StatisticsDialog::InitStatisticsWindow()
  275. {
  276. if (m_treeRoot == nullptr)
  277. {
  278. m_treeRoot = ExternalCreatePaletteRoot(m_nodePaletteModel, m_leafMap);
  279. GraphCanvas::NodePaletteConfig paletteConfig;
  280. paletteConfig.m_rootTreeItem = m_treeRoot;
  281. paletteConfig.m_editorId = ScriptCanvasEditor::AssetEditorId;
  282. paletteConfig.m_mimeType = "";
  283. paletteConfig.m_isInContextMenu = false;
  284. paletteConfig.m_saveIdentifier = "ScriptCanvas_UsageStatistics";
  285. paletteConfig.m_clearSelectionOnSceneChange = false;
  286. paletteConfig.m_allowArrowKeyNavigation = true;
  287. m_ui->nodePaletteWidget->SetupNodePalette(paletteConfig);
  288. m_scriptCanvasAssetTreeRoot = aznew ScriptCanvasAssetNodeUsageTreeItemRoot();
  289. m_scriptCanvasAssetTree = aznew GraphCanvas::GraphCanvasTreeModel(m_scriptCanvasAssetTreeRoot);
  290. m_scriptCanvasAssetFilterModel = aznew ScriptCanvasAssetNodeUsageFilterModel();
  291. m_scriptCanvasAssetFilterModel->setSourceModel(m_scriptCanvasAssetTree);
  292. TraverseTree();
  293. AzFramework::AssetCatalogEventBus::Handler::BusConnect();
  294. m_ui->scriptCanvasAssetTree->setModel(m_scriptCanvasAssetFilterModel);
  295. m_ui->splitter->setStretchFactor(0, 1);
  296. m_ui->splitter->setStretchFactor(1, 2);
  297. m_ui->searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(250));
  298. m_ui->scriptCanvasAssetTree->header()->setSectionResizeMode(ScriptCanvasAssetNodeUsageTreeItem::Column::Name, QHeaderView::ResizeMode::ResizeToContents);
  299. m_ui->scriptCanvasAssetTree->header()->setSectionResizeMode(ScriptCanvasAssetNodeUsageTreeItem::Column::UsageCount, QHeaderView::ResizeMode::Fixed);
  300. m_ui->scriptCanvasAssetTree->header()->resizeSection(ScriptCanvasAssetNodeUsageTreeItem::Column::UsageCount, 30);
  301. QObject::connect(m_ui->scriptCanvasAssetTree, &QTreeView::clicked, this, &StatisticsDialog::OnScriptCanvasAssetClicked);
  302. QObject::connect(m_ui->nodePaletteWidget, &GraphCanvas::NodePaletteWidget::OnSelectionCleared, this, &StatisticsDialog::OnSelectionCleared);
  303. QObject::connect(m_ui->nodePaletteWidget, &GraphCanvas::NodePaletteWidget::OnTreeItemSelected, this, &StatisticsDialog::OnItemSelected);
  304. QObject::connect(m_ui->searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, this, &StatisticsDialog::OnFilterUpdated);
  305. QObject::connect(m_scriptCanvasAssetBrowserModel, &QAbstractItemModel::rowsInserted, this, &StatisticsDialog::OnScriptCanvasAssetRowsInserted);
  306. OnSelectionCleared();
  307. NodePaletteModelNotificationBus::Handler::BusConnect(m_nodePaletteModel.GetNotificationId());
  308. }
  309. }
  310. void StatisticsDialog::ResetModel()
  311. {
  312. if (m_treeRoot)
  313. {
  314. m_leafMap.clear();
  315. m_treeRoot = ExternalCreatePaletteRoot(m_nodePaletteModel, m_leafMap);
  316. m_ui->nodePaletteWidget->ResetModel(m_treeRoot);
  317. }
  318. }
  319. void StatisticsDialog::TraverseTree(QModelIndex index)
  320. {
  321. QModelIndex sourceIndex = m_scriptCanvasAssetBrowserModel->mapToSource(index);
  322. AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry = reinterpret_cast<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>(sourceIndex.internalPointer());
  323. ProcessAsset(entry);
  324. int rowCount = m_scriptCanvasAssetBrowserModel->rowCount(index);
  325. for (int i = 0; i < rowCount; ++i)
  326. {
  327. QModelIndex nextIndex = m_scriptCanvasAssetBrowserModel->index(i, 0, index);
  328. TraverseTree(nextIndex);
  329. }
  330. }
  331. void StatisticsDialog::ProcessAsset([[maybe_unused]] const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
  332. {
  333. // #sc_editor_asset_redux cut or update
  334. // if (entry)
  335. // {
  336. // if (entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product)
  337. // {
  338. // const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry* productEntry = static_cast<const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry*>(entry);
  339. //
  340. // if (productEntry->GetAssetType() == azrtti_typeid<OldAssetType>())
  341. // {
  342. // const AZ::Data::AssetId& assetId = productEntry->GetAssetId();
  343. //
  344. // m_scriptCanvasAssetTreeRoot->RegisterAsset(assetId, productEntry->GetAssetType());
  345. // }
  346. // }
  347. // }
  348. }
  349. #include <Editor/View/Widgets/StatisticsDialog/moc_ScriptCanvasStatisticsDialog.cpp>
  350. }