Files
o3de/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp
T
guthadam 5593350f84 ATOM-15372 Restoring material browser filter logic
Restoring material browser filter logic to only show folders with content that matches the filter.

This change was originally introduced with the functionality to create a new folder within the material browser.  Creating a new, empty folder would not display the folder in the browser because it did not have any content that matched the filter.  While that makes sense to address the issue with the create folder command, it makes it extremely difficult and navigate the browser to find assets that match the filter because every folder that does not match the filter is also displayed in the tree.  We can revisit issues with the create folder action later.

https://jira.agscollab.com/browse/ATOM-15372
2021-04-27 17:12:42 -05:00

238 lines
10 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/Document/MaterialDocumentSystemRequestBus.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
#include <Source/Window/MaterialBrowserWidget.h>
#include <Source/Window/ui_MaterialBrowserWidget.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QAction>
#include <QByteArray>
#include <QCursor>
#include <QDesktopServices>
#include <QList>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QUrl>
AZ_POP_DISABLE_WARNING
namespace MaterialEditor
{
MaterialBrowserWidget::MaterialBrowserWidget(QWidget* parent)
: QWidget(parent)
, m_ui(new Ui::MaterialBrowserWidget)
{
using namespace AzToolsFramework::AssetBrowser;
m_ui->setupUi(this);
m_ui->m_searchWidget->Setup(true, true);
m_ui->m_searchWidget->SetFilterState("", AZ::RPI::StreamingImageAsset::Group, true);
m_ui->m_searchWidget->SetFilterState("", AZ::RPI::MaterialAsset::Group, true);
m_ui->m_searchWidget->setMinimumSize(QSize(150, 0));
m_ui->m_viewOptionButton->setIcon(QIcon(":/Icons/View.svg"));
m_ui->m_splitter->setSizes(QList<int>() << 400 << 200);
m_ui->m_splitter->setStretchFactor(0, 1);
connect(m_ui->m_viewOptionButton, &QPushButton::clicked, this, &MaterialBrowserWidget::OpenOptionsMenu);
// Get the asset browser model
AssetBrowserModel* assetBrowserModel = nullptr;
AssetBrowserComponentRequestBus::BroadcastResult(assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel);
AZ_Assert(assetBrowserModel, "Failed to get file browser model");
// Hook up the data set to the tree view
m_filterModel = aznew AssetBrowserFilterModel(this);
m_filterModel->setSourceModel(assetBrowserModel);
m_filterModel->SetFilter(CreateFilter());
m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel);
m_ui->m_assetBrowserTreeViewWidget->SetShowSourceControlIcons(false);
m_ui->m_assetBrowserTreeViewWidget->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
// Maintains the tree expansion state between runs
m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main");
connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel, &AssetBrowserFilterModel::filterUpdatedSlot);
connect(m_filterModel, &AssetBrowserFilterModel::filterChanged, this, [this]()
{
const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty();
constexpr bool selectFirstFilteredIndex = true;
m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex);
});
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::activated, this, &MaterialBrowserWidget::OpenSelectedEntries);
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, [this]() {
const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
if (!selectedAssets.empty())
{
m_ui->m_previewerFrame->Display(selectedAssets.front());
}
else
{
m_ui->m_previewerFrame->Clear();
}
});
MaterialDocumentNotificationBus::Handler::BusConnect();
}
MaterialBrowserWidget::~MaterialBrowserWidget()
{
// Maintains the tree expansion state between runs
m_ui->m_assetBrowserTreeViewWidget->SaveState();
MaterialDocumentNotificationBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
}
AzToolsFramework::AssetBrowser::FilterConstType MaterialBrowserWidget::CreateFilter() const
{
using namespace AzToolsFramework::AssetBrowser;
QSharedPointer<EntryTypeFilter> sourceFilter(new EntryTypeFilter);
sourceFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Source);
QSharedPointer<EntryTypeFilter> folderFilter(new EntryTypeFilter);
folderFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Folder);
QSharedPointer<CompositeFilter> sourceOrFolderFilter(new CompositeFilter(CompositeFilter::LogicOperatorType::OR));
sourceOrFolderFilter->AddFilter(sourceFilter);
sourceOrFolderFilter->AddFilter(folderFilter);
QSharedPointer<CompositeFilter> finalFilter(new CompositeFilter(CompositeFilter::LogicOperatorType::AND));
finalFilter->AddFilter(sourceOrFolderFilter);
finalFilter->AddFilter(m_ui->m_searchWidget->GetFilter());
return finalFilter;
}
void MaterialBrowserWidget::OpenSelectedEntries()
{
const AZStd::vector<AssetBrowserEntry*> entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
const int multiSelectPromptThreshold = 10;
if (entries.size() >= multiSelectPromptThreshold)
{
if (QMessageBox::question(
QApplication::activeWindow(),
QString("Attemptng to open %1 files").arg(entries.size()),
"Would you like to open anyway?",
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
{
return;
}
}
for (const AssetBrowserEntry* entry : entries)
{
if (entry)
{
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension))
{
MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath());
}
else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension))
{
//ignore MaterialTypeExtension
}
else
{
QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str()));
}
}
}
}
void MaterialBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId)
{
AZStd::string absolutePath;
MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
if (!absolutePath.empty())
{
// Selecting a new asset in the browser is not guaranteed to happen immediately.
// The asset browser model notifications are sent before the model is updated.
// Instead of relying on the notifications, queue the selection and process it on tick until this change occurs.
m_pathToSelect = absolutePath;
AzFramework::StringFunc::Path::Normalize(m_pathToSelect);
AZ::TickBus::Handler::BusConnect();
}
}
void MaterialBrowserWidget::OnTick(float deltaTime, AZ::ScriptTimePoint time)
{
AZ_UNUSED(time);
AZ_UNUSED(deltaTime);
if (!m_pathToSelect.empty())
{
// Attempt to select the new path
AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(
&AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Events::SelectFileAtPath, m_pathToSelect);
// Iterate over the selected entries to verify if the selection was made
for (const AssetBrowserEntry* entry : m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets())
{
if (entry)
{
AZStd::string sourcePath = entry->GetFullPath();
AzFramework::StringFunc::Path::Normalize(sourcePath);
if (m_pathToSelect == sourcePath)
{
// Once the selection is confirmed, cancel the operation and disconnect
AZ::TickBus::Handler::BusDisconnect();
m_pathToSelect.clear();
}
}
}
}
}
void MaterialBrowserWidget::OpenOptionsMenu()
{
QMenu menu;
QAction* action = new QAction("Show Asset Preview", this);
action->setCheckable(true);
action->setChecked(m_ui->m_previewerFrame->isVisible());
connect(action, &QAction::triggered, [this]() {
bool isPreviewFrameVisible = m_ui->m_previewerFrame->isVisible();
m_ui->m_previewerFrame->setVisible(!isPreviewFrameVisible);
if (isPreviewFrameVisible)
{
m_materialBrowserState = m_ui->m_splitter->saveState();
m_ui->m_splitter->setSizes(QList({ 1, 0 }));
}
else
{
m_ui->m_splitter->restoreState(m_materialBrowserState);
}
});
menu.addAction(action);
menu.exec(QCursor::pos());
}
} // namespace MaterialEditor
#include <Source/Window/moc_MaterialBrowserWidget.cpp>