c6ba1ef064
• This change is partially to unblock physics tool prototyping. It introduces a tool ID that is passed down into systems and acts as a context for document, window, and other systems and buses. • The document system component is no longer a component. It is just a system class that can be constructed with a tool ID. Internally, it will connect to its buses and be addressable by tool ID. More than one can be instantiated, each with a unique tool ID. • These changes are still backward compatible because most of the buses were using broadcast for standalone applications. All of those calls have been updated but not all of the scripts, which should still work as is. • Got rid of the window factory request bus in favor of just instantiating the main window or any other UI in the application layer. • Fixed a couple of bugs that were discovered while making these changes. Signed-off-by: Guthrie Adams <guthadam@amazon.com>
235 lines
9.5 KiB
C++
235 lines
9.5 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AssetBrowser/ui_AtomToolsAssetBrowser.h>
|
|
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h>
|
|
#include <AtomToolsFramework/Util/Util.h>
|
|
#include <AzFramework/StringFunc/StringFunc.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>
|
|
|
|
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
|
#include <QAction>
|
|
#include <QCursor>
|
|
#include <QMenu>
|
|
#include <QMessageBox>
|
|
#include <QPushButton>
|
|
AZ_POP_DISABLE_WARNING
|
|
|
|
namespace AtomToolsFramework
|
|
{
|
|
AtomToolsAssetBrowser::AtomToolsAssetBrowser(QWidget* parent)
|
|
: QWidget(parent)
|
|
, m_ui(new Ui::AtomToolsAssetBrowser)
|
|
{
|
|
using namespace AzToolsFramework::AssetBrowser;
|
|
|
|
m_ui->setupUi(this);
|
|
|
|
m_ui->m_searchWidget->Setup(true, 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);
|
|
|
|
// 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_filterModel, &AssetBrowserFilterModel::filterChanged, this, &AtomToolsAssetBrowser::UpdateFilter);
|
|
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::activated, this, &AtomToolsAssetBrowser::OpenSelectedEntries);
|
|
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AtomToolsAssetBrowser::UpdatePreview);
|
|
connect(m_ui->m_viewOptionButton, &QPushButton::clicked, this, &AtomToolsAssetBrowser::OpenOptionsMenu);
|
|
connect(
|
|
m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel,
|
|
&AssetBrowserFilterModel::filterUpdatedSlot);
|
|
}
|
|
|
|
AtomToolsAssetBrowser::~AtomToolsAssetBrowser()
|
|
{
|
|
// Maintains the tree expansion state between runs
|
|
m_ui->m_assetBrowserTreeViewWidget->SaveState();
|
|
AZ::TickBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::SetFilterState(const AZStd::string& category, const AZStd::string& displayName, bool enabled)
|
|
{
|
|
m_ui->m_searchWidget->SetFilterState(category.c_str(), displayName.c_str(), enabled);
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::SetOpenHandler(AZStd::function<void(const AZStd::string&)> openHandler)
|
|
{
|
|
m_openHandler = openHandler;
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::SelectEntries(const AZStd::string& absolutePath)
|
|
{
|
|
AZ::TickBus::Handler::BusDisconnect();
|
|
|
|
m_pathToSelect = absolutePath;
|
|
if (!m_pathToSelect.empty() && AzFramework::StringFunc::Path::Normalize(m_pathToSelect))
|
|
{
|
|
// 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.
|
|
AZ::TickBus::Handler::BusConnect();
|
|
}
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::OpenSelectedEntries()
|
|
{
|
|
const AZStd::vector<AssetBrowserEntry*> entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
|
|
|
|
const bool promptToOpenMultipleFiles =
|
|
GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/AssetBrowser/PromptToOpenMultipleFiles", true);
|
|
const AZ::u64 promptToOpenMultipleFilesThreshold =
|
|
GetSettingOrDefault<AZ::u64>("/O3DE/AtomToolsFramework/AssetBrowser/PromptToOpenMultipleFilesThreshold", 10);
|
|
|
|
if (promptToOpenMultipleFiles && promptToOpenMultipleFilesThreshold <= entries.size())
|
|
{
|
|
QMessageBox::StandardButton result = QMessageBox::question(
|
|
QApplication::activeWindow(),
|
|
tr("Attemptng to open %1 files").arg(entries.size()),
|
|
tr("Would you like to open anyway?"),
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
if (result == QMessageBox::No)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (const AssetBrowserEntry* entry : entries)
|
|
{
|
|
if (entry && entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Folder && m_openHandler)
|
|
{
|
|
m_openHandler(entry->GetFullPath().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::OpenOptionsMenu()
|
|
{
|
|
QMenu menu;
|
|
QAction* action = menu.addAction(tr("Show Asset Preview"), this, &AtomToolsAssetBrowser::TogglePreview);
|
|
action->setCheckable(true);
|
|
action->setChecked(m_ui->m_previewerFrame->isVisible());
|
|
menu.exec(QCursor::pos());
|
|
}
|
|
|
|
AzToolsFramework::AssetBrowser::FilterConstType AtomToolsAssetBrowser::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 AtomToolsAssetBrowser::UpdateFilter()
|
|
{
|
|
const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty();
|
|
constexpr bool selectFirstFilteredIndex = true;
|
|
m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex);
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::UpdatePreview()
|
|
{
|
|
const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
|
|
if (!selectedAssets.empty())
|
|
{
|
|
m_ui->m_previewerFrame->Display(selectedAssets.front());
|
|
}
|
|
else
|
|
{
|
|
m_ui->m_previewerFrame->Clear();
|
|
}
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::TogglePreview()
|
|
{
|
|
const bool isPreviewFrameVisible = m_ui->m_previewerFrame->isVisible();
|
|
m_ui->m_previewerFrame->setVisible(!isPreviewFrameVisible);
|
|
if (isPreviewFrameVisible)
|
|
{
|
|
m_browserState = m_ui->m_splitter->saveState();
|
|
m_ui->m_splitter->setSizes(QList({ 1, 0 }));
|
|
}
|
|
else
|
|
{
|
|
m_ui->m_splitter->restoreState(m_browserState);
|
|
}
|
|
}
|
|
|
|
void AtomToolsAssetBrowser::OnTick(float deltaTime, AZ::ScriptTimePoint time)
|
|
{
|
|
AZ_UNUSED(time);
|
|
AZ_UNUSED(deltaTime);
|
|
|
|
if (m_pathToSelect.empty())
|
|
{
|
|
AZ::TickBus::Handler::BusDisconnect();
|
|
m_pathToSelect.clear();
|
|
return;
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // namespace AtomToolsFramework
|
|
|
|
#include <AtomToolsFramework/AssetBrowser/moc_AtomToolsAssetBrowser.cpp>
|