AssetTreeEntry.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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 "AssetTreeEntry.h"
  9. #include "EditorCommon.h"
  10. #include <AzCore/std/containers/map.h>
  11. #include <AzCore/Asset/AssetManager.h>
  12. #include <AzCore/Asset/AssetTypeInfoBus.h>
  13. #include <AzFramework/StringFunc/StringFunc.h>
  14. #include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
  15. #include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
  16. #include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
  17. UISliceLibraryFilter::UISliceLibraryFilter(const AZ::Data::AssetType& assetType, const AZStd::string& pathToSearch)
  18. : m_assetType(assetType)
  19. , m_pathToSearch(pathToSearch)
  20. {
  21. // propagation = Down means the filter will examine all children recursively until it satisfies or no more children are left
  22. // in our case we start from root entry and examine everything underneath it
  23. SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down);
  24. }
  25. AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter* UISliceLibraryFilter::Clone() const
  26. {
  27. auto clone = new UISliceLibraryFilter(m_assetType, m_pathToSearch.c_str());
  28. clone->m_name = m_name;
  29. clone->m_tag = m_tag;
  30. clone->m_direction = m_direction;
  31. return clone;
  32. }
  33. QString UISliceLibraryFilter::GetNameInternal() const
  34. {
  35. return "UISliceLibraryFilter";
  36. }
  37. bool UISliceLibraryFilter::MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const
  38. {
  39. // entry must be a product
  40. auto product = azrtti_cast<const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry*>(entry);
  41. if (!product)
  42. {
  43. return false;
  44. }
  45. // entry must be of slice asset type
  46. if (product->GetAssetType() != m_assetType)
  47. {
  48. return false;
  49. }
  50. // entry must be located within m_pathToSearch
  51. AZStd::string relativePath = product->GetRelativePath();
  52. AzFramework::StringFunc::AssetDatabasePath::Normalize(relativePath);
  53. if (AzFramework::StringFunc::Find(relativePath, m_pathToSearch.c_str()) == AZStd::string::npos)
  54. {
  55. return false;
  56. }
  57. return true;
  58. }
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////
  60. AssetTreeEntry::~AssetTreeEntry()
  61. {
  62. for (auto folderEntry : m_folders)
  63. {
  64. delete folderEntry.second;
  65. }
  66. }
  67. ////////////////////////////////////////////////////////////////////////////////////////////////////
  68. void AssetTreeEntry::Insert(const AZStd::string& path, const AZStd::string& menuName, const AZ::Data::AssetId& assetId)
  69. {
  70. if (path.empty())
  71. {
  72. // there are no more folders in the pathname - add the leaf file entry
  73. m_files.insert(AZStd::make_pair(menuName, assetId));
  74. }
  75. else
  76. {
  77. AZStd::string folderName;
  78. AZStd::string remainderPath;
  79. size_t separator = path.find('/');
  80. if (separator == AZStd::string::npos)
  81. {
  82. folderName = path;
  83. }
  84. else
  85. {
  86. folderName = path.substr(0, separator);
  87. if (path.length() > separator + 1)
  88. {
  89. remainderPath = path.substr(separator + 1);
  90. }
  91. }
  92. AssetTreeEntry* folderEntry = nullptr;
  93. // check if the folder already exists
  94. if (m_folders.count(folderName) == 0)
  95. {
  96. // does not exist, create it and insert it in tree
  97. folderEntry = new AssetTreeEntry;
  98. m_folders.insert(AZStd::make_pair(folderName, folderEntry));
  99. }
  100. else
  101. {
  102. // already exists
  103. folderEntry = m_folders[folderName];
  104. }
  105. // recurse down the pathname creating folders until we get to the leaf folder
  106. // to insert the file entry
  107. folderEntry->Insert(remainderPath, menuName, assetId);
  108. }
  109. }
  110. ////////////////////////////////////////////////////////////////////////////////////////////////////
  111. AssetTreeEntry* AssetTreeEntry::BuildAssetTree(const AZ::Data::AssetType& assetType, const AZStd::string& pathToSearch)
  112. {
  113. using namespace AzToolsFramework::AssetBrowser;
  114. // asset browser model is a collection of all assets. We search it from root entry down for all ui slice files.
  115. AssetBrowserModel* assetBrowserModel;
  116. AssetBrowserComponentRequestBus::BroadcastResult(assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel);
  117. AZ_Assert(assetBrowserModel, "Failed to get asset browser model");
  118. const auto rootEntry = assetBrowserModel->GetRootEntry();
  119. // UISliceLibraryFilter::Filter function returns all assets (recursively) that match the specified filter
  120. // in this case we are only looking for ui slices.
  121. AZStd::unordered_set<const AssetBrowserEntry*> entries;
  122. UISliceLibraryFilter filter(assetType, pathToSearch);
  123. filter.Filter(entries, rootEntry.get());
  124. AssetTreeEntry* assetTree = new AssetTreeEntry;
  125. for (const auto& entry : entries)
  126. {
  127. if (auto product = azrtti_cast<const ProductAssetBrowserEntry*>(entry); product)
  128. {
  129. AZStd::string name;
  130. AZStd::string path;
  131. // split the product relative path into name and path. Note that product's parent (source entry) is used because
  132. // product name stored in db is in all lower case, but we want to preserve case here
  133. AzFramework::StringFunc::Path::Split(product->GetParent()->GetRelativePath().c_str(), nullptr, &path, &name);
  134. // find next character position after default slice path in order to generate hierarchical sub-menus matching the subfolders
  135. const size_t pos = AzFramework::StringFunc::Find(path, pathToSearch) + pathToSearch.length();
  136. assetTree->Insert(path.substr(pos), name, product->GetAssetId());
  137. }
  138. }
  139. return assetTree;
  140. }