Explorar o código

Squashing asset browser filter changes moving to development branch

Signed-off-by: Guthrie Adams <[email protected]>
Guthrie Adams hai 1 ano
pai
achega
3d3d959a6c
Modificáronse 28 ficheiros con 669 adicións e 663 borrados
  1. 4 2
      Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp
  2. 9 19
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp
  3. 1 2
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h
  4. 4 6
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableViewProxyModel.cpp
  5. 1 2
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableViewProxyModel.h
  6. 4 5
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserThumbnailViewProxyModel.cpp
  7. 1 1
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserThumbnailViewProxyModel.h
  8. 81 31
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTreeToTableProxyModel.cpp
  9. 6 2
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp
  10. 39 0
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp
  11. 14 0
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h
  12. 2 7
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryUtils.cpp
  13. 6 1
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp
  14. 206 288
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp
  15. 56 50
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h
  16. 11 19
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserListView.cpp
  17. 141 151
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp
  18. 32 43
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserThumbnailView.cpp
  19. 16 22
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp
  20. 4 4
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp
  21. 2 2
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h
  22. 1 1
      Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/Model/AssetCompleterModel.cpp
  23. 1 1
      Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/Model/AssetCompleterModel.h
  24. 0 2
      Gems/GraphModel/Code/Include/GraphModel/Model/Slot.h
  25. 1 1
      Gems/GraphModel/Code/Source/Model/Slot.cpp
  26. 10 1
      Gems/LyShine/Code/Editor/AssetTreeEntry.cpp
  27. 1 0
      Gems/LyShine/Code/Editor/AssetTreeEntry.h
  28. 15 0
      README.md

+ 4 - 2
Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp

@@ -116,8 +116,6 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent)
     AZ_Assert(m_assetBrowserModel, "Failed to get filebrowser model");
     m_filterModel->setSourceModel(m_assetBrowserModel);
     m_filterModel->SetFilter(m_ui->m_searchWidget->GetFilter());
-    // Turn off DynamicSort as sorting is now manual.
-    m_filterModel->setDynamicSortFilter(false);
 
     m_ui->m_assetBrowserListViewWidget->setVisible(false);
     m_ui->m_toolsMenuButton->setVisible(false);
@@ -523,6 +521,10 @@ void AzAssetBrowserWindow::CreateToolsMenu()
         m_toolsMenu->addAction(openNewAction);
 
         m_toolsMenu->addSeparator();
+        auto* expandAllAction = new QAction(tr("Expand All"), this);
+        connect(expandAllAction, &QAction::triggered, this, [this] { m_ui->m_assetBrowserTreeViewWidget->expandAll(); });
+        m_toolsMenu->addAction(expandAllAction);
+
         auto* collapseAllAction = new QAction(tr("Collapse All"), this);
         connect(collapseAllAction, &QAction::triggered, this, [this] { m_ui->m_assetBrowserTreeViewWidget->collapseAll(); });
         m_toolsMenu->addAction(collapseAllAction);

+ 9 - 19
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp

@@ -39,6 +39,8 @@ namespace AzToolsFramework
             : QSortFilterProxyModel(parent)
             , m_isTableView(isTableView)
         {
+            setDynamicSortFilter(true);
+            setRecursiveFilteringEnabled(true);
             m_shownColumns.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName));
             if (ed_useNewAssetBrowserListView)
             {
@@ -107,11 +109,11 @@ namespace AzToolsFramework
             {
                 if (index.column() == aznumeric_cast<int>(AssetBrowserEntry::Column::Name))
                 {
-                    QString name = static_cast<const SourceAssetBrowserEntry*>(assetBrowserEntry)->GetName().c_str();
-
-                    if (!m_searchString.empty())
+                    const QString name = assetBrowserEntry->GetName().c_str();
+                    if (!m_searchString.isEmpty())
                     {
-                        name = AzToolsFramework::RichTextHighlighter::HighlightText(name, m_searchString.c_str());
+                        // highlight characters in filter
+                        return AzToolsFramework::RichTextHighlighter::HighlightText(name, m_searchString);
                     }
                     return name;
                 }
@@ -132,7 +134,7 @@ namespace AzToolsFramework
 
         void AssetBrowserFilterModel::SetSearchString(const QString& searchString)
         {
-            m_searchString = searchString.toUtf8().data();
+            m_searchString = searchString;
         }
 
         bool AssetBrowserFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
@@ -161,7 +163,7 @@ namespace AzToolsFramework
             {
                 return true;
             }
-            return m_filter->Match(entry);
+            return m_filter->MatchWithoutPropagation(entry);
         }
 
         bool AssetBrowserFilterModel::filterAcceptsColumn(int source_column, const QModelIndex&) const
@@ -194,18 +196,6 @@ namespace AzToolsFramework
             if (compFilter)
             {
                 const auto& subFilters = compFilter->GetSubFilters();
-                const auto& compFilterIter = AZStd::find_if(subFilters.cbegin(), subFilters.cend(),
-                    [](FilterConstType filter) -> bool
-                    {
-                        const auto assetTypeFilter = qobject_cast<QSharedPointer<const CompositeFilter>>(filter);
-                        return !assetTypeFilter.isNull();
-                    });
-
-                if (compFilterIter != subFilters.end())
-                {
-                    m_assetTypeFilter = qobject_cast<QSharedPointer<const CompositeFilter>>(*compFilterIter);
-                }
-
                 const auto& compositeStringFilterIter = AZStd::find_if(subFilters.cbegin(), subFilters.cend(),
                     [](FilterConstType filter) -> bool
                     {
@@ -246,8 +236,8 @@ namespace AzToolsFramework
                     }
                 }
             }
+
             invalidateFilter();
-            
             Q_EMIT filterChanged();
         }
 

+ 1 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h

@@ -84,7 +84,6 @@ namespace AzToolsFramework
             FilterConstType m_filter;
             AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...'
             QSharedPointer<const StringFilter> m_stringFilter;
-            QWeakPointer<const CompositeFilter> m_assetTypeFilter;
             QCollator m_collator;  // cache the collator as its somewhat expensive to constantly create and destroy one.
             AZ_POP_DISABLE_WARNING
             bool m_invalidateFilter = false;
@@ -93,7 +92,7 @@ namespace AzToolsFramework
             AssetBrowserEntry::AssetEntrySortMode m_sortMode = AssetBrowserEntry::AssetEntrySortMode::Name;
             Qt::SortOrder m_sortOrder = Qt::DescendingOrder;
  
-            AZStd::string m_searchString = "";
+            QString m_searchString;
         };
     } // namespace AssetBrowser
 } // namespace AzToolsFramework

+ 4 - 6
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableViewProxyModel.cpp

@@ -42,12 +42,11 @@ namespace AzToolsFramework
                     {
                     case Name:
                         {
-                            QString name = static_cast<const SourceAssetBrowserEntry*>(assetBrowserEntry)->GetName().c_str();
-
-                            if (!m_searchString.empty())
+                            const QString name = assetBrowserEntry->GetName().c_str();
+                            if (!m_searchString.isEmpty())
                             {
                                 // highlight characters in filter
-                                name = AzToolsFramework::RichTextHighlighter::HighlightText(name, m_searchString.c_str());
+                                return AzToolsFramework::RichTextHighlighter::HighlightText(name, m_searchString);
                             }
                             return name;
                         }
@@ -183,7 +182,6 @@ namespace AzToolsFramework
             }
         }
         
-
         bool AssetBrowserTableViewProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
         {
             if (action == Qt::IgnoreAction)
@@ -244,7 +242,7 @@ namespace AzToolsFramework
 
         void AssetBrowserTableViewProxyModel::SetSearchString(const QString& searchString)
         {
-             m_searchString = searchString.toUtf8().data();
+            m_searchString = searchString;
         }
     } // namespace AssetBrowser
 } // namespace AzToolsFramework

+ 1 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableViewProxyModel.h

@@ -51,8 +51,7 @@ namespace AzToolsFramework
         private:
             QPersistentModelIndex m_rootIndex;
             bool m_searchResultsMode;
-
-            AZStd::string m_searchString = "";
+            QString m_searchString;
         };
     } // namespace AssetBrowser
 } // namespace AzToolsFramework

+ 4 - 5
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserThumbnailViewProxyModel.cpp

@@ -43,12 +43,11 @@ namespace AzToolsFramework
             {
             case Qt::DisplayRole:
                 {
-                    QString name = static_cast<const SourceAssetBrowserEntry*>(assetBrowserEntry)->GetName().c_str();
-
-                    if (!m_searchString.empty())
+                    const QString name = assetBrowserEntry->GetName().c_str();
+                    if (!m_searchString.isEmpty())
                     {
                         // highlight characters in filter
-                        name = AzToolsFramework::RichTextHighlighter::HighlightText(name, m_searchString.c_str());
+                        return AzToolsFramework::RichTextHighlighter::HighlightText(name, m_searchString);
                     }
                     return name;
                 }
@@ -128,7 +127,7 @@ namespace AzToolsFramework
 
         void AssetBrowserThumbnailViewProxyModel::SetSearchString(const QString& searchString)
         {
-            m_searchString = searchString.toUtf8().data();
+            m_searchString = searchString;
         }
 
         Qt::DropActions AssetBrowserThumbnailViewProxyModel::supportedDropActions() const

+ 1 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserThumbnailViewProxyModel.h

@@ -46,7 +46,7 @@ namespace AzToolsFramework
         private:
             QPersistentModelIndex m_rootIndex;
             bool m_searchResultsMode;
-            AZStd::string m_searchString;
+            QString m_searchString;
         };
     } // namespace AssetBrowser
 } // namespace AzToolsFramework

+ 81 - 31
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTreeToTableProxyModel.cpp

@@ -5,9 +5,10 @@
  * SPDX-License-Identifier: Apache-2.0 OR MIT
  *
  */
-#include <AzToolsFramework/AssetBrowser/AssetBrowserTreeToTableProxyModel.h>
-#include <AzCore/std/functional.h>
+
 #include <AzCore/Debug/Trace.h>
+#include <AzCore/std/functional.h>
+#include <AzToolsFramework/AssetBrowser/AssetBrowserTreeToTableProxyModel.h>
 
 namespace AzToolsFramework
 {
@@ -105,86 +106,128 @@ namespace AzToolsFramework
         {
             beginResetModel();
 
-            if (sourceModel())
+            auto sourceModelPtr = sourceModel();
+            if (sourceModelPtr)
             {
-                disconnect(sourceModel(), nullptr, this, nullptr);
+                disconnect(sourceModelPtr, nullptr, this, nullptr);
             }
 
             QAbstractProxyModel::setSourceModel(model);
             if (model)
             {
-                connect(model, &QAbstractItemModel::rowsAboutToBeInserted, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::rowsAboutToBeInserted,
+                    this,
                     [this](const QModelIndex& parent, int start, int end)
                     {
                         RowsAboutToBeInserted(parent, start, end);
                     });
 
-                connect(model, &QAbstractItemModel::rowsInserted, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::rowsInserted,
+                    this,
                     [this](const QModelIndex& parent, int start, int end)
                     {
                         RowsInserted(parent, start, end);
                     });
 
-                connect(model, &QAbstractItemModel::rowsAboutToBeRemoved, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::rowsAboutToBeRemoved,
+                    this,
                     [this](const QModelIndex& parent, int start, int end)
                     {
                         RowsAboutToBeRemoved(parent, start, end);
                     });
 
-                connect(model, &QAbstractItemModel::rowsRemoved, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::rowsRemoved,
+                    this,
                     [this](const QModelIndex& parent, int start)
                     {
                         RowsRemoved(parent, start);
                     });
 
-                connect(model, &QAbstractItemModel::rowsAboutToBeMoved, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::rowsAboutToBeMoved,
+                    this,
                     [this]()
                     {
                         LayoutChanged();
                     });
 
-                connect(model, &QAbstractItemModel::rowsMoved, this,
-                    [this](const QModelIndex& srcParent, int srcStart, [[maybe_unused]]int srcEnd, const QModelIndex& destParent, int destStart)
+                connect(
+                    model,
+                    &QAbstractItemModel::rowsMoved,
+                    this,
+                    [this](
+                        const QModelIndex& srcParent,
+                        int srcStart,
+                        [[maybe_unused]] int srcEnd,
+                        const QModelIndex& destParent,
+                        int destStart)
                     {
                         RowsMoved(srcParent, srcStart, destParent, destStart);
                     });
 
-                connect(model, &QAbstractItemModel::modelAboutToBeReset, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::modelAboutToBeReset,
+                    this,
                     [this]()
                     {
                         beginResetModel();
                     });
 
-                connect(model, &QAbstractItemModel::modelReset, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::modelReset,
+                    this,
                     [this]()
                     {
                         ModelReset();
                     });
 
-                connect(model, &QAbstractItemModel::dataChanged, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::dataChanged,
+                    this,
                     [this](const QModelIndex& topLeft, const QModelIndex& bottomRight)
                     {
                         DataChanged(topLeft, bottomRight);
                     });
 
-                connect(model, &QAbstractItemModel::layoutAboutToBeChanged, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::layoutAboutToBeChanged,
+                    this,
                     [this]()
                     {
                         LayoutAboutToBeChanged();
                     });
 
-                connect(model, &QAbstractItemModel::layoutChanged, this,
+                connect(
+                    model,
+                    &QAbstractItemModel::layoutChanged,
+                    this,
                     [this]()
                     {
                         LayoutChanged();
                     });
 
-                connect(model, &QObject::destroyed, this,
+                connect(
+                    model,
+                    &QObject::destroyed,
+                    this,
                     [this]()
                     {
                         resetInternalData();
                     });
-             }
+            }
 
             resetInternalData();
             if (model && model->hasChildren())
@@ -196,12 +239,13 @@ namespace AzToolsFramework
 
         QVariant AssetBrowserTreeToTableProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
         {
-            if (!sourceModel() || columnCount() <= section)
+            auto sourceModelPtr = sourceModel();
+            if (!sourceModelPtr || columnCount() <= section)
             {
                 return QVariant();
             }
 
-            return sourceModel()->headerData(section, orientation, role);
+            return sourceModelPtr->headerData(section, orientation, role);
         }
 
         QModelIndex AssetBrowserTreeToTableProxyModel::parent([[maybe_unused]] const QModelIndex& index) const
@@ -367,12 +411,13 @@ namespace AzToolsFramework
 
         int AssetBrowserTreeToTableProxyModel::columnCount(const QModelIndex& parent) const
         {
-            if (parent.isValid() || !sourceModel())
+            auto sourceModelPtr = sourceModel();
+            if (parent.isValid() || !sourceModelPtr)
             {
                 return 0;
             }
 
-            return sourceModel()->columnCount();
+            return sourceModelPtr->columnCount();
         }
 
         void AssetBrowserTreeToTableProxyModel::UpdateInternalIndices(int start, int offset)
@@ -385,7 +430,7 @@ namespace AzToolsFramework
             {
                 updates.insert(it.key() + offset, *it);
             }
-              
+
             const QHash<int, QPersistentModelIndex>::const_iterator end2 = updates.constEnd();
 
             for (QHash<int, QPersistentModelIndex>::const_iterator it = updates.constBegin(); it != end2; ++it)
@@ -712,7 +757,8 @@ namespace AzToolsFramework
 
         QModelIndex AssetBrowserTreeToTableProxyModel::mapFromSource(const QModelIndex& sourceIndex) const
         {
-            if (!sourceModel())
+            auto sourceModelPtr = sourceModel();
+            if (!sourceModelPtr)
             {
                 return QModelIndex();
             }
@@ -770,7 +816,8 @@ namespace AzToolsFramework
 
         QModelIndex AssetBrowserTreeToTableProxyModel::mapToSource(const QModelIndex& proxyIndex) const
         {
-            if (m_map.Empty() || !proxyIndex.isValid() || !sourceModel())
+            auto sourceModelPtr = sourceModel();
+            if (m_map.Empty() || !proxyIndex.isValid() || !sourceModelPtr)
             {
                 return QModelIndex();
             }
@@ -814,23 +861,25 @@ namespace AzToolsFramework
 
         Qt::ItemFlags AssetBrowserTreeToTableProxyModel::flags(const QModelIndex& index) const
         {
-            if (!index.isValid() || !sourceModel())
+            auto sourceModelPtr = sourceModel();
+            if (!index.isValid() || !sourceModelPtr)
             {
                 return QAbstractProxyModel::flags(index);
             }
 
             const QModelIndex srcIndex = mapToSource(index);
-            return sourceModel()->flags(srcIndex);
+            return sourceModelPtr->flags(srcIndex);
         }
 
         int AssetBrowserTreeToTableProxyModel::rowCount(const QModelIndex& parent) const
         {
-            if (m_parents.contains(parent) || parent.isValid() || !sourceModel())
+            auto sourceModelPtr = sourceModel();
+            if (m_parents.contains(parent) || parent.isValid() || !sourceModelPtr)
             {
                 return 0;
             }
 
-            if (m_map.Empty() && sourceModel()->hasChildren())
+            if (m_map.Empty() && sourceModelPtr->hasChildren())
             {
                 const_cast<AssetBrowserTreeToTableProxyModel*>(this)->RefreshMap();
             }
@@ -839,14 +888,15 @@ namespace AzToolsFramework
 
         QVariant AssetBrowserTreeToTableProxyModel::data(const QModelIndex& index, int role) const
         {
-            if (!sourceModel())
+            auto sourceModelPtr = sourceModel();
+            if (!sourceModelPtr)
             {
                 return QVariant();
             }
 
             if (!index.isValid())
             {
-                return sourceModel()->data(index, role);
+                return sourceModelPtr->data(index, role);
             }
 
             QModelIndex sourceIndex = mapToSource(index);

+ 6 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp

@@ -267,14 +267,18 @@ namespace AzToolsFramework
 
             m_selection.GetResults().clear();
 
+            AZStd::unordered_set<const AssetBrowserEntry*> entries;
             for (auto entry : selectedAssets)
             {
-                m_selection.GetSelectionFilter()->Filter(m_selection.GetResults(), entry);
-                if (m_selection.IsValid() && !m_selection.GetMultiselect())
+                m_selection.GetSelectionFilter()->Filter(entries, entry);
+
+                if (!entries.empty() && !m_selection.GetMultiselect())
                 {
                     break;
                 }
             }
+
+            m_selection.GetResults().assign(entries.begin(), entries.end());
             return m_selection.IsValid();
         }
 

+ 39 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp

@@ -170,6 +170,16 @@ namespace AzToolsFramework
             return m_name;
         }
 
+        const AZ::u32 AssetBrowserEntry::GetGroupNameCrc() const
+        {
+            return m_groupNameCrc;
+        }
+
+        const QString& AssetBrowserEntry::GetGroupName() const
+        {
+            return m_groupName;
+        }
+
         const QString& AssetBrowserEntry::GetDisplayName() const
         {
             return m_displayName;
@@ -314,6 +324,35 @@ namespace AzToolsFramework
             }
         }
 
+        void AssetBrowserEntry::VisitUp(const AZStd::function<bool(const AssetBrowserEntry*)>& visitorFn) const
+        {
+            if (!visitorFn)
+            {
+                return;
+            }
+
+            for (auto entry = this; entry && entry->GetEntryType() != AssetEntryType::Root; entry = entry->GetParent())
+            {
+                if (!visitorFn(entry))
+                {
+                    return;
+                }
+            }
+        }
+
+        void AssetBrowserEntry::VisitDown(const AZStd::function<bool(const AssetBrowserEntry*)>& visitorFn) const
+        {
+            if (!visitorFn || !visitorFn(this))
+            {
+                return;
+            }
+
+            for (auto child : m_children)
+            {
+                child->VisitDown(visitorFn);
+            }
+        }
+
         const AssetBrowserEntry* AssetBrowserEntry::GetChild(int index) const
         {
             if (index < m_children.size())

+ 14 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h

@@ -112,6 +112,10 @@ namespace AzToolsFramework
 
             //! Actual name of the asset or folder
             const AZStd::string& GetName() const;
+            //! Group name provided by asset type info
+            const AZ::u32 GetGroupNameCrc() const;
+            //! Group name provided by asset type info
+            const QString& GetGroupName() const;
             //! Display name represents how entry is shown in asset browser
             const QString& GetDisplayName() const;
 
@@ -137,6 +141,14 @@ namespace AzToolsFramework
             const QString& GetEntryTypeAsString() const;
             static const AZStd::string ExtensionToType(AZStd::string_view str);
 
+            //! Call the visitor function for the current entry and all of its parents.
+            //! Returning false from the visitor function stops recursion.
+            void VisitUp(const AZStd::function<bool(const AssetBrowserEntry*)>& visitorFn) const;
+
+            //! Recursively call the visitor function for the current entry and all of its children.
+            //! Returning false from the visitor function stops recursion.
+            void VisitDown(const AZStd::function<bool(const AssetBrowserEntry*)>& visitorFn) const;
+
             //! Get immediate children of specific type
             template<typename EntryType>
             void GetChildren(AZStd::vector<const EntryType*>& entries) const;
@@ -170,6 +182,8 @@ namespace AzToolsFramework
 
         protected:
             AZStd::string m_name;
+            AZ::u32 m_groupNameCrc{ 0 };
+            QString m_groupName;
             QString m_displayName;
             QString m_displayPath;
             QString m_entryType;

+ 2 - 7
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryUtils.cpp

@@ -95,12 +95,7 @@ namespace AzToolsFramework
 
                 for (const AssetBrowserEntry* entry : entries)
                 {
-                    if (!entry)
-                    {
-                        continue;
-                    }
-
-                    if (alreadyAdded.find(entry) != alreadyAdded.end())
+                    if (!entry || alreadyAdded.contains(entry))
                     {
                         continue;
                     }
@@ -130,7 +125,7 @@ namespace AzToolsFramework
                     if (target)
                     {
                         anyFound = true;
-                        if (alreadyAdded.find(target) == alreadyAdded.end())
+                        if (!alreadyAdded.contains(target))
                         {
                             entries.push_back(target);
                             alreadyAdded.insert(target);

+ 6 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp

@@ -337,8 +337,13 @@ namespace AzToolsFramework
             product->m_visiblePath = cleanedRelative;
             product->SetFullPath((AZ::IO::Path("@products@") / cleanedRelative).LexicallyNormal());
 
+            AZStd::string assetGroupName;
+            AZ::AssetTypeInfoBus::EventResult(
+                assetGroupName, productWithUuidDatabaseEntry.second.m_assetType, &AZ::AssetTypeInfo::GetGroup);
+            product->m_groupName = AzToQtUtf8String(assetGroupName);
+            product->m_groupNameCrc = AZ::Crc32(assetGroupName);
+
             // compute the display data from the above data.
-            // does someone have information about a more friendly name for this type?
             AZStd::string assetTypeName;
             AZ::AssetTypeInfoBus::EventResult(
                 assetTypeName, productWithUuidDatabaseEntry.second.m_assetType, &AZ::AssetTypeInfo::GetAssetTypeDisplayName);

+ 206 - 288
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp

@@ -7,14 +7,12 @@
  */
 
 #include <AzCore/Asset/AssetTypeInfoBus.h>
-
 #include <AzFramework/StringFunc/StringFunc.h>
-
-#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
-#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
-#include <AzToolsFramework/AssetBrowser/Entries/ProductAssetBrowserEntry.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
 #include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
+#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
+#include <AzToolsFramework/AssetBrowser/Entries/ProductAssetBrowserEntry.h>
+#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
 
 namespace AzToolsFramework
 {
@@ -22,109 +20,76 @@ namespace AzToolsFramework
     {
         namespace
         {
-            bool StringMatch(const QString& searched, const QString& text)
+            inline bool StringMatch(const QString& searched, const QString& text)
             {
                 return text.contains(searched, Qt::CaseInsensitive);
             }
 
-            //! Intersect operation between two sets which then overwrites result
-            void Intersect(AZStd::vector<const AssetBrowserEntry*>& result, AZStd::vector<const AssetBrowserEntry*>& set)
+            //! Expand all entries that are either parent or child relationship to the entry and write to result
+            void Expand(AZStd::unordered_set<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry)
             {
-                // inefficient, but sets are tiny so probably not worth the optimization effort
-                AZStd::vector<const AssetBrowserEntry*> intersection;
-                for (auto entry : result)
-                {
-                    if (AZStd::find(set.begin(), set.end(), entry) != set.end())
+                entry->VisitUp(
+                    [&](const auto& currentEntry)
                     {
-                        intersection.push_back(entry);
-                    }
-                }
-                result = intersection;
-            }
-
-            //! Insert an entry if it doesn't already exist
-            void Join(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry)
-            {
-                if (AZStd::find(result.begin(), result.end(), entry) == result.end())
-                {
-                    result.push_back(entry);
-                }
-            }
-
-            //! Join operation between two sets which then overwrites result
-            void Join(AZStd::vector<const AssetBrowserEntry*>& result, AZStd::vector<const AssetBrowserEntry*>& set)
-            {
-                AZStd::vector<const AssetBrowserEntry*> unionResult;
-                for (auto entry : set)
-                {
-                    Join(result, entry);
-                }
-            }
-
-            //! Expand all children recursively and write to result
-            void ExpandDown(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry)
-            {
-                Join(result, entry);
-                AZStd::vector<const AssetBrowserEntry*> children;
-                entry->GetChildren<AssetBrowserEntry>(children);
-                for (auto child : children)
-                {
-                    ExpandDown(result, child);
-                }
-            }
+                        result.insert(currentEntry);
+                        return true;
+                    });
 
-            //! Expand all entries that are either parent or child relationship to the entry and write to result
-            void Expand(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry)
-            {
-                auto parent = entry->GetParent();
-                while (parent && parent->GetEntryType() != AssetBrowserEntry::AssetEntryType::Root)
-                {
-                    Join(result, parent);
-                    parent = parent->GetParent();
-                }
-                ExpandDown(result, entry);
+                entry->VisitDown(
+                    [&](const auto& currentEntry)
+                    {
+                        result.reserve(result.size() + currentEntry->GetChildCount() + 1);
+                        result.insert(currentEntry);
+                        return true;
+                    });
             }
         }
 
         //////////////////////////////////////////////////////////////////////////
         // AssetBrowserEntryFilter
         //////////////////////////////////////////////////////////////////////////
-        AssetBrowserEntryFilter::AssetBrowserEntryFilter()
-            : m_direction(None)
-        {
-        }
-
         bool AssetBrowserEntryFilter::Match(const AssetBrowserEntry* entry) const
         {
-            if (MatchInternal(entry))
+            if (m_direction == None)
             {
-                return true;
+                if (MatchInternal(entry))
+                {
+                    return true;
+                }
             }
 
             if (m_direction & Up)
             {
-                auto parent = entry->GetParent();
-                while (parent && parent->GetEntryType() != AssetBrowserEntry::AssetEntryType::Root)
-                {
-                    if (MatchInternal(parent))
+                bool result = false;
+                entry->VisitUp(
+                    [&result, this](const auto& currentEntry)
                     {
-                        return true;
-                    }
-                    parent = parent->GetParent();
+                        result = result || MatchInternal(currentEntry);
+                        return !result;
+                    });
+
+                if (result)
+                {
+                    return true;
                 }
             }
+
             if (m_direction & Down)
             {
-                AZStd::vector<const AssetBrowserEntry*> children;
-                entry->GetChildren<AssetBrowserEntry>(children);
-                for (auto child : children)
-                {
-                    if (MatchDown(child))
+                bool result = false;
+                entry->VisitDown(
+                    [&](const auto& currentEntry)
                     {
-                        return true;
-                    }
+                        result = result || MatchInternal(currentEntry);
+                        return !result;
+                    });
+
+                if (result)
+                {
+                    return true;
                 }
             }
+
             return false;
         }
 
@@ -133,27 +98,43 @@ namespace AzToolsFramework
             return MatchInternal(entry);
         }
 
-        void AssetBrowserEntryFilter::Filter(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const
+        void AssetBrowserEntryFilter::Filter(AZStd::unordered_set<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const
         {
-            FilterInternal(result, entry);
-
-            if (m_direction & Up)
+            if (m_direction == None)
             {
-                auto parent = entry->GetParent();
-                while (parent && parent->GetEntryType() != AssetBrowserEntry::AssetEntryType::Root)
+                if (MatchInternal(entry))
                 {
-                    FilterInternal(result, parent);
-                    parent = parent->GetParent();
+                    Expand(result, entry);
+                    return;
                 }
             }
+
+            if (m_direction & Up)
+            {
+                entry->VisitUp(
+                    [&result, this](const auto& currentEntry)
+                    {
+                        if (MatchInternal(currentEntry))
+                        {
+                            Expand(result, currentEntry);
+                            return false;
+                        }
+                        return true;
+                    });
+            }
+
             if (m_direction & Down)
             {
-                AZStd::vector<const AssetBrowserEntry*> children;
-                entry->GetChildren<AssetBrowserEntry>(children);
-                for (auto child : children)
-                {
-                    FilterDown(result, child);
-                }
+                entry->VisitDown(
+                    [&](const auto& currentEntry)
+                    {
+                        if (MatchInternal(currentEntry))
+                        {
+                            Expand(result, currentEntry);
+                            return false;
+                        }
+                        return true;
+                    });
             }
         }
 
@@ -182,51 +163,18 @@ namespace AzToolsFramework
             m_direction = direction;
         }
 
-        void AssetBrowserEntryFilter::FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const
-        {
-            if (MatchInternal(entry))
-            {
-                Join(result, entry);
-            }
-        }
-
-        bool AssetBrowserEntryFilter::MatchDown(const AssetBrowserEntry* entry) const
-        {
-            if (MatchInternal(entry))
-            {
-                return true;
-            }
-            AZStd::vector<const AssetBrowserEntry*> children;
-            entry->GetChildren<AssetBrowserEntry>(children);
-            for (auto child : children)
-            {
-                if (MatchDown(child))
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        void AssetBrowserEntryFilter::FilterDown(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const
-        {
-            if (MatchInternal(entry))
-            {
-                Join(result, entry);
-            }
-            AZStd::vector<const AssetBrowserEntry*> children;
-            entry->GetChildren<AssetBrowserEntry>(children);
-            for (auto child : children)
-            {
-                FilterDown(result, child);
-            }
-        }
-
         //////////////////////////////////////////////////////////////////////////
         // StringFilter
         //////////////////////////////////////////////////////////////////////////
-        StringFilter::StringFilter()
-            : m_filterString("") {}
+        AssetBrowserEntryFilter* StringFilter::Clone() const
+        {
+            auto clone = new StringFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            clone->m_filterString = m_filterString;
+            return clone;
+        }
 
         void StringFilter::SetFilterString(const QString& filterString)
         {
@@ -258,6 +206,15 @@ namespace AzToolsFramework
         {
         }
 
+        AssetBrowserEntryFilter* CustomFilter::Clone() const
+        {
+            auto clone = new CustomFilter(m_filterFn);
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            return clone;
+        }
+
         QString CustomFilter::GetNameInternal() const
         {
             return "Custom Filter";
@@ -265,12 +222,22 @@ namespace AzToolsFramework
 
         bool CustomFilter::MatchInternal(const AssetBrowserEntry* entry) const
         {
-            return m_filterFn && m_filterFn(entry);
+            return !m_filterFn || m_filterFn(entry);
         }
 
         //////////////////////////////////////////////////////////////////////////
         // RegExpFilter
         //////////////////////////////////////////////////////////////////////////
+        AssetBrowserEntryFilter* RegExpFilter::Clone() const
+        {
+            auto clone = new RegExpFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            clone->m_filterPattern = m_filterPattern;
+            return clone;
+        }
+
         void RegExpFilter::SetFilterPattern(const QRegExp& filterPattern)
         {
             m_filterPattern = filterPattern;
@@ -291,8 +258,15 @@ namespace AzToolsFramework
         //////////////////////////////////////////////////////////////////////////
         // AssetTypeFilter
         //////////////////////////////////////////////////////////////////////////
-        AssetTypeFilter::AssetTypeFilter()
-            : m_assetType(AZ::Data::AssetType::CreateNull()) {}
+        AssetBrowserEntryFilter* AssetTypeFilter::Clone() const
+        {
+            auto clone = new AssetTypeFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            clone->m_assetType = m_assetType;
+            return clone;
+        }
 
         void AssetTypeFilter::SetAssetType(AZ::Data::AssetType assetType)
         {
@@ -322,32 +296,36 @@ namespace AzToolsFramework
         bool AssetTypeFilter::MatchInternal(const AssetBrowserEntry* entry) const
         {
             // this filter only works on products.
-            if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
+            const ProductAssetBrowserEntry* product = entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product
+                ? static_cast<const ProductAssetBrowserEntry*>(entry)
+                : nullptr;
+            if (!product)
             {
-                if (m_assetType.IsNull())
-                {
-                    return true;
-                }
-
-                if (static_cast<const ProductAssetBrowserEntry*>(entry)->GetAssetType() == m_assetType)
-                {
-                    return true;
-                }
+                return false;
             }
-            return false;
+
+            return m_assetType.IsNull() || (product && product->GetAssetType() == m_assetType);
         }
 
         //////////////////////////////////////////////////////////////////////////
         // AssetGroupFilter
         //////////////////////////////////////////////////////////////////////////
-        AssetGroupFilter::AssetGroupFilter()
-            : m_group("All")
+        AssetBrowserEntryFilter* AssetGroupFilter::Clone() const
         {
+            auto clone = new AssetGroupFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            clone->SetAssetGroup(m_group);
+            return clone;
         }
 
         void AssetGroupFilter::SetAssetGroup(const QString& group)
         {
             m_group = group;
+            m_groupCrc = AZ::Crc32(group.toUtf8().constData());
+            m_groupIsAll = m_group.compare("All", Qt::CaseInsensitive) == 0;
+            m_groupIsOther = m_group.compare("Other", Qt::CaseInsensitive) == 0;
         }
 
         const QString& AssetGroupFilter::GetAssetTypeGroup() const
@@ -363,27 +341,15 @@ namespace AzToolsFramework
         bool AssetGroupFilter::MatchInternal(const AssetBrowserEntry* entry) const
         {
             // this filter only works on products.
-            if (entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Product)
+            const ProductAssetBrowserEntry* product = entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product
+                ? static_cast<const ProductAssetBrowserEntry*>(entry)
+                : nullptr;
+            if (!product)
             {
                 return false;
             }
 
-            if (m_group.compare("All", Qt::CaseInsensitive) == 0)
-            {
-                return true;
-            }
-
-            auto product = static_cast<const ProductAssetBrowserEntry*>(entry);
-
-            QString group;
-            AZ::AssetTypeInfoBus::EventResult(group, product->GetAssetType(), &AZ::AssetTypeInfo::GetGroup);
-
-            if (m_group.compare("Other", Qt::CaseInsensitive) == 0 && group.isEmpty())
-            {
-                return true;
-            }
-
-            return (m_group.compare(group, Qt::CaseInsensitive) == 0);
+            return (m_groupIsAll) || (m_groupIsOther && product->GetGroupName().isEmpty()) || (m_groupCrc == product->GetGroupNameCrc());
         }
 
         //////////////////////////////////////////////////////////////////////////
@@ -394,6 +360,16 @@ namespace AzToolsFramework
         {
         }
 
+        AssetBrowserEntryFilter* EntryTypeFilter::Clone() const
+        {
+            auto clone = new EntryTypeFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            clone->m_entryType = m_entryType;
+            return clone;
+        }
+
         void EntryTypeFilter::SetEntryType(AssetBrowserEntry::AssetEntryType entryType)
         {
             m_entryType = entryType;
@@ -419,7 +395,23 @@ namespace AzToolsFramework
         //////////////////////////////////////////////////////////////////////////
         CompositeFilter::CompositeFilter(LogicOperatorType logicOperator)
             : m_logicOperator(logicOperator)
-            , m_emptyResult(true) {}
+        {
+        }
+
+        AssetBrowserEntryFilter* CompositeFilter::Clone() const
+        {
+            auto clone = new CompositeFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            clone->m_logicOperator = m_logicOperator;
+            clone->m_emptyResult = m_emptyResult;
+            for (const auto& subFilter : m_subFilters)
+            {
+                clone->AddFilter(FilterConstType(subFilter->Clone()));
+            }
+            return clone;
+        }
 
         void CompositeFilter::AddFilter(FilterConstType filter)
         {
@@ -464,7 +456,7 @@ namespace AzToolsFramework
 
         QString CompositeFilter::GetNameInternal() const
         {
-            QString name = "";
+            QString name;
             for (auto it = m_subFilters.begin(); it != m_subFilters.end(); ++it)
             {
                 name += (*it)->GetName();
@@ -478,7 +470,7 @@ namespace AzToolsFramework
 
         bool CompositeFilter::MatchInternal(const AssetBrowserEntry* entry) const
         {
-            if (m_subFilters.count() == 0)
+            if (m_subFilters.empty())
             {
                 return m_emptyResult;
             }
@@ -486,124 +478,59 @@ namespace AzToolsFramework
             // AND
             if (m_logicOperator == LogicOperatorType::AND)
             {
-                for (auto filter : m_subFilters)
-                {
-                    if (!filter->Match(entry))
-                    {
-                        return false;
-                    }
-                }
-                return true;
-            }
-            // OR
-            for (auto filter : m_subFilters)
-            {
-                if (filter->Match(entry))
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        void CompositeFilter::FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const
-        {
-            // if no subfilters are present in this composite filter then all relating entries would match
-            if (m_subFilters.isEmpty())
-            {
-                // only if match on empty filter is success
-                if (m_emptyResult)
-                {
-                    Expand(result, entry);
-                }
-                return;
-            }
-
-            // AND
-            if (m_logicOperator == LogicOperatorType::AND)
-            {
-                AZStd::vector<const AssetBrowserEntry*> andResult;
-                bool firstResult = true;
-
-                for (auto filter : m_subFilters)
-                {
-                    if (firstResult)
-                    {
-                        firstResult = false;
-                        filter->Filter(andResult, entry);
-                    }
-                    else
-                    {
-                        AZStd::vector<const AssetBrowserEntry*> set;
-                        filter->Filter(set, entry);
-                        Intersect(andResult, set);
-                    }
-                    if (andResult.empty())
-                    {
-                        break;
-                    }
-                }
-                Join(result, andResult);
+                return AZStd::all_of(m_subFilters.begin(), m_subFilters.end(), [&entry](const auto& filter) {
+                    return filter->Match(entry);
+                });
             }
             // OR
-            else
-            {
-                for (auto filter : m_subFilters)
-                {
-                    AZStd::vector<const AssetBrowserEntry*> set;
-                    filter->Filter(set, entry);
-                    Join(result, set);
-                }
-            }
+            return AZStd::any_of(m_subFilters.begin(), m_subFilters.end(), [&entry](const auto& filter) {
+                return filter->Match(entry);
+            });
         }
 
         //////////////////////////////////////////////////////////////////////////
         // InverseFilter
         //////////////////////////////////////////////////////////////////////////
-        InverseFilter::InverseFilter() {}
+        AssetBrowserEntryFilter* InverseFilter::Clone() const
+        {
+            auto clone = new InverseFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            clone->m_filter = FilterConstType(m_filter->Clone());
+            return clone;
+        }
 
         void InverseFilter::SetFilter(FilterConstType filter)
         {
-            if (m_filter == filter)
+            if (m_filter != filter)
             {
-                return;
+                m_filter = filter;
+                Q_EMIT updatedSignal();
             }
-
-            m_filter = filter;
-            Q_EMIT updatedSignal();
         }
 
         QString InverseFilter::GetNameInternal() const
         {
-            if (m_filter.isNull())
-            {
-                QString name = tr("NOT");
-            }
-            QString name = tr("NOT (%1)").arg(m_filter->GetName());
-            return name;
+            return m_filter.isNull() ? tr("NOT") : tr("NOT (%1)").arg(m_filter->GetName());
         }
 
         bool InverseFilter::MatchInternal(const AssetBrowserEntry* entry) const
         {
-            if (m_filter.isNull())
-            {
-                return false;
-            }
-            return !m_filter->Match(entry);
-        }
-
-        void InverseFilter::FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const
-        {
-            if (MatchInternal(entry))
-            {
-                Expand(result, entry);
-            }
+            return m_filter && !m_filter->Match(entry);
         }
 
         //////////////////////////////////////////////////////////////////////////
         // CleanerProductsFilter
         //////////////////////////////////////////////////////////////////////////
-        CleanerProductsFilter::CleanerProductsFilter() {}
+        AssetBrowserEntryFilter* CleanerProductsFilter::Clone() const
+        {
+            auto clone = new CleanerProductsFilter();
+            clone->m_name = m_name;
+            clone->m_tag = m_tag;
+            clone->m_direction = m_direction;
+            return clone;
+        }
 
         QString CleanerProductsFilter::GetNameInternal() const
         {
@@ -612,39 +539,30 @@ namespace AzToolsFramework
 
         bool CleanerProductsFilter::MatchInternal(const AssetBrowserEntry* entry) const
         {
-            auto product = azrtti_cast<const ProductAssetBrowserEntry*>(entry);
+            const ProductAssetBrowserEntry* product = entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product
+                ? static_cast<const ProductAssetBrowserEntry*>(entry)
+                : nullptr;
             if (!product)
             {
                 return true;
             }
-            auto source = product->GetParent();
-            if (!source)
-            {
-                return true;
-            }
-            if (source->GetChildCount() != 1)
-            {
-                return true;
-            }
 
-            AZStd::string assetTypeName;
-            AZ::AssetTypeInfoBus::EventResult(assetTypeName, product->GetAssetType(), &AZ::AssetTypeInfo::GetAssetTypeDisplayName);
-            if (!assetTypeName.empty())
+            auto source = product->GetParent();
+            if (!source || source->GetChildCount() != 1)
             {
                 return true;
             }
-            
-            return false;
-        }
 
-        void CleanerProductsFilter::FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const
-        {
-            if (MatchInternal(entry))
-            {
-                Expand(result, entry);
-            }
+            bool result = false;
+            AZ::AssetTypeInfoBus::Event(
+                product->GetAssetType(),
+                [&result](AZ::AssetTypeInfoBus::Events* handler)
+                {
+                    const char* assetTypeName = handler->GetAssetTypeDisplayName();
+                    result = assetTypeName && assetTypeName[0];
+                });
+            return result;
         }
-
     } // namespace AssetBrowser
 } // namespace AzToolsFramework
 

+ 56 - 50
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h

@@ -8,16 +8,15 @@
 #pragma once
 
 #if !defined(Q_MOC_RUN)
+#include <AzCore/Asset/AssetTypeInfoBus.h>
+#include <AzCore/std/algorithm.h>
+#include <AzCore/std/containers/unordered_set.h>
+#include <AzCore/std/containers/vector.h>
 #include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
 
 #include <QObject>
-#include <QString>
 #include <QSharedPointer>
 #include <QString>
-
-#include <AzCore/Asset/AssetTypeInfoBus.h>
-#include <AzCore/std/containers/vector.h>
-#include <AzCore/std/algorithm.h>
 #endif
 
 namespace AzToolsFramework
@@ -32,8 +31,7 @@ namespace AzToolsFramework
         //////////////////////////////////////////////////////////////////////////
         //! Filters are used to fascilitate searching asset browser for specific asset
         //! They are also used for enforcing selection constraints for asset picking
-        class AssetBrowserEntryFilter
-            : public QObject
+        class AssetBrowserEntryFilter : public QObject
         {
             Q_OBJECT
         public:
@@ -52,8 +50,12 @@ namespace AzToolsFramework
                 Down    = 0x02
             };
 
-            AssetBrowserEntryFilter();
-            virtual ~AssetBrowserEntryFilter() =  default;
+            AssetBrowserEntryFilter() = default;
+            ~AssetBrowserEntryFilter() override = default;
+
+            //! Cloning function that must be overridden for certain asset browser views that duplicate and modify incoming filters\
+            //! This should be implemented using a copy constructor, which is currently not possible because inheriting QObject prevents it.
+            virtual AssetBrowserEntryFilter* Clone() const = 0;
 
             //! Check if entry matches filter
             bool Match(const AssetBrowserEntry* entry) const;
@@ -63,7 +65,7 @@ namespace AzToolsFramework
             bool MatchWithoutPropagation(const AssetBrowserEntry* entry) const;
 
             //! Retrieve all matching entries that are either entry itself or its parents or children
-            void Filter(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const;
+            void Filter(AZStd::unordered_set<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const;
 
             //! Filter name is used to uniquely identify the filter
             QString GetName() const;
@@ -76,39 +78,36 @@ namespace AzToolsFramework
             void SetFilterPropagation(int direction);
 
         Q_SIGNALS:
-            //! Emitted every time a filter is updated, in case of composite filter, the signal is propagated to the top level filter so only one listener needs to connected
+            //! Emitted every time a filter is updated, in case of composite filter, the signal is propagated to the top level filter so
+            //! only one listener needs to connected
             void updatedSignal() const;
 
         protected:
             //! Internal name auto generated based on filter type and data
             virtual QString GetNameInternal() const = 0;
+
             //! Internal matching logic overrided by every filter type
             virtual bool MatchInternal(const AssetBrowserEntry* entry) const = 0;
-            //! Internal filtering logic overrided by every filter type
-            virtual void FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const;
 
-        private:
+        protected:
             QString m_name;
             QString m_tag;
-            int m_direction;
-
-            bool MatchDown(const AssetBrowserEntry* entry) const;
-            void FilterDown(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const;
+            int m_direction{ None };
         };
 
-
         //////////////////////////////////////////////////////////////////////////
         // StringFilter
         //////////////////////////////////////////////////////////////////////////
         //! StringFilter filters assets based on their name
-        class StringFilter
-            : public AssetBrowserEntryFilter
+        class StringFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
         public:
-            StringFilter();
+            StringFilter() = default;
             ~StringFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
             void SetFilterString(const QString& filterString);
             QString GetFilterString() const;
 
@@ -123,7 +122,7 @@ namespace AzToolsFramework
         //////////////////////////////////////////////////////////////////////////
         // CustomFilter
         //////////////////////////////////////////////////////////////////////////
-        //! CustomFilter filters assets based on a custom filter function 
+        //! CustomFilter filters assets based on a custom filter function
         class CustomFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
@@ -131,6 +130,8 @@ namespace AzToolsFramework
             CustomFilter(const AZStd::function<bool(const AssetBrowserEntry*)>& filterFn);
             ~CustomFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
         protected:
             QString GetNameInternal() const override;
             bool MatchInternal(const AssetBrowserEntry* entry) const override;
@@ -150,6 +151,8 @@ namespace AzToolsFramework
             RegExpFilter() = default;
             ~RegExpFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
             void SetFilterPattern(const QRegExp& filterPattern);
 
         protected:
@@ -164,14 +167,15 @@ namespace AzToolsFramework
         // AssetTypeFilter
         //////////////////////////////////////////////////////////////////////////
         //! AssetTypeFilter filters products based on their asset type
-        class AssetTypeFilter
-            : public AssetBrowserEntryFilter
+        class AssetTypeFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
         public:
-            AssetTypeFilter();
+            AssetTypeFilter() = default;
             ~AssetTypeFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
             void SetAssetType(AZ::Data::AssetType assetType);
             void SetAssetType(const char* assetTypeName);
             AZ::Data::AssetType GetAssetType() const;
@@ -181,21 +185,22 @@ namespace AzToolsFramework
             bool MatchInternal(const AssetBrowserEntry* entry) const override;
 
         private:
-            AZ::Data::AssetType m_assetType;
+            AZ::Data::AssetType m_assetType{ AZ::Data::AssetType::CreateNull() };
         };
 
         //////////////////////////////////////////////////////////////////////////
         // AssetGroupFilter
         //////////////////////////////////////////////////////////////////////////
         //! AssetGroupFilter filters products based on their asset group
-        class AssetGroupFilter
-            : public AssetBrowserEntryFilter
+        class AssetGroupFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
         public:
-            AssetGroupFilter();
+            AssetGroupFilter() = default;
             ~AssetGroupFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
             void SetAssetGroup(const QString& group);
             const QString& GetAssetTypeGroup() const;
 
@@ -204,20 +209,24 @@ namespace AzToolsFramework
             bool MatchInternal(const AssetBrowserEntry* entry) const override;
 
         private:
-            QString m_group;
+            QString m_group{ "All" };
+            AZ::u32 m_groupCrc{ AZ::Crc32("All") };
+            bool m_groupIsAll{ true };
+            bool m_groupIsOther{ false };
         };
 
         //////////////////////////////////////////////////////////////////////////
         // EntryTypeFilter
         //////////////////////////////////////////////////////////////////////////
-        class EntryTypeFilter
-            : public AssetBrowserEntryFilter
+        class EntryTypeFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
         public:
             EntryTypeFilter();
             ~EntryTypeFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
             void SetEntryType(AssetBrowserEntry::AssetEntryType entryType);
             AssetBrowserEntry::AssetEntryType GetEntryType() const;
 
@@ -237,8 +246,7 @@ namespace AzToolsFramework
             If more complex logic operations required, CompositeFilters can be nested
             with different logic operator types
         */
-        class CompositeFilter
-            : public AssetBrowserEntryFilter
+        class CompositeFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
         public:
@@ -248,9 +256,12 @@ namespace AzToolsFramework
                 AND
             };
 
+            CompositeFilter() = default;
             explicit CompositeFilter(LogicOperatorType logicOperator);
             ~CompositeFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
             void AddFilter(FilterConstType filter);
             void RemoveFilter(FilterConstType filter);
             void RemoveAllFilters();
@@ -262,32 +273,31 @@ namespace AzToolsFramework
         protected:
             QString GetNameInternal() const override;
             bool MatchInternal(const AssetBrowserEntry* entry) const override;
-            void FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const override;
 
         private:
             QList<FilterConstType> m_subFilters;
-            LogicOperatorType m_logicOperator;
-            bool m_emptyResult;
+            LogicOperatorType m_logicOperator{ LogicOperatorType::AND };
+            bool m_emptyResult{ true };
         };
 
         //////////////////////////////////////////////////////////////////////////
         // InverseFilter
         //////////////////////////////////////////////////////////////////////////
         //! Inverse filter negates result of its child filter
-        class InverseFilter
-            : public AssetBrowserEntryFilter
+        class InverseFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
         public:
-            InverseFilter();
+            InverseFilter() = default;
             ~InverseFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
             void SetFilter(FilterConstType filter);
 
         protected:
             QString GetNameInternal() const override;
             bool MatchInternal(const AssetBrowserEntry* entry) const override;
-            void FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const override;
 
         private:
             FilterConstType m_filter;
@@ -297,24 +307,20 @@ namespace AzToolsFramework
         // CleanerProductsFilter
         //////////////////////////////////////////////////////////////////////////
         //! Filters out products that shouldn't be shown
-        class CleanerProductsFilter
-            : public AssetBrowserEntryFilter
+        class CleanerProductsFilter : public AssetBrowserEntryFilter
         {
             Q_OBJECT
         public:
-            CleanerProductsFilter();
+            CleanerProductsFilter() = default;
             ~CleanerProductsFilter() override = default;
 
+            AssetBrowserEntryFilter* Clone() const override;
+
         protected:
             QString GetNameInternal() const override;
             bool MatchInternal(const AssetBrowserEntry* entry) const override;
-            void FilterInternal(AZStd::vector<const AssetBrowserEntry*>& result, const AssetBrowserEntry* entry) const override;
-
-        private:
-            FilterConstType m_filter;
         };
 
-
         template<class T>
         struct EBusAggregateUniqueResults
         {

+ 11 - 19
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserListView.cpp

@@ -161,28 +161,25 @@ namespace AzToolsFramework
 
         void AssetBrowserListView::DeleteEntries()
         {
-            auto entries = GetSelectedAssets(false); // you cannot delete product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot delete product files.
             AssetBrowserViewUtils::DeleteEntries(entries, this);
         }
 
         void AssetBrowserListView::MoveEntries()
         {
-            auto entries = GetSelectedAssets(false); // you cannot move product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot move product files.
             AssetBrowserViewUtils::MoveEntries(entries, this);
         }
 
         void AssetBrowserListView::DuplicateEntries()
         {
-            auto entries = GetSelectedAssets(false); // you may not duplicate product files.
+            const auto& entries = GetSelectedAssets(false); // you may not duplicate product files.
             AssetBrowserViewUtils::DuplicateEntries(entries);
         }
 
         void AssetBrowserListView::RenameEntry()
         {
-            auto entries = GetSelectedAssets(false); // you cannot rename product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot rename product files.
             if (AssetBrowserViewUtils::RenameEntry(entries, this))
             {
                 edit(currentIndex());
@@ -191,8 +188,7 @@ namespace AzToolsFramework
 
         void AssetBrowserListView::AfterRename(QString newVal)
         {
-            auto entries = GetSelectedAssets(false); // you cannot rename product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot rename product files.
             AssetBrowserViewUtils::AfterRename(newVal, entries, this);
         }
 
@@ -211,15 +207,12 @@ namespace AzToolsFramework
             AssetBrowserModel::SourceIndexesToAssetDatabaseEntries(sourceIndexes, entries);
             if (!includeProducts)
             {
-                entries.erase(
-                    AZStd::remove_if(
-                        entries.begin(),
-                        entries.end(),
-                        [&](const AssetBrowserEntry* entry) -> bool
-                        {
-                            return entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product;
-                        }),
-                    entries.end());
+                AZStd::erase_if(
+                    entries,
+                    [&](const AssetBrowserEntry* entry) -> bool
+                    {
+                        return entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product;
+                    });
             }
 
             return entries;
@@ -303,7 +296,6 @@ namespace AzToolsFramework
             header()->setMaximumSectionSize(aznumeric_cast<int>(newWidth * MaxHeaderResizeProportion));
         }
 
-
         void AssetBrowserListView::OnContextMenu([[maybe_unused]] const QPoint& point)
         {
             const auto& selectedAssets = GetSelectedAssets();

+ 141 - 151
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp

@@ -5,37 +5,35 @@
  * SPDX-License-Identifier: Apache-2.0 OR MIT
  *
  */
-#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h>
 
+#include <AzCore/Utils/Utils.h>
+#include <AzFramework/StringFunc/StringFunc.h>
+#include <AzQtComponents/Components/Widgets/AssetFolderTableView.h>
+#include <AzQtComponents/DragAndDrop/MainWindowDragAndDrop.h>
+#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
 #include <AzToolsFramework/ActionManager/HotKey/HotKeyManagerInterface.h>
+#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserTableViewProxyModel.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserTreeToTableProxyModel.h>
 #include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
-#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
 #include <AzToolsFramework/AssetBrowser/Entries/ProductAssetBrowserEntry.h>
+#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
+#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h>
 #include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
 #include <AzToolsFramework/AssetBrowser/Views/AssetBrowserViewUtils.h>
-#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
 #include <AzToolsFramework/Editor/ActionManagerIdentifiers/EditorContextIdentifiers.h>
 #include <AzToolsFramework/Editor/ActionManagerUtils.h>
 #include <AzToolsFramework/Editor/RichTextHighlighter.h>
-#include <AzCore/Utils/Utils.h>
-
-#include <AzQtComponents/Components/Widgets/AssetFolderTableView.h>
-#include <AzQtComponents/DragAndDrop/MainWindowDragAndDrop.h>
-
-#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
-#include <AzFramework/StringFunc/StringFunc.h>
 
 #if !defined(Q_MOC_RUN)
-#include <QVBoxLayout>
-#include <QtWidgets/QApplication>
+#include <QApplication>
 #include <QDragMoveEvent>
 #include <QHeaderView>
 #include <QLineEdit>
 #include <QMenu>
+#include <QVBoxLayout>
 #endif
 
 namespace AzToolsFramework
@@ -56,7 +54,6 @@ namespace AzToolsFramework
             // only lists directories, and at the same time get sort and filter entries features from AssetBrowserFilterModel.
             using namespace AzToolsFramework::AssetBrowser;
             AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel);
-            m_assetFilterModel->sort(0, Qt::DescendingOrder);
 
             m_tableViewProxyModel->setSourceModel(m_assetFilterModel);
             m_tableViewWidget->setSortingEnabled(false);
@@ -70,6 +67,8 @@ namespace AzToolsFramework
                 m_tableViewWidget->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
             }
 
+            SetSortMode(AssetBrowserEntry::AssetEntrySortMode::Name);
+
             connect(
                 m_tableViewWidget->header(),
                 &QHeaderView::sortIndicatorChanged,
@@ -111,14 +110,16 @@ namespace AzToolsFramework
                     emit entryClicked(indexData);
                 });
 
-             connect(
+            connect(
                 m_tableViewWidget,
-                &AzQtComponents::AssetFolderTableView::rowDeselected, this, []
+                &AzQtComponents::AssetFolderTableView::rowDeselected,
+                this,
+                []
                 {
                     AssetBrowserPreviewRequestBus::Broadcast(&AssetBrowserPreviewRequest::ClearPreview);
                 });
 
-             connect(
+            connect(
                 m_tableViewWidget,
                 &AzQtComponents::AssetFolderTableView::doubleClicked,
                 this,
@@ -128,82 +129,83 @@ namespace AzToolsFramework
                     emit entryDoubleClicked(indexData);
                 });
 
-             connect(
-                 m_tableViewWidget,
-                 &AzQtComponents::AssetFolderTableView::customContextMenuRequested,
-                 this,
-                 [this](const QPoint& pos)
-                 {
-                     if (auto index = m_tableViewWidget->indexAt(pos); index.isValid())
-                     {
-                         QMenu menu(this);
-                         AZStd::vector<const AssetBrowserEntry*> entries = GetSelectedAssets();
-                         AssetBrowserInteractionNotificationBus::Broadcast(
-                             &AssetBrowserInteractionNotificationBus::Events::AddContextMenuActions, this, &menu, entries);
-
-                         if (!menu.isEmpty())
-                         {
-                             menu.exec(QCursor::pos());
-                         }
-                     }
-                     else if (!index.isValid() && m_assetTreeView)
-                     {
-                         m_assetTreeView->OnContextMenu(pos);
-                     }
-                 });
-
-              connect(
-                 m_tableViewDelegate,
-                 &TableViewDelegate::renameTableEntry, this,
-                 [this](QString name)
-                 {
-                     AfterRename(name);
-                 });
-
-              AssignWidgetToActionContextHelper(EditorIdentifiers::EditorAssetBrowserActionContextIdentifier, this);
-
-              QAction* deleteAction = new QAction("Delete Action", this);
-              deleteAction->setShortcut(QKeySequence::Delete);
-              deleteAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-              connect(
-                  deleteAction,
-                  &QAction::triggered,
-                  this,
-                  [this]()
-                  {
-                      DeleteEntries();
-                  });
-              addAction(deleteAction);
-
-              QAction* renameAction = new QAction("Rename Action", this);
-              renameAction->setShortcut(Qt::Key_F2);
-              renameAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-              connect(
-                  renameAction,
-                  &QAction::triggered,
-                  this,
-                  [this]()
-                  {
-                      RenameEntry();
-                  });
-              addAction(renameAction);
-
-              QAction* duplicateAction = new QAction("Duplicate Action", this);
-              duplicateAction->setShortcut(QKeySequence("Ctrl+D"));
-              duplicateAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-              connect(
-                  duplicateAction,
-                  &QAction::triggered,
-                  this,
-                  [this]()
-                  {
-                      DuplicateEntries();
-                  });
-              addAction(duplicateAction);
+            connect(
+                m_tableViewWidget,
+                &AzQtComponents::AssetFolderTableView::customContextMenuRequested,
+                this,
+                [this](const QPoint& pos)
+                {
+                    if (auto index = m_tableViewWidget->indexAt(pos); index.isValid())
+                    {
+                        QMenu menu(this);
+                        const auto& entries = GetSelectedAssets();
+                        AssetBrowserInteractionNotificationBus::Broadcast(
+                            &AssetBrowserInteractionNotificationBus::Events::AddContextMenuActions, this, &menu, entries);
+
+                        if (!menu.isEmpty())
+                        {
+                            menu.exec(QCursor::pos());
+                        }
+                    }
+                    else if (!index.isValid() && m_assetTreeView)
+                    {
+                        m_assetTreeView->OnContextMenu(pos);
+                    }
+                });
+
+            connect(
+                m_tableViewDelegate,
+                &TableViewDelegate::renameTableEntry,
+                this,
+                [this](QString name)
+                {
+                    AfterRename(name);
+                });
+
+            AssignWidgetToActionContextHelper(EditorIdentifiers::EditorAssetBrowserActionContextIdentifier, this);
+
+            QAction* deleteAction = new QAction("Delete Action", this);
+            deleteAction->setShortcut(QKeySequence::Delete);
+            deleteAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+            connect(
+                deleteAction,
+                &QAction::triggered,
+                this,
+                [this]()
+                {
+                    DeleteEntries();
+                });
+            addAction(deleteAction);
+
+            QAction* renameAction = new QAction("Rename Action", this);
+            renameAction->setShortcut(Qt::Key_F2);
+            renameAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+            connect(
+                renameAction,
+                &QAction::triggered,
+                this,
+                [this]()
+                {
+                    RenameEntry();
+                });
+            addAction(renameAction);
+
+            QAction* duplicateAction = new QAction("Duplicate Action", this);
+            duplicateAction->setShortcut(QKeySequence("Ctrl+D"));
+            duplicateAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+            connect(
+                duplicateAction,
+                &QAction::triggered,
+                this,
+                [this]()
+                {
+                    DuplicateEntries();
+                });
+            addAction(duplicateAction);
 
             connect(
                 m_tableViewWidget,
-                 &AzQtComponents::AssetFolderTableView::showInTableFolderTriggered,
+                &AzQtComponents::AssetFolderTableView::showInTableFolderTriggered,
                 this,
                 [this](const QModelIndex& index)
                 {
@@ -276,7 +278,7 @@ namespace AzToolsFramework
             return m_tableViewWidget;
         }
 
-         void AssetBrowserTableView::SetName(const QString& name)
+        void AssetBrowserTableView::SetName(const QString& name)
         {
             m_name = name;
         }
@@ -308,28 +310,25 @@ namespace AzToolsFramework
 
         void AssetBrowserTableView::DeleteEntries()
         {
-            auto entries = GetSelectedAssets();
-
+            const auto& entries = GetSelectedAssets();
             AssetBrowserViewUtils::DeleteEntries(entries, this);
         }
 
         void AssetBrowserTableView::MoveEntries()
         {
-            auto entries = GetSelectedAssets();
-
+            const auto& entries = GetSelectedAssets();
             AssetBrowserViewUtils::MoveEntries(entries, this);
         }
 
         void AssetBrowserTableView::DuplicateEntries()
         {
-            auto entries = GetSelectedAssets();
+            const auto& entries = GetSelectedAssets();
             AssetBrowserViewUtils::DuplicateEntries(entries);
         }
 
         void AssetBrowserTableView::RenameEntry()
         {
-            auto entries = GetSelectedAssets();
-
+            const auto& entries = GetSelectedAssets();
             if (AssetBrowserViewUtils::RenameEntry(entries, this))
             {
                 QModelIndex selectedIndex = m_tableViewWidget->selectionModel()->selectedIndexes()[0];
@@ -339,8 +338,7 @@ namespace AzToolsFramework
 
         void AssetBrowserTableView::AfterRename(QString newVal)
         {
-            auto entries = GetSelectedAssets();
-
+            const auto& entries = GetSelectedAssets();
             AssetBrowserViewUtils::AfterRename(newVal, entries, this);
         }
 
@@ -350,8 +348,10 @@ namespace AzToolsFramework
             AZStd::vector<const AssetBrowserEntry*> entries;
             if (m_tableViewWidget->selectionModel())
             {
-                auto indexes = m_tableViewWidget->selectionModel()->selectedRows();
-                for (const auto index : indexes)
+                const auto& indexes = m_tableViewWidget->selectionModel()->selectedRows();
+                entries.reserve(indexes.size());
+
+                for (const auto& index : indexes)
                 {
                     const AssetBrowserEntry* item = index.data(AssetBrowserModel::Roles::EntryRole).value<const AssetBrowserEntry*>();
                     if (item)
@@ -369,7 +369,8 @@ namespace AzToolsFramework
 
             if (proxyIndex.isValid())
             {
-                m_tableViewWidget->selectionModel()->select(proxyIndex, QItemSelectionModel::SelectionFlag::ClearAndSelect | QItemSelectionModel::Rows);
+                m_tableViewWidget->selectionModel()->select(
+                    proxyIndex, QItemSelectionModel::SelectionFlag::ClearAndSelect | QItemSelectionModel::Rows);
 
                 m_tableViewWidget->scrollTo(proxyIndex, QAbstractItemView::ScrollHint::PositionAtCenter);
 
@@ -448,15 +449,13 @@ namespace AzToolsFramework
             }
 
             m_assetTreeView = treeView;
-            m_assetTreeView->SetAttachedTableView(this);
-
-            m_assetTreeView->SetAttachedTableView(this);
-
             if (!m_assetTreeView)
             {
                 return;
             }
 
+            m_assetTreeView->SetAttachedTableView(this);
+
             auto treeViewFilterModel = qobject_cast<AssetBrowserFilterModel*>(m_assetTreeView->model());
             if (!treeViewFilterModel)
             {
@@ -528,8 +527,8 @@ namespace AzToolsFramework
                 return;
             }
 
-            auto selectedIndexes = selected.indexes();
-            if (selectedIndexes.count() > 0)
+            const auto& selectedIndexes = selected.indexes();
+            if (!selectedIndexes.empty())
             {
                 auto newRootIndex = m_tableViewProxyModel->mapFromSource(
                     m_assetFilterModel->mapFromSource(treeViewFilterModel->mapToSource(selectedIndexes[0])));
@@ -539,6 +538,8 @@ namespace AzToolsFramework
             {
                 m_tableViewWidget->setRootIndex({});
             }
+
+            m_assetFilterModel->sort(0, Qt::DescendingOrder);
         }
 
         void AssetBrowserTableView::UpdateFilterInLocalFilterModel()
@@ -561,36 +562,33 @@ namespace AzToolsFramework
             }
 
             bool hasString{ false };
+            const QString tagString("String");
+            const QString tagFolder("Folder");
             auto filterCopy = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
-            for (auto& subFilter : filter->GetSubFilters())
+            for (const auto& subFilter : filter->GetSubFilters())
             {
-                // Switch between "search mode" where all results in the asset folder tree are shown,
-                // and "normal mode", where only contents for a single folder are shown, depending on
-                // whether there is an active string search ongoing.
-                if (subFilter->GetTag() == "String")
+                if (subFilter->GetTag() == tagString)
                 {
                     auto stringCompFilter = qobject_cast<const CompositeFilter*>(subFilter.get());
-                    if (!stringCompFilter)
-                    {
-                        continue;
-                    }
-
-                    auto stringSubFilters = stringCompFilter->GetSubFilters();
-
-                    hasString = stringSubFilters.count() != 0;
-                    m_tableViewProxyModel->SetShowSearchResultsMode(hasString);
-                    m_tableViewWidget->SetShowSearchResultsMode(hasString);
+                    hasString |= stringCompFilter && !stringCompFilter->GetSubFilters().empty();
                 }
 
                 // Skip the folder filter on the table view so that we can see files
-                if (subFilter->GetTag() != "Folder")
+                if (subFilter->GetTag() != tagFolder)
                 {
-                    filterCopy->AddFilter(subFilter);
+                    filterCopy->AddFilter(FilterConstType(subFilter->Clone()));
                 }
             }
+
+            // Switch between "search mode" where all results in the asset folder tree are shown,
+            // and "normal mode", where only contents for a single folder are shown, depending on
+            // whether there is an active string search ongoing.
+            m_tableViewProxyModel->SetShowSearchResultsMode(hasString);
+            m_tableViewWidget->SetShowSearchResultsMode(hasString);
+
             if (hasString)
             {
-                for (auto& subFilter : filterCopy->GetSubFilters())
+                for (const auto& subFilter : filter->GetSubFilters())
                 {
                     auto anyCompFilter = qobject_cast<const CompositeFilter*>(subFilter.get());
                     if (anyCompFilter)
@@ -598,19 +596,14 @@ namespace AzToolsFramework
                         auto myCompFilter = const_cast<CompositeFilter*>(anyCompFilter);
                         myCompFilter->SetFilterPropagation(AssetBrowserEntryFilter::None);
                     }
-
                 }
-                using EntryType = AssetBrowserEntry::AssetEntryType;
-                EntryType types[] = { EntryType::Folder, EntryType::Root, EntryType::Source };
-                auto productFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::OR);
+
+                auto productFilter = new CustomFilter([](const AssetBrowserEntry* entry) {
+                    return entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Product;
+                });
                 productFilter->SetName("NoProduct");
-                for (auto type : types)
-                {
-                    EntryTypeFilter* entryTypeFilter = new EntryTypeFilter();
-                    entryTypeFilter->SetEntryType(type);
-                    entryTypeFilter->SetFilterPropagation(AssetBrowserEntryFilter::None);
-                    productFilter->AddFilter(FilterConstType(entryTypeFilter));
-                }
+                productFilter->SetFilterPropagation(AssetBrowserEntryFilter::None);
+
                 filterCopy->AddFilter(FilterConstType(productFilter));
                 filterCopy->SetFilterPropagation(AssetBrowserEntryFilter::None);
             }
@@ -618,7 +611,9 @@ namespace AzToolsFramework
             {
                 filterCopy->SetFilterPropagation(AssetBrowserEntryFilter::Up | AssetBrowserEntryFilter::Down);
             }
+
             m_assetFilterModel->SetFilter(FilterConstType(filterCopy));
+
             if (hasString)
             {
                 m_tableViewWidget->expandAll();
@@ -633,22 +628,19 @@ namespace AzToolsFramework
 
         void AssetBrowserTableView::SetSortMode(const AssetBrowserEntry::AssetEntrySortMode mode)
         {
-            if (mode == m_assetFilterModel->GetSortMode())
+            // If the sort mode is being set to the same value then alternate the sort order
+            if (m_assetFilterModel->GetSortMode() == mode)
             {
-                if (m_assetFilterModel->GetSortOrder() == Qt::DescendingOrder)
-                {
-                    m_assetFilterModel->SetSortOrder(Qt::AscendingOrder);
-                }
-                else
-                {
-                    m_assetFilterModel->SetSortOrder(Qt::DescendingOrder);
-                }
+                m_assetFilterModel->SetSortOrder(
+                    m_assetFilterModel->GetSortOrder() == Qt::DescendingOrder ? Qt::AscendingOrder : Qt::DescendingOrder);
             }
-            m_assetFilterModel->SetSortMode(mode);
 
+            m_assetFilterModel->SetSortMode(mode);
             m_assetFilterModel->sort(0, m_assetFilterModel->GetSortOrder());
+            m_assetFilterModel->setDynamicSortFilter(true);
 
-            m_tableViewWidget->header()->setSortIndicator(SortModeToColumn(m_assetFilterModel->GetSortMode()), m_assetFilterModel->GetSortOrder());
+            m_tableViewWidget->header()->setSortIndicator(
+                SortModeToColumn(m_assetFilterModel->GetSortMode()), m_assetFilterModel->GetSortOrder());
         }
 
         AssetBrowserEntry::AssetEntrySortMode AssetBrowserTableView::GetSortMode() const
@@ -663,7 +655,6 @@ namespace AzToolsFramework
 
         TableViewDelegate::TableViewDelegate(QWidget* parent)
             : QStyledItemDelegate(parent)
-
         {
         }
 
@@ -704,8 +695,7 @@ namespace AzToolsFramework
             }
         }
 
-        QWidget* TableViewDelegate::createEditor(
-            QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
+        QWidget* TableViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
         {
             QWidget* widget = QStyledItemDelegate::createEditor(parent, option, index);
             if (auto* lineEdit = qobject_cast<QLineEdit*>(widget))

+ 32 - 43
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserThumbnailView.cpp

@@ -46,12 +46,9 @@ namespace AzToolsFramework
         {
             // Using our own instance of AssetBrowserFilterModel to be able to show also files when the main model
             // only lists directories, and at the same time get sort and filter entries features from AssetBrowserFilterModel.
-
-            // Turn off DynamicSort as sorting is now manual.
-            m_assetFilterModel->setDynamicSortFilter(false);
-            m_assetFilterModel->sort(0, Qt::DescendingOrder);
             m_thumbnailViewProxyModel->setSourceModel(m_assetFilterModel);
             m_thumbnailViewWidget->setModel(m_thumbnailViewProxyModel);
+            SetSortMode(AssetBrowserEntry::AssetEntrySortMode::Name);
 
             connect(
                 m_thumbnailViewWidget,
@@ -101,7 +98,7 @@ namespace AzToolsFramework
                 this,
                 [this]()
                 {
-                    AZStd::vector<const AssetBrowserEntry*> entries = AZStd::move(GetSelectedAssets());
+                    auto entries = AZStd::move(GetSelectedAssets());
                     if (entries.empty() && m_assetTreeView)
                     {
                         // Tree has the current open folder selected if context is valid (not searching, etc)
@@ -245,28 +242,25 @@ namespace AzToolsFramework
 
         void AssetBrowserThumbnailView::DeleteEntries()
         {
-            auto entries = GetSelectedAssets(false); // you cannot delete product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot delete product files.
             AssetBrowserViewUtils::DeleteEntries(entries, this);
         }
 
         void AssetBrowserThumbnailView::MoveEntries()
         {
-            auto entries = GetSelectedAssets(false); // you cannot move product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot move product files.
             AssetBrowserViewUtils::MoveEntries(entries, this);
         }
 
         void AssetBrowserThumbnailView::DuplicateEntries()
         {
-            auto entries = GetSelectedAssets(false); // you may not duplicate product files.
+            const auto& entries = GetSelectedAssets(false); // you may not duplicate product files.
             AssetBrowserViewUtils::DuplicateEntries(entries);
         }
 
         void AssetBrowserThumbnailView::RenameEntry()
         {
-            auto entries = GetSelectedAssets(false); // you cannot rename product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot rename product files.
             if (AssetBrowserViewUtils::RenameEntry(entries, this))
             {
                 QModelIndex selectedIndex = m_thumbnailViewWidget->selectionModel()->selectedIndexes()[0];
@@ -276,8 +270,7 @@ namespace AzToolsFramework
 
         void AssetBrowserThumbnailView::AfterRename(QString newVal)
         {
-            auto entries = GetSelectedAssets(false); // you cannot rename product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot rename product files.
             AssetBrowserViewUtils::AfterRename(newVal, entries, this);
         }
 
@@ -289,16 +282,12 @@ namespace AzToolsFramework
                 AssetBrowserModel::SourceIndexesToAssetDatabaseEntries(m_thumbnailViewWidget->selectionModel()->selectedIndexes(), entries);
                 if (!includeProducts)
                 {
-                    entries.erase(
-                        AZStd::remove_if(
-                            entries.begin(),
-                            entries.end(),
-                            [&](const AssetBrowserEntry* entry) -> bool
-                            {
-                                return entry->GetEntryType() ==
-                                    AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product;
-                            }),
-                        entries.end());
+                    AZStd::erase_if(
+                        entries,
+                        [&](const AssetBrowserEntry* entry) -> bool
+                        {
+                            return entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product;
+                        });
                 }
             }
             return entries;
@@ -321,13 +310,13 @@ namespace AzToolsFramework
             }
 
             m_assetTreeView = treeView;
-            m_assetTreeView->SetAttachedThumbnailView(this);
-
             if (!m_assetTreeView)
             {
                 return;
             }
 
+            m_assetTreeView->SetAttachedThumbnailView(this);
+
             auto treeViewFilterModel = qobject_cast<AssetBrowserFilterModel*>(m_assetTreeView->model());
             if (!treeViewFilterModel)
             {
@@ -441,6 +430,8 @@ namespace AzToolsFramework
             {
                 m_thumbnailViewWidget->setRootIndex({});
             }
+
+            m_assetFilterModel->sort(0, Qt::DescendingOrder);
         }
 
         void AssetBrowserThumbnailView::OpenItemForEditing(const QModelIndex& index)
@@ -477,32 +468,31 @@ namespace AzToolsFramework
                 return;
             }
 
+            bool hasString{ false };
+            const QString tagString("String");
+            const QString tagFolder("Folder");
             auto filterCopy = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
             for (const auto& subFilter : filter->GetSubFilters())
             {
-                // Switch between "search mode" where all results in the asset folder tree are shown,
-                // and "normal mode", where only contents for a single folder are shown, depending on
-                // whether there is an active string search ongoing.
-                if (subFilter->GetTag() == "String")
+                if (subFilter->GetTag() == tagString)
                 {
                     auto stringCompFilter = qobject_cast<const CompositeFilter*>(subFilter.get());
-                    if (!stringCompFilter)
-                    {
-                        continue;
-                    }
-
-                    auto stringSubFilters = stringCompFilter->GetSubFilters();
-
-                    m_thumbnailViewProxyModel->SetShowSearchResultsMode(stringSubFilters.count() != 0);
-                    m_thumbnailViewWidget->SetShowSearchResultsMode(stringSubFilters.count() != 0);
+                    hasString |= stringCompFilter && !stringCompFilter->GetSubFilters().empty();
                 }
 
                 // Skip the folder filter on the thumbnail view so that we can see files
-                if (subFilter->GetTag() != "Folder")
+                if (subFilter->GetTag() != tagFolder)
                 {
-                    filterCopy->AddFilter(subFilter);
+                    filterCopy->AddFilter(FilterConstType(subFilter->Clone()));
                 }
             }
+
+            // Switch between "search mode" where all results in the asset folder tree are shown,
+            // and "normal mode", where only contents for a single folder are shown, depending on
+            // whether there is an active string search ongoing.
+            m_thumbnailViewProxyModel->SetShowSearchResultsMode(hasString);
+            m_thumbnailViewWidget->SetShowSearchResultsMode(hasString);
+
             filterCopy->SetFilterPropagation(AssetBrowserEntryFilter::Down);
 
             m_assetFilterModel->SetFilter(FilterConstType(filterCopy));
@@ -511,8 +501,8 @@ namespace AzToolsFramework
         void AssetBrowserThumbnailView::SetSortMode(const AssetBrowserEntry::AssetEntrySortMode mode)
         {
             m_assetFilterModel->SetSortMode(mode);
-
             m_assetFilterModel->sort(0, Qt::DescendingOrder);
+            m_assetFilterModel->setDynamicSortFilter(true);
         }
 
        AssetBrowserEntry::AssetEntrySortMode AssetBrowserThumbnailView::GetSortMode() const
@@ -547,6 +537,5 @@ namespace AzToolsFramework
         {
             m_thumbnailViewProxyModel->SetSearchString(searchString);
         }
-
     } // namespace AssetBrowser
 } // namespace AzToolsFramework

+ 16 - 22
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp

@@ -196,15 +196,12 @@ namespace AzToolsFramework
 
             if (!includeProducts)
             {
-                entries.erase(
-                    AZStd::remove_if(
-                        entries.begin(),
-                        entries.end(),
-                        [&](const AssetBrowserEntry* entry) -> bool
-                        {
-                            return entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product;
-                        }),
-                    entries.end());
+                AZStd::erase_if(
+                    entries,
+                    [&](const AssetBrowserEntry* entry) -> bool
+                    {
+                        return entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product;
+                    });
             }
 
             return entries;
@@ -222,8 +219,7 @@ namespace AzToolsFramework
         void AssetBrowserTreeView::SelectFileAtPathAfterUpdate(const AZStd::string& assetPath)
         {
             m_fileToSelectAfterUpdate = assetPath;
-        }
-        
+        }        
 
         void AssetBrowserTreeView::SelectFileAtPath(const AZStd::string& assetPath)
         {
@@ -611,6 +607,8 @@ namespace AzToolsFramework
             AZ_Assert(m_assetBrowserSortFilterProxyModel, "Expecting AssetBrowserFilterModel");
             m_assetBrowserModel = qobject_cast<AssetBrowserModel*>(m_assetBrowserSortFilterProxyModel->sourceModel());
             QTreeViewWithStateSaving::setModel(model);
+
+            SetSortMode(AssetBrowserEntry::AssetEntrySortMode::Name);
         }
 
         void AssetBrowserTreeView::dragEnterEvent(QDragEnterEvent* event)
@@ -673,7 +671,7 @@ namespace AzToolsFramework
             using namespace AzQtComponents;
             DragAndDropContextBase context;
             DragAndDropEventsBus::Event(
-                DragAndDropContexts::EditorMainWindow, &DragAndDropEvents::DropAtLocation, event, context, QString(pathName.data()));
+                DragAndDropContexts::EditorMainWindow, &DragAndDropEvents::DropAtLocation, event, context, QString(pathName.c_str()));
         }
 
         void AssetBrowserTreeView::dragLeaveEvent(QDragLeaveEvent* event)
@@ -749,15 +747,13 @@ namespace AzToolsFramework
 
         void AssetBrowserTreeView::DeleteEntries()
         {
-            auto entries = GetSelectedAssets(false); // you cannot delete product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot delete product files.
             AssetBrowserViewUtils::DeleteEntries(entries, this);
         }
 
         void AssetBrowserTreeView::RenameEntry()
         {
-            auto entries = GetSelectedAssets(false); // you cannot rename product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot rename product files.
             if (AssetBrowserViewUtils::RenameEntry(entries, this))
             {
                 edit(currentIndex());
@@ -766,21 +762,19 @@ namespace AzToolsFramework
 
         void AssetBrowserTreeView::AfterRename(QString newVal)
         {
-            auto entries = GetSelectedAssets(false); // you cannot rename product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot rename product files.
             AssetBrowserViewUtils::AfterRename(newVal, entries, this);
         }
 
         void AssetBrowserTreeView::DuplicateEntries()
         {
-            auto entries = GetSelectedAssets(false); // you may not duplicate product files.
+            const auto& entries = GetSelectedAssets(false); // you may not duplicate product files.
             AssetBrowserViewUtils::DuplicateEntries(entries);
         }
 
         void AssetBrowserTreeView::MoveEntries()
         {
-            auto entries = GetSelectedAssets(false); // you cannot move product files.
-
+            const auto& entries = GetSelectedAssets(false); // you cannot move product files.
             AssetBrowserViewUtils::MoveEntries(entries, this);
         }
 
@@ -825,8 +819,8 @@ namespace AzToolsFramework
         void AssetBrowserTreeView::SetSortMode(const AssetBrowserEntry::AssetEntrySortMode mode)
         {
             m_assetBrowserSortFilterProxyModel->SetSortMode(mode);
-
             m_assetBrowserSortFilterProxyModel->sort(0, Qt::DescendingOrder);
+            m_assetBrowserSortFilterProxyModel->setDynamicSortFilter(true);
         }
 
         AssetBrowserEntry::AssetEntrySortMode AssetBrowserTreeView::GetSortMode() const

+ 4 - 4
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp

@@ -114,9 +114,9 @@ namespace AzToolsFramework
                 ? qvariant_cast<QString>(entry->data(aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName)))
                 : qvariant_cast<QString>(entry->data(aznumeric_cast<int>(AssetBrowserEntry::Column::Path)));
 
-            if (!m_searchString.empty())
+            if (!m_searchString.isEmpty())
             {
-                displayString = AzToolsFramework::RichTextHighlighter::HighlightText(displayString, m_searchString.c_str());
+                displayString = AzToolsFramework::RichTextHighlighter::HighlightText(displayString, m_searchString);
             }
 
             RichTextHighlighter::PaintHighlightedRichText(displayString, painter, actualOption, remainingRect);
@@ -214,9 +214,9 @@ namespace AzToolsFramework
             return m_iconSize;
         }
 
-        void EntryDelegate::SetSearchString(QString searchString)
+        void EntryDelegate::SetSearchString(const QString& searchString)
         {
-            m_searchString = searchString.toUtf8().data();
+            m_searchString = searchString;
         }
 
         SearchEntryDelegate::SearchEntryDelegate(QWidget* parent)

+ 2 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h

@@ -57,7 +57,7 @@ namespace AzToolsFramework
             //! Set whether to show source control icons, this is still temporary mainly to support existing functionality of material browser
             void SetShowSourceControlIcons(bool showSourceControl);
             void SetShowFavoriteIcons(bool showFavoriteIcons);
-            void SetSearchString(QString searchString);
+            void SetSearchString(const QString& searchString);
 
         signals:
             void RenameEntry(const QString& value) const;
@@ -68,7 +68,7 @@ namespace AzToolsFramework
             bool m_showFavoriteIcons = false;
             //! Draw a thumbnail and return its width
             int DrawThumbnail(QPainter* painter, const QPoint& point, const QSize& size, const AssetBrowserEntry* entry) const;
-            AZStd::string m_searchString;
+            QString m_searchString;
         };
 
         //! SearchEntryDelegate draws a single item in AssetBrowserListView.

+ 1 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/Model/AssetCompleterModel.cpp

@@ -72,7 +72,7 @@ namespace AzToolsFramework
         emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
     }
 
-    void AssetCompleterModel::SearchStringHighlight(QString searchString)
+    void AssetCompleterModel::SearchStringHighlight(const QString& searchString)
     {
         m_highlightString = searchString;
     }

+ 1 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/Model/AssetCompleterModel.h

@@ -36,7 +36,7 @@ namespace AzToolsFramework
         void SetFilter(const AZStd::vector<AZ::Data::AssetType>& assetTypes);
         void SetFilter(FilterConstType filter);
         void RefreshAssetList();
-        void SearchStringHighlight(QString searchString);
+        void SearchStringHighlight(const QString& searchString);
 
         Qt::ItemFlags flags(const QModelIndex &index) const override;
 

+ 0 - 2
Gems/GraphModel/Code/Include/GraphModel/Model/Slot.h

@@ -66,8 +66,6 @@ namespace GraphModel
         bool operator>(const SlotId& rhs) const;
 
         AZStd::size_t GetHash() const;
-        AZStd::string GetRepr() const { return AZStd::string::format("GraphModelSlotId(%s,%d", m_name.c_str(), m_subId); }
-
         AZStd::string ToString() const;
 
         SlotName m_name;

+ 1 - 1
Gems/GraphModel/Code/Source/Model/Slot.cpp

@@ -47,9 +47,9 @@ namespace GraphModel
                 ->Constructor<const SlotName&>()
                 ->Constructor<const SlotName&, SlotSubId>()
                 ->Method("__repr__", &SlotId::ToString)
+                ->Method("ToString", &SlotId::ToString)
                 ->Method("IsValid", &SlotId::IsValid)
                 ->Method("GetHash", &SlotId::GetHash)
-                ->Method("__repr__", [](SlotId* self) { return self->GetRepr(); })
                 ->Property("name", BehaviorValueProperty(&SlotId::m_name))
                 ->Property("subId", BehaviorValueProperty(&SlotId::m_subId))
                 ;

+ 10 - 1
Gems/LyShine/Code/Editor/AssetTreeEntry.cpp

@@ -27,6 +27,15 @@ UISliceLibraryFilter::UISliceLibraryFilter(const AZ::Data::AssetType& assetType,
     SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::Down);
 }
 
+AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter* UISliceLibraryFilter::Clone() const
+{
+    auto clone = new UISliceLibraryFilter(m_assetType, m_pathToSearch.c_str());
+    clone->m_name = m_name;
+    clone->m_tag = m_tag;
+    clone->m_direction = m_direction;
+    return clone;
+}
+
 QString UISliceLibraryFilter::GetNameInternal() const
 {
     return "UISliceLibraryFilter";
@@ -124,7 +133,7 @@ AssetTreeEntry* AssetTreeEntry::BuildAssetTree(const AZ::Data::AssetType& assetT
 
     // UISliceLibraryFilter::Filter function returns all assets (recursively) that match the specified filter
     // in this case we are only looking for ui slices.
-    AZStd::vector<const AssetBrowserEntry*> entries;
+    AZStd::unordered_set<const AssetBrowserEntry*> entries;
     UISliceLibraryFilter filter(assetType, pathToSearch.c_str());
     filter.Filter(entries, rootEntry.get());
 

+ 1 - 0
Gems/LyShine/Code/Editor/AssetTreeEntry.h

@@ -28,6 +28,7 @@ class UISliceLibraryFilter
 public:
     UISliceLibraryFilter(const AZ::Data::AssetType& assetType, const char* pathToSearch);
     ~UISliceLibraryFilter() override = default;
+    AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter* Clone() const override;
 
 protected:
     QString GetNameInternal() const override;

+ 15 - 0
README.md

@@ -5,6 +5,21 @@ O3DE (Open 3D Engine) is an open-source, real-time, multi-platform 3D engine tha
 ## Contribute
 For information about contributing to Open 3D Engine, visit [https://o3de.org/docs/contributing/](https://o3de.org/docs/contributing/).
 
+## Updates to this readme
+July 06, 2021
+- Switch licenses to APACHE-2.0 OR MIT
+
+May 14, 2021 
+- Removed instructions for the 3rdParty zip file and downloader URL. This is no longer a requirement. 
+- Updated instructions for dependencies
+- Links to full documentation
+
+April 7-13, 2021
+- Updates to the 3rdParty zip file
+
+March 25, 2021
+- Initial commit for instructions
+
 ## Download and Install
 
 This repository uses Git LFS for storing large binary files.