123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- /*
- * 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 <source/ui/SeedTabWidget.h>
- #include <source/ui/ui_SeedTabWidget.h>
- #include <source/utils/GUIApplicationManager.h>
- #include <source/ui/AddSeedDialog.h>
- #include <source/ui/EditSeedDialog.h>
- #include <source/ui/NewFileDialog.h>
- #include <source/models/SeedListFileTableModel.h>
- #include <source/models/SeedListTableModel.h>
- #include <AzCore/Outcome/Outcome.h>
- #include <AzCore/Utils/Utils.h>
- #include <AzFramework/StringFunc/StringFunc.h>
- #include <AzQtComponents/Components/FilteredSearchWidget.h>
- #include <AzToolsFramework/Asset/AssetSeedManager.h>
- #include <AzToolsFramework/AssetCatalog/PlatformAddressedAssetCatalog.h>
- #include <QCheckBox>
- #include <QFileDialog>
- #include <QItemSelection>
- #include <QItemSelectionRange>
- #include <QMessageBox>
- #include <QPushButton>
- const char GenerateAssetListFilesDialogName[] = "Generate Asset List Files";
- const int CheckBoxTableIndentationSize = 2; // when the indentation is 0, the checkboxes are too close to the edge
- namespace AssetBundler
- {
- SeedTabWidget::SeedTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager, const QString& assetBundlingDirectory)
- : AssetBundlerTabWidget(parent, guiApplicationManager)
- , m_fileTableModel(new SeedListFileTableModel(this))
- , m_seedListContentsModel(new SeedListTableModel())
- {
- AZ_UNUSED(assetBundlingDirectory);
- m_ui.reset(new Ui::SeedTabWidget);
- m_ui->setupUi(this);
- m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize);
- AZ::Debug::TraceMessageBus::Handler::BusConnect();
- // File view of all Seed List Files
- m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(
- this,
- m_fileTableModel->GetFileNameColumnIndex(),
- m_fileTableModel->GetTimeStampColumnIndex()));
- m_fileTableFilterModel->setSourceModel(m_fileTableModel.data());
- m_ui->fileTableView->setModel(m_fileTableFilterModel.data());
- connect(m_ui->fileFilteredSearchWidget,
- &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
- m_fileTableFilterModel.data(),
- static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
- connect(m_ui->fileTableView->selectionModel(),
- &QItemSelectionModel::selectionChanged,
- this,
- &SeedTabWidget::FileSelectionChanged);
- m_ui->fileTableView->setIndentation(CheckBoxTableIndentationSize);
- // New File Button
- connect(m_ui->createNewSeedListButton, &QPushButton::clicked, this, &SeedTabWidget::OnNewFileButtonPressed);
- // Select Default Seed Lists
- connect(m_ui->selectDefaultSeedListsCheckBox, &QCheckBox::clicked, this, &SeedTabWidget::OnSelectDefaultSeedListsCheckBoxChanged);
- // Generate Asset Lists Button
- SetGenerateAssetListsButtonEnabled(false);
- connect(m_ui->generateAssetListsButton, &QPushButton::clicked, this, &SeedTabWidget::OnGenerateAssetListsButtonPressed);
- // Table that displays the contents of a Seed List File
- m_seedListContentsFilterModel.reset(new AssetBundlerFileTableFilterModel(this, SeedListTableModel::Column::ColumnRelativePath));
- m_seedListContentsFilterModel->setSourceModel(m_seedListContentsModel.data());
- m_ui->seedFileContentsTable->setModel(m_seedListContentsFilterModel.data());
- connect(m_ui->seedListContentsFilteredSearchWidget,
- &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
- m_seedListContentsFilterModel.data(),
- static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
- m_ui->seedFileContentsTable->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(m_ui->seedFileContentsTable,
- &QTreeView::customContextMenuRequested,
- this,
- &SeedTabWidget::OnSeedListContentsTableContextMenuRequested);
- m_ui->seedFileContentsTable->setIndentation(0);
- // Edit All Platforms
- connect(m_ui->editAllSeedsButton, &QPushButton::clicked, this, &SeedTabWidget::OnEditAllButtonPressed);
- // Add Seed
- connect(m_ui->addSeedButton, &QPushButton::clicked, this, &SeedTabWidget::OnAddSeedButtonPressed);
- SetModelDataSource();
- }
- SeedTabWidget::~SeedTabWidget()
- {
- AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
- }
- bool SeedTabWidget::HasUnsavedChanges()
- {
- return m_fileTableModel->HasUnsavedChanges();
- }
- void SeedTabWidget::Reload()
- {
- // Reload all the seed list files
- m_fileTableModel->Reload(
- AzToolsFramework::AssetSeedManager::GetSeedFileExtension(),
- m_watchedFolders,
- m_watchedFiles,
- m_filePathToGemNameMap);
- // Update the selected row
- FileSelectionChanged();
- }
- bool SeedTabWidget::SaveCurrentSelection()
- {
- return m_fileTableModel->Save(m_selectedFileTableIndex);
- }
- bool SeedTabWidget::SaveAll()
- {
- return m_fileTableModel->SaveAll();
- }
- void SeedTabWidget::SetModelDataSource()
- {
- // Remove the current watched folders and files
- m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles);
- // Set the new watched folders for the model
- m_watchedFolders.clear();
- m_watchedFolders.insert(m_guiApplicationManager->GetSeedListsFolder().c_str());
- // Get the list of default Seed List files
- m_filePathToGemNameMap = AssetBundler::GetDefaultSeedListFiles(
- AZStd::string_view{ AZ::Utils::GetEnginePath() },
- m_guiApplicationManager->GetCurrentProjectName(),
- m_guiApplicationManager->GetGemInfoList(), m_guiApplicationManager->GetEnabledPlatforms());
- // Get the list of default Seeds that are not stored in a Seed List file on-disk
- AZStd::vector<AZStd::string> defaultSeeds =
- GetDefaultSeeds(AZ::Utils::GetProjectPath(), m_guiApplicationManager->GetCurrentProjectName());
- m_fileTableModel->AddDefaultSeedsToInMemoryList(
- defaultSeeds,
- m_guiApplicationManager->GetCurrentProjectName().c_str(),
- m_guiApplicationManager->GetEnabledPlatforms());
- // Set the new watched filess for the model
- m_watchedFiles.clear();
- for (const auto& it : m_filePathToGemNameMap)
- {
- m_watchedFiles.insert(it.first.c_str());
- }
- ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::SeedListFileType);
- m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles);
- }
- AzQtComponents::TableView* SeedTabWidget::GetFileTableView()
- {
- return m_ui->fileTableView;
- }
- QModelIndex SeedTabWidget::GetSelectedFileTableIndex()
- {
- return m_selectedFileTableIndex;
- }
- AssetBundlerAbstractFileTableModel* SeedTabWidget::GetFileTableModel()
- {
- return m_fileTableModel.get();
- }
- void SeedTabWidget::SetActiveProjectLabel(const QString& labelText)
- {
- m_ui->activeProjectLabel->setText(labelText);
- }
- void SeedTabWidget::ApplyConfig()
- {
- const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig();
- m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth);
- m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnFileName, config.seedListFileNameColumnWidth);
- m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnCheckBox, config.checkBoxColumnWidth);
- m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnProject, config.projectNameColumnWidth);
- m_ui->seedFileContentsTable->header()->resizeSection(
- SeedListTableModel::Column::ColumnRelativePath,
- config.seedListContentsNameColumnWidth);
- }
- void SeedTabWidget::UncheckSelectDefaultSeedListsCheckBox()
- {
- m_ui->selectDefaultSeedListsCheckBox->setChecked(false);
- }
- void SeedTabWidget::SetGenerateAssetListsButtonEnabled(bool isEnabled)
- {
- m_ui->generateAssetListsButton->setEnabled(isEnabled);
- }
- bool SeedTabWidget::OnPreError(
- const char* /*window*/,
- const char* /*fileName*/,
- int /*line*/,
- const char* /*func*/,
- const char* /*message*/)
- {
- m_hasWarningsOrErrors = true;
- return false;
- }
- bool SeedTabWidget::OnPreWarning(
- const char* /*window*/,
- const char* /*fileName*/,
- int /*line*/,
- const char* /*func*/,
- const char* /*message*/)
- {
- m_hasWarningsOrErrors = true;
- return false;
- }
- void SeedTabWidget::FileSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/)
- {
- if (m_ui->fileTableView->selectionModel()->selectedRows().size() == 0)
- {
- // Set selected index to an invalid value
- m_selectedFileTableIndex = QModelIndex();
- m_ui->seedListFileAbsolutePathLabel->clear();
- return;
- }
- m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->fileTableView->selectionModel()->currentIndex());
- m_seedListContentsModel = m_fileTableModel->GetSeedListFileContents(m_selectedFileTableIndex);
- m_seedListContentsFilterModel->setSourceModel(m_seedListContentsModel.data());
- m_ui->seedListFileAbsolutePathLabel->setText(m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex).c_str());
- }
- void SeedTabWidget::OnNewFileButtonPressed()
- {
- AZStd::string absoluteFilePath = NewFileDialog::OSNewFileDialog(
- this,
- AzToolsFramework::AssetSeedManager::GetSeedFileExtension(),
- "Seed List",
- m_guiApplicationManager->GetSeedListsFolder());
- if (absoluteFilePath.empty())
- {
- // User canceled out of the file dialog
- return;
- }
- AZStd::vector<AZStd::string> createdFiles = m_fileTableModel->CreateNewFiles(
- absoluteFilePath,
- AzFramework::PlatformFlags::Platform_NONE,
- QString(m_guiApplicationManager->GetCurrentProjectName().c_str()));
- if (!createdFiles.empty())
- {
- AddScanPathToAssetBundlerSettings(AssetBundlingFileType::SeedListFileType, createdFiles.at(0));
- }
- }
- void SeedTabWidget::OnSelectDefaultSeedListsCheckBoxChanged()
- {
- m_fileTableModel->SelectDefaultSeedLists(m_ui->selectDefaultSeedListsCheckBox->isChecked());
- }
- void SeedTabWidget::OnGenerateAssetListsButtonPressed()
- {
- m_generateAssetListsDialog.reset(
- new NewFileDialog(
- this,
- GenerateAssetListFilesDialogName,
- QString(m_guiApplicationManager->GetAssetListsFolder().c_str()),
- AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(),
- QString(tr("Asset List (*.%1)")).arg(AzToolsFramework::AssetSeedManager::GetAssetListFileExtension()),
- m_guiApplicationManager->GetEnabledPlatforms()));
- auto dialogResponse = m_generateAssetListsDialog->exec();
- if (dialogResponse == QDialog::DialogCode::Rejected)
- {
- // User canceled the operation
- return;
- }
- m_hasWarningsOrErrors = false;
- auto createdFiles = m_fileTableModel->GenerateAssetLists(
- m_generateAssetListsDialog->GetAbsoluteFilePath(),
- m_generateAssetListsDialog->GetPlatformFlags());
- // Warnings will not prevent the generation of Asset List files, we must track them separately
- NewFileDialog::FileGenerationResultMessageBox(this, createdFiles, m_hasWarningsOrErrors);
- if (createdFiles.empty())
- {
- // Error has already been thrown
- return;
- }
- // Add created files to the file watcher
- for (const AZStd::string& absolutePath : createdFiles)
- {
- AddScanPathToAssetBundlerSettings(AssetBundlingFileType::AssetListFileType, absolutePath);
- }
- // The watched files list was updated after the files were created, so we need to force-reload them
- m_guiApplicationManager->UpdateFiles(AssetBundlingFileType::AssetListFileType, createdFiles);
- }
- void SeedTabWidget::OnEditSeedButtonPressed()
- {
- if (!m_selectedFileTableIndex.isValid())
- {
- AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Edit Seed operation: No Seed List File is selected");
- return;
- }
- // Get the current platforms of the selected Seed so we can display them as already checked
- QModelIndex currentSeedIndex =
- m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex());
- auto getPlatformOutcome = m_seedListContentsModel->GetSeedPlatforms(currentSeedIndex);
- if (!getPlatformOutcome.IsSuccess())
- {
- // Error has already been thrown
- return;
- }
- // Create and display the Edit Seed dialog
- m_editSeedDialog.reset(new EditSeedDialog(this, m_guiApplicationManager->GetEnabledPlatforms(), getPlatformOutcome.GetValue()));
- auto dialogResponse = m_editSeedDialog->exec();
- if (dialogResponse == QDialog::DialogCode::Rejected)
- {
- // User canceled the operation
- return;
- }
- // Set the data in the model
- m_fileTableModel->SetSeedPlatforms(m_selectedFileTableIndex, currentSeedIndex, m_editSeedDialog->GetPlatformFlags());
- }
- void SeedTabWidget::OnEditAllButtonPressed()
- {
- if (!m_selectedFileTableIndex.isValid())
- {
- AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Edit All operation: No Seed List File is selected");
- return;
- }
- // Get the platforms of all the seeds so we can display them as already checked or partially checked
- AzFramework::PlatformFlags selectedPlatformFlags = AzFramework::PlatformFlags::AllNamedPlatforms;
- AzFramework::PlatformFlags partiallySelectedPlatformFlags = AzFramework::PlatformFlags::Platform_NONE;
- QMap<QModelIndex, AzFramework::PlatformFlags> indexToPlatformFlagsMap;
- for (int row = 0; row < m_seedListContentsModel->rowCount(); ++row)
- {
- QModelIndex currentSeedIndex = m_seedListContentsModel->index(row, 0);
- auto getPlatformOutcome = m_seedListContentsModel->GetSeedPlatforms(currentSeedIndex);
- if (!getPlatformOutcome.IsSuccess())
- {
- // Error has already been thrown
- return;
- }
- indexToPlatformFlagsMap[currentSeedIndex] = getPlatformOutcome.TakeValue();
- selectedPlatformFlags &= indexToPlatformFlagsMap[currentSeedIndex];
- partiallySelectedPlatformFlags |= selectedPlatformFlags ^ indexToPlatformFlagsMap[currentSeedIndex];
- }
- // Create and display the Edit Seed dialog
- m_editSeedDialog.reset(new EditSeedDialog(
- this,
- m_guiApplicationManager->GetEnabledPlatforms(),
- selectedPlatformFlags,
- partiallySelectedPlatformFlags));
- auto dialogResponse = m_editSeedDialog->exec();
- if (dialogResponse == QDialog::DialogCode::Rejected)
- {
- // User canceled the operation
- return;
- }
- // Set the data in the model
- for (int row = 0; row < m_seedListContentsModel->rowCount(); ++row)
- {
- QModelIndex currentSeedIndex = m_seedListContentsModel->index(row, 0);
- AzFramework::PlatformFlags checkedPlatforms = m_editSeedDialog->GetPlatformFlags();
- AzFramework::PlatformFlags partiallyCheckedPlatforms = m_editSeedDialog->GetPartiallySelectedPlatformFlags();
- // If the platform is partially checked, we want to keep its original status when saving the changes
- AzFramework::PlatformFlags platformFlags =
- indexToPlatformFlagsMap[currentSeedIndex] & partiallyCheckedPlatforms | checkedPlatforms;
- m_fileTableModel->SetSeedPlatforms(m_selectedFileTableIndex, currentSeedIndex, platformFlags);
- }
- }
- void SeedTabWidget::OnAddSeedButtonPressed()
- {
- if (!m_selectedFileTableIndex.isValid())
- {
- AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Add Seed operation: No Seed List File is selected");
- return;
- }
- // Get path to the platform-specific cache folder of one of the enabled platforms
- AzFramework::PlatformFlags enabledPlatforms = m_guiApplicationManager->GetEnabledPlatforms();
- AZStd::fixed_vector<AzFramework::PlatformId, AzFramework::PlatformId::NumPlatformIds> enabledPlatformIndices =
- AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(enabledPlatforms);
- AZStd::string platformSpecificCachePath =
- AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(enabledPlatformIndices[0]);
- // Create and display the Add Seed Dialog
- m_addSeedDialog.reset(new AddSeedDialog(this, enabledPlatforms, platformSpecificCachePath));
- auto dialogResponse = m_addSeedDialog->exec();
- if (dialogResponse == QDialog::DialogCode::Rejected)
- {
- // User canceled the operation
- return;
- }
- // Set the data in the model
- m_fileTableModel->AddSeed(m_selectedFileTableIndex, m_addSeedDialog->GetFileName(), m_addSeedDialog->GetPlatformFlags());
- }
- void SeedTabWidget::OnRemoveSeedButtonPressed()
- {
- if (!m_selectedFileTableIndex.isValid())
- {
- AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Remove Seed operation: No Seed List File is selected");
- return;
- }
- // Set the data in the model
- QModelIndex currentSeedIndex =
- m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex());
- m_fileTableModel->RemoveSeed(m_selectedFileTableIndex, currentSeedIndex);
- }
- void SeedTabWidget::OnSeedListContentsTableContextMenuRequested(const QPoint& pos)
- {
- if (!m_selectedFileTableIndex.isValid())
- {
- return;
- }
- QMenu* contextMenu = new QMenu(this);
- contextMenu->setToolTipsVisible(true);
- QAction* action = contextMenu->addAction(tr("Edit Platforms"));
- connect(action, &QAction::triggered, this, &SeedTabWidget::OnEditSeedButtonPressed);
- action->setToolTip(tr("Change what platforms are referenced when generating an Asset List file."));
- contextMenu->addSeparator();
- action = contextMenu->addAction(tr("Add Seed"));
- connect(action, &QAction::triggered, this, &SeedTabWidget::OnAddSeedButtonPressed);
- action->setToolTip(tr("Add a new Seed to the Seed List file."));
- action = contextMenu->addAction(tr("Remove Seed"));
- connect(action, &QAction::triggered, this, &SeedTabWidget::OnRemoveSeedButtonPressed);
- action->setToolTip(tr("Removes the Seed from the Seed List file."));
- contextMenu->exec(m_ui->seedFileContentsTable->mapToGlobal(pos));
- delete contextMenu;
- }
- } //namespace AssetBundler
- #include <source/ui/moc_SeedTabWidget.cpp>
|