/* * 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 #include #include #include #include #include #include #include #include #include #include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include #include #include #include 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() << 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 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 entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); const bool promptToOpenMultipleFiles = GetSettingOrDefault("/O3DE/AtomToolsFramework/AssetBrowser/PromptToOpenMultipleFiles", true); const AZ::u64 promptToOpenMultipleFilesThreshold = GetSettingOrDefault("/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 sourceFilter(new EntryTypeFilter); sourceFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Source); QSharedPointer folderFilter(new EntryTypeFilter); folderFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Folder); QSharedPointer sourceOrFolderFilter(new CompositeFilter(CompositeFilter::LogicOperatorType::OR)); sourceOrFolderFilter->AddFilter(sourceFilter); sourceOrFolderFilter->AddFilter(folderFilter); QSharedPointer 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