diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.h b/Code/Framework/AzCore/AzCore/IO/Path/Path.h index 61294cd637..6c1b519224 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.h +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.h @@ -95,6 +95,12 @@ namespace AZ::IO constexpr int Compare(AZStd::string_view pathString) const noexcept; constexpr int Compare(const value_type* pathString) const noexcept; + // Extension for fixed strings + //! extension: fixed string types with MaxPathLength capacity + //! Returns a new instance of an AZStd::fixed_string with capacity of MaxPathLength + //! made from the internal string + constexpr AZStd::fixed_string FixedMaxPathString() const noexcept; + // decomposition //! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of //! "/O3DE/foo/bar/name.txt" diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl index 1e42fc9df7..05a92c5247 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl @@ -915,6 +915,11 @@ namespace AZ::IO return compare_string_view(path); } + constexpr AZStd::fixed_string PathView::FixedMaxPathString() const noexcept + { + return AZStd::fixed_string(m_path.begin(), m_path.end()); + } + // decomposition constexpr auto PathView::RootName() const -> PathView { diff --git a/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp index 5efef8166c..68ba64ea1a 100644 --- a/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp @@ -14,6 +14,7 @@ #include "ProductAssetTreeItemData.h" #include +#include #include namespace AssetProcessor @@ -159,31 +160,33 @@ namespace AssetProcessor return; } + AZ::IO::Path productNamePath(product.m_productName, AZ::IO::PosixPathSeparator); - AZStd::vector tokens; - AzFramework::StringFunc::Tokenize(product.m_productName.c_str(), tokens, AZ_CORRECT_DATABASE_SEPARATOR, false, true); - - if (tokens.empty()) + if (productNamePath.empty()) { AZ_Warning("AssetProcessor", false, "Product id %d has an invalid name: %s", product.m_productID, product.m_productName.c_str()); return; } AssetTreeItem* parentItem = m_root.get(); - AZStd::string fullFolderName; - for (int i = 0; i < tokens.size() - 1; ++i) + AZ::IO::Path currentFullFolderPath; + const AZ::IO::PathView filename = productNamePath.Filename(); + const AZ::IO::PathView fullPathWithoutFilename = productNamePath.RemoveFilename(); + AZStd::fixed_string currentPath; + for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt) { - AzFramework::StringFunc::AssetDatabasePath::Join(fullFolderName.c_str(), tokens[i].c_str(), fullFolderName); - AssetTreeItem* nextParent = parentItem->GetChildFolder(tokens[i].c_str()); + currentPath = pathIt->FixedMaxPathString(); + currentFullFolderPath /= currentPath; + AssetTreeItem* nextParent = parentItem->GetChildFolder(currentPath.c_str()); if (!nextParent) { if (!modelIsResetting) { - QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem); + QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem); beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount()); } - nextParent = parentItem->CreateChild(ProductAssetTreeItemData::MakeShared(nullptr, fullFolderName, tokens[i].c_str(), true, AZ::Uuid::CreateNull())); - m_productToTreeItem[fullFolderName] = nextParent; + nextParent = parentItem->CreateChild(ProductAssetTreeItemData::MakeShared(nullptr, currentFullFolderPath.Native(), currentPath.c_str(), true, AZ::Uuid::CreateNull())); + m_productToTreeItem[currentFullFolderPath.Native()] = nextParent; // m_productIdToTreeItem is not used for folders, folders don't have product IDs. if (!modelIsResetting) @@ -205,12 +208,12 @@ namespace AssetProcessor if (!modelIsResetting) { - QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem); + QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem); beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount()); } AZStd::shared_ptr productItemData = - ProductAssetTreeItemData::MakeShared(&product, product.m_productName, tokens[tokens.size() - 1].c_str(), false, sourceId); + ProductAssetTreeItemData::MakeShared(&product, product.m_productName, AZStd::fixed_string(filename.Native()).c_str(), false, sourceId); m_productToTreeItem[product.m_productName] = parentItem->CreateChild(productItemData); m_productIdToTreeItem[product.m_productID] = m_productToTreeItem[product.m_productName]; diff --git a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp index dda0a58837..69e60f6733 100644 --- a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp @@ -63,8 +63,7 @@ namespace AssetProcessor } - auto fullPath = AZ::IO::Path(scanFolder.m_scanFolder) / source.m_sourceName; - + AZ::IO::Path fullPath = AZ::IO::Path(scanFolder.m_scanFolder, AZ::IO::PosixPathSeparator) / source.m_sourceName; // It's common for Open 3D Engine game projects and scan folders to be in a subfolder // of the engine install. To improve readability of the source files, strip out @@ -78,34 +77,35 @@ namespace AssetProcessor AzFramework::StringFunc::Replace(fullPath.Native(), m_assetRoot.absolutePath().toUtf8(), ""); } - - AZStd::vector tokens; - AzFramework::StringFunc::Tokenize(fullPath.c_str(), tokens, AZ_CORRECT_DATABASE_SEPARATOR, false, true); - - if (tokens.empty()) + if (fullPath.empty()) { - AZ_Warning("AssetProcessor", false, "Source id %s has an invalid name: %s", - source.m_sourceGuid.ToString().c_str(), source.m_sourceName.c_str()); + AZ_Warning( + "AssetProcessor", false, "Source id %s has an invalid name: %s", source.m_sourceGuid.ToString().c_str(), + source.m_sourceName.c_str()); return; } QModelIndex newIndicesStart; AssetTreeItem* parentItem = m_root.get(); - AZStd::string fullFolderName; - for (int i = 0; i < tokens.size() - 1; ++i) + AZ::IO::Path currentFullFolderPath; + const AZ::IO::PathView filename = fullPath.Filename(); + const AZ::IO::PathView fullPathWithoutFilename = fullPath.RemoveFilename(); + AZStd::fixed_string currentPath; + for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt) { - AzFramework::StringFunc::AssetDatabasePath::Join(fullFolderName.c_str(), tokens[i].c_str(), fullFolderName); - AssetTreeItem* nextParent = parentItem->GetChildFolder(tokens[i].c_str()); + currentPath = pathIt->FixedMaxPathString(); + currentFullFolderPath /= currentPath; + AssetTreeItem* nextParent = parentItem->GetChildFolder(currentPath.c_str()); if (!nextParent) { if (!modelIsResetting) { - QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem); + QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem); beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount()); } - nextParent = parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(nullptr, nullptr, fullFolderName, tokens[i].c_str(), true)); - m_sourceToTreeItem[fullFolderName] = nextParent; + nextParent = parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(nullptr, nullptr, currentFullFolderPath.Native(), currentPath.c_str(), true)); + m_sourceToTreeItem[currentFullFolderPath.Native()] = nextParent; // Folders don't have source IDs, don't add to m_sourceIdToTreeItem if (!modelIsResetting) { @@ -117,12 +117,12 @@ namespace AssetProcessor if (!modelIsResetting) { - QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem); + QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem); beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount()); } m_sourceToTreeItem[source.m_sourceName] = - parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, tokens[tokens.size() - 1].c_str(), false)); + parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, AZStd::fixed_string(filename.Native()).c_str(), false)); m_sourceIdToTreeItem[source.m_sourceID] = m_sourceToTreeItem[source.m_sourceName]; if (!modelIsResetting) {