From 5cee8d18929c10b2bd67cbaaab0554e916360648 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 10 Sep 2021 10:59:40 -0700 Subject: [PATCH 01/24] stubbed out refactor of version explorer Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/View/Windows/MainWindow.cpp | 71 -- .../Code/Editor/View/Windows/MainWindow.h | 3 - .../Windows/Tools/UpgradeTool/FileSaver.cpp | 1023 +++++++++++++++++ .../Windows/Tools/UpgradeTool/FileSaver.h | 180 +++ .../Windows/Tools/UpgradeTool/Modifier.cpp | 1023 +++++++++++++++++ .../View/Windows/Tools/UpgradeTool/Modifier.h | 167 +++ .../Windows/Tools/UpgradeTool/Scanner.cpp | 1023 +++++++++++++++++ .../View/Windows/Tools/UpgradeTool/Scanner.h | 167 +++ .../Windows/Tools/UpgradeTool/UpgradeTool.cpp | 697 ----------- .../Windows/Tools/UpgradeTool/UpgradeTool.h | 149 --- .../Windows/Tools/UpgradeTool/UpgradeTool.ui | 260 ----- .../Tools/UpgradeTool/VersionExplorer.h | 10 +- .../Tools/UpgradeTool/VersionExplorerLog.cpp | 1023 +++++++++++++++++ .../Tools/UpgradeTool/VersionExplorerLog.h | 167 +++ .../Tools/UpgradeTool/VersionExplorerTraits.h | 19 + .../Code/scriptcanvasgem_editor_files.cmake | 11 +- 16 files changed, 4803 insertions(+), 1190 deletions(-) create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h delete mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp delete mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h delete mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.ui create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index fbe03ffc0a..856cceb508 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -704,78 +704,7 @@ namespace ScriptCanvasEditor m_autoSaveTimer.setSingleShot(true); connect(&m_autoSaveTimer, &QTimer::timeout, this, &MainWindow::OnAutoSave); - UpdateMenuState(false); - - PromptForUpgrade(); - } - - void MainWindow::PromptForUpgrade() - { - static bool displayUpgradePrompt = false; // Set to true if you need the upgrade dialog to show up on ScriptCanvas editor open - if (displayUpgradePrompt && m_showUpgradeTool) - { - QTimer::singleShot(1.f, this, [this]() - { - UpgradeTool* upgradeTool = aznew UpgradeTool(this); - - QPoint centerPoint = frameGeometry().center(); - - upgradeTool->adjustSize(); - upgradeTool->move(centerPoint.x() - upgradeTool->width() / 2, centerPoint.y() - upgradeTool->height() / 2); - - if (upgradeTool->exec() == QDialog::Accepted) - { - // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - QString message = QObject::tr("%1 Graph(s) upgraded
%2 graph(s) did not require upgrade").arg(upgradeTool->UpgradedGraphCount()).arg(upgradeTool->SkippedGraphCount()); - if (assetsThatNeedManualInspection > 0) - { - message.append(QObject::tr("
%1 graph(s) that need manual corrections. You will be prompted to review them after you close this dialog.
").arg(assetsThatNeedManualInspection)); - } - - // Report - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string outputFileName = AZStd::string::format("@devroot@/ScriptCanvasUpgradeReport.html"); - AZ::IO::FileIOBase::GetInstance()->ResolvePath(outputFileName.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - AZStd::string urlToReport = AZStd::string::format("For more information see the Upgrade Report.", resolvedBuffer); - message.append(QObject::tr("
%1").arg(urlToReport.c_str())); - - // Backup - if (upgradeTool->HasBackup()) - { - AZStd::string outputFileName2 = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP"); - - AZ::IO::FileIOBase::GetInstance()->ResolvePath(outputFileName2.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - - AZStd::string backupPath = AZStd::string::format("
Open the Backup Folder.", resolvedBuffer); - message.append(QObject::tr("%1").arg(backupPath.c_str())); - } - - // Done upgrading, show details - QMessageBox mb(QMessageBox::Information, - QObject::tr("Upgrade Complete"), - message, - QMessageBox::Ok, this); - mb.setTextFormat(Qt::RichText); - - centerPoint = frameGeometry().center(); - - mb.adjustSize(); - mb.move(centerPoint.x() - width() / 2, centerPoint.y() - height() / 2); - - mb.exec(); - - // If there are graphs that need manual correction, show the helper - if (assetsThatNeedManualInspection > 0) - { - UpgradeHelper* upgradeHelper = new UpgradeHelper(this); - upgradeHelper->show(); - } - } - - }); - } } MainWindow::~MainWindow() diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index d11d2f0052..ed00254677 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -51,7 +51,6 @@ #include -#include #include #if SCRIPTCANVAS_EDITOR @@ -806,7 +805,5 @@ namespace ScriptCanvasEditor Workspace* m_workspace; void OnSaveCallback(bool saveSuccess, AZ::Data::AssetPtr, AZ::Data::AssetId previousFileAssetId); - - void PromptForUpgrade(); }; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp new file mode 100644 index 0000000000..eb182ed291 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp @@ -0,0 +1,1023 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace VersionExplorerCpp +{ + class FileEventHandler + : public AZ::IO::FileIOEventBus::Handler + { + public: + int m_errorCode = 0; + AZStd::string m_fileName; + + FileEventHandler() + { + BusConnect(); + } + + ~FileEventHandler() + { + BusDisconnect(); + } + + void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override + { + m_errorCode = errorCode; + + if (fileName) + { + m_fileName = fileName; + } + } + }; +} + +namespace ScriptCanvasEditor +{ + EditorKeepAlive::EditorKeepAlive() + { + ISystem* system = nullptr; + CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); + + m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); + + if (m_edKeepEditorActive) + { + m_keepEditorActive = m_edKeepEditorActive->GetIVal(); + m_edKeepEditorActive->Set(1); + } + } + + EditorKeepAlive::~EditorKeepAlive() + { + if (m_edKeepEditorActive) + { + m_edKeepEditorActive->Set(m_keepEditorActive); + } + } + + VersionExplorer::VersionExplorer(QWidget* parent /*= nullptr*/) + : AzQtComponents::StyledDialog(parent) + , m_ui(new Ui::VersionExplorer()) + { + m_ui->setupUi(this); + + m_ui->tableWidget->horizontalHeader()->setVisible(false); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); + m_ui->tableWidget->setColumnWidth(3, 22); + + m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); + + connect(m_ui->scanButton, &QPushButton::pressed, this, &VersionExplorer::OnScan); + connect(m_ui->closeButton, &QPushButton::pressed, this, &VersionExplorer::OnClose); + connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &VersionExplorer::OnUpgradeAll); + + m_ui->progressBar->setValue(0); + m_ui->progressBar->setVisible(false); + + m_keepEditorAlive = AZStd::make_unique(); + m_inspectingAsset = m_assetsToInspect.end(); + + } + + VersionExplorer::~VersionExplorer() + { + AZ::SystemTickBus::Handler::BusDisconnect(); + + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + + } + + void VersionExplorer::Log(const char* format, ...) + { + if (m_ui->verbose->isChecked()) + { + char sBuffer[2048]; + va_list ArgList; + va_start(ArgList, format); + azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); + sBuffer[sizeof(sBuffer) - 1] = '\0'; + va_end(ArgList); + + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); + } + } + + void VersionExplorer::OnClose() + { + reject(); + } + + bool VersionExplorer::IsUpgrading() const + { + return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; + } + + void VersionExplorer::OnSystemTick() + { + switch (m_state) + { + case ProcessState::Scan: + + if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) + { + m_inProgress = true; + AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; + m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); + m_currentAsset.BlockUntilLoadComplete(); + if (m_currentAsset.IsReady()) + { + // The asset is ready, grab its info + m_inProgress = true; + InspectAsset(m_currentAsset, assetToUpgrade); + } + else + { + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem + ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + ++m_currentAssetRowIndex; + + Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); + ++m_failedAssets; + ScanComplete(m_currentAsset); + } + } + break; + + case ProcessState::Upgrade: + { + AZStd::lock_guard lock(m_mutex); + if (m_upgradeComplete) + { + ++m_upgradeAssetIndex; + m_inProgress = false; + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + + if (m_scriptCanvasEntity) + { + m_scriptCanvasEntity->Deactivate(); + m_scriptCanvasEntity = nullptr; + } + + GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); + + if (!m_isUpgradingSingleGraph) + { + if (m_inProgressAsset != m_assetsToUpgrade.end()) + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + } + + if (m_inProgressAsset == m_assetsToUpgrade.end()) + { + FinalizeUpgrade(); + } + } + else + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + m_inProgress = false; + m_state = ProcessState::Inactive; + m_settingsCache.reset(); + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + m_isUpgradingSingleGraph = false; + + if (m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(false); + } + + m_upgradeComplete = false; + } + + if (!IsUpgrading() && m_state == ProcessState::Upgrade) + { + AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); + // Make the backup + if (errorMessage.empty()) + { + Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); + QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); + spinner->SetIsBusy(true); + } + } + + // Upgrade the graph + UpgradeGraph(*m_inProgressAsset); + } + else + { + Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); + GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); + } + + } + break; + } + default: + break; + } + + FlushLogs(); + + AZ::Data::AssetManager::Instance().DispatchEvents(); + AZ::SystemTickBus::ExecuteQueuedEvents(); + } + + // Backup + + void VersionExplorer::OnUpgradeAll() + { + m_state = ProcessState::Upgrade; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + AZ::Interface::Get()->SetIsUpgrading(true); + AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); + m_inProgressAsset = m_assetsToUpgrade.begin(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + AZ::SystemTickBus::Handler::BusConnect(); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + m_keepEditorAlive = AZStd::make_unique(); + } + + AZStd::string VersionExplorer::BackupGraph(const AZ::Data::Asset& asset) + { + if (!m_ui->makeBackupCheckbox->isChecked()) + { + // considered a success + return ""; + } + + QDateTime theTime = QDateTime::currentDateTime(); + QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); + + AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); + char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); + backupPath = backupPathCStr; + + if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) + { + if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); + return "Failed to create backup folder"; + } + } + + AZStd::string devRoot = "@devroot@"; + AZStd::string devAssets = "@devassets@"; + + char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); + + char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); + + AZStd::string relativePath = devAssetsCStr; + AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AZStd::string sourceFilePath; + + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound{}; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); + if (sourceInfoFound) + { + AZStd::string assetPath; + AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); + + sourceFilePath = assetPath; + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); + return "Failed to find source file"; + } + + devRoot = devRootCStr; + AzFramework::StringFunc::Path::Normalize(devRoot); + + relativePath = sourceFilePath; + AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AzFramework::StringFunc::Path::Normalize(relativePath); + AzFramework::StringFunc::Path::Normalize(backupPath); + + AZStd::string targetFilePath = backupPath; + targetFilePath += relativePath; + + if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return "Failed to copy source file to backup location"; + } + + Log("VersionExplorer::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return ""; + } + + void VersionExplorer::UpgradeGraph(const AZ::Data::Asset& asset) + { + m_inProgress = true; + m_upgradeComplete = false; + Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); + m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); + m_scriptCanvasEntity = nullptr; + + UpgradeNotifications::Bus::Handler::BusConnect(); + + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "VersionExplorer::UpgradeGraph The Script Canvas asset must have a valid entity"); + if (!scriptCanvasEntity) + { + return; + } + + AZ::Entity* queryEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); + if (queryEntity) + { + if (queryEntity->GetState() == AZ::Entity::State::Active) + { + queryEntity->Deactivate(); + } + + scriptCanvasEntity = queryEntity; + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) + { + scriptCanvasEntity->Init(); + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) + { + scriptCanvasEntity->Activate(); + } + + AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + if (graphComponent) + { + m_scriptCanvasEntity = scriptCanvasEntity; + + graphComponent->UpgradeGraph + ( asset + , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_ui->verbose->isChecked()); + } + } + + AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); + } + + void VersionExplorer::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + if (!fullPathFound) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); + } + + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + this->OnSourceFileReleased(asset); + }); + streamer->QueueRequest(flushRequest); + } + + void VersionExplorer::OnSourceFileReleased(AZ::Data::Asset asset) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + m_tmpFileName.clear(); + AZStd::string tmpFileName; + // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. + // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. + if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); + return; + } + + bool tempSavedSucceeded = false; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + if (fileStream.IsOpen()) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasEditor::ScriptCanvasAssetHandler handler; + tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); + } + + fileStream.Close(); + } + + // attempt to remove temporary file no matter what + m_tmpFileName = tmpFileName; + if (!tempSavedSucceeded) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); + return; + } + + using SCCommandBus = AzToolsFramework::SourceControlCommandBus; + SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, + [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + { + constexpr const size_t k_maxAttemps = 10; + + if (!info.IsReadOnly()) + { + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + if (m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + int result = QMessageBox::No; + if (!m_overwriteAll) + { + QMessageBox mb(QMessageBox::Warning, + QObject::tr("Failed to Save Upgraded File"), + QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), + QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); + + result = mb.exec(); + if (result == QMessageBox::YesToAll) + { + m_overwriteAll = true; + } + } + + if (result == QMessageBox::Yes || m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + } + } + }); + } + + void VersionExplorer::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target + , size_t remainingAttempts) + { + VersionExplorerCpp::FileEventHandler fileEventHandler; + + if (remainingAttempts == 0) + { + // all attempts failed, give up + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); + GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); + } + else if (remainingAttempts == 2) + { + // before the final attempt, flush all caches + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); + streamer->SetRequestCompleteCallback(flushRequest + , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction( + [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + else + { + // the actual move attempt + auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); + if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) + { + m_tmpFileName.clear(); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + // Bump the slice asset up in the asset processor's queue. + AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); + AZ::SystemTickBus::QueueFunction([this, asset]() + { + GraphUpgradeComplete(asset, OperationResult::Success, ""); + }); + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + } + } + + void VersionExplorer::GraphUpgradeComplete + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + AZStd::lock_guard lock(m_mutex); + m_upgradeComplete = true; + m_upgradeResult = result; + m_upgradeMessage = message; + m_upgradeAsset = asset; + + if (!m_tmpFileName.empty()) + { + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); + + if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) + { + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); + } + } + + if (m_upgradeResult == OperationResult::Failure) + { + AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); + } + + m_tmpFileName.clear(); + } + + void VersionExplorer::GraphUpgradeCompleteUIUpdate + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + QString text = asset.GetHint().c_str(); + QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); + + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); + QString assetName = asset.GetHint().c_str(); + + if (label->text().compare(assetName) == 0) + { + m_ui->tableWidget->removeCellWidget(row, ColumnAction); + m_ui->tableWidget->removeCellWidget(row, ColumnStatus); + + QToolButton* doneButton = new QToolButton(this); + doneButton->setToolTip("Upgrade complete"); + if (result == OperationResult::Success) + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); + } + else + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); + doneButton->setToolTip(message.data()); + } + + m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); + } + } + } + } + + void VersionExplorer::FinalizeUpgrade() + { + Log("FinalizeUpgrade!"); + m_inProgress = false; + m_assetsToUpgrade.clear(); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(true); + m_keepEditorAlive.reset(); + m_ui->progressBar->setVisible(false); + + // Manual correction + size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); + if (assetsThatNeedManualInspection > 0) + { + m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); + } + else + { + m_ui->spinner->SetText("Upgrade complete."); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Interface::Get()->SetIsUpgrading(false); + m_settingsCache.reset(); + } + + // Scanning + + void VersionExplorer::OnScan() + { + m_assetsToUpgrade.clear(); + m_assetsToInspect.clear(); + m_ui->tableWidget->setRowCount(0); + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); + m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); + DoScan(); + } + + void VersionExplorer::DoScan() + { + m_state = ProcessState::Scan; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + + AZ::SystemTickBus::Handler::BusConnect(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + if (!m_assetsToInspect.empty()) + { + m_discoveredAssets = m_assetsToInspect.size(); + m_failedAssets = 0; + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + m_ui->progressFrame->setVisible(true); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); + m_ui->progressBar->setValue(0); + + m_ui->spinner->SetIsBusy(true); + m_ui->spinner->SetBusyIconSize(32); + + m_ui->scanButton->setEnabled(false); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(false); + + m_inspectingAsset = m_assetsToInspect.begin(); + m_keepEditorAlive = AZStd::make_unique(); + } + } + + void VersionExplorer::BackupComplete() + { + m_currentAssetRowIndex = 0; + m_ui->progressBar->setValue(0); + DoScan(); + } + + void VersionExplorer::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) + { + Log("InspectAsset: %s", asset.GetHint().c_str()); + AZ::Entity* scriptCanvasEntity = nullptr; + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + if (!scriptCanvasAsset) + { + Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + return; + } + + scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); + } + + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); + bool forceUpgrade = m_ui->forceUpgrade->isChecked(); + ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); + + + if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) + { + ScanComplete(asset); + Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); + return; + } + + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + + if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) + { + m_assetsToUpgrade.push_back(asset); + + AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); + spinner->SetBusyIconSize(16); + + QPushButton* rowGoToButton = new QPushButton(this); + rowGoToButton->setText("Upgrade"); + rowGoToButton->setEnabled(false); + + connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { + + AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { + // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda + UpgradeSingle(rowGoToButton, spinner, assetInfo); + }); + + AZ::SystemTickBus::ExecuteQueuedEvents(); + + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); + } + + char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; + AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); + AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); + AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); + AZ::StringFunc::Path::Normalize(path); + + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; + QByteArray assetNameUtf8 = asset.GetHint().c_str(); + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); + + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + + QToolButton* browseButton = new QToolButton(this); + browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); + browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); + + QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); + connect(browseButton, &QPushButton::clicked, [absolutePath] { + AzQtComponents::ShowFileOnDesktop(absolutePath); + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); + ScanComplete(asset); + ++m_inspectedAssets; + ++m_currentAssetRowIndex; + } + + void VersionExplorer::UpgradeSingle + ( QPushButton* rowGoToButton + , AzQtComponents::StyledBusyLabel* spinner + , AZ::Data::AssetInfo assetInfo) + { + AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset + ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + + if (asset) + { + asset.BlockUntilLoadComplete(); + + if (asset.IsReady()) + { + AZ::Interface::Get()->SetIsUpgrading(true); + m_isUpgradingSingleGraph = true; + m_logs.clear(); + m_ui->textEdit->clear(); + spinner->SetIsBusy(true); + rowGoToButton->setEnabled(false); + + m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() + , [asset](const UpgradeAssets::value_type& assetToUpgrade) + { + return assetToUpgrade.GetId() == asset.GetId(); + }); + + m_state = ProcessState::Upgrade; + AZ::SystemTickBus::Handler::BusConnect(); + } + } + } + + void VersionExplorer::ScanComplete(const AZ::Data::Asset& asset) + { + Log("ScanComplete: %s", asset.GetHint().c_str()); + m_inProgress = false; + m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); + m_ui->scanButton->setEnabled(true); + + m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); + FlushLogs(); + + if (m_inspectingAsset == m_assetsToInspect.end()) + { + AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + } + } + + void VersionExplorer::FinalizeScan() + { + Log("FinalizeScan()"); + + m_ui->spinner->SetIsBusy(false); + m_ui->onlyShowOutdated->setEnabled(true); + + // Enable all the Upgrade buttons + for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) + { + QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); + if (button) + { + button->setEnabled(true); + } + } + + QString spinnerText = QStringLiteral("Scan Complete"); + if (m_assetsToUpgrade.empty()) + { + spinnerText.append(" - No graphs require upgrade!"); + } + else + { + spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" + , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); + } + + + m_ui->spinner->SetText(spinnerText); + m_ui->progressBar->setVisible(false); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + + m_keepEditorAlive.reset(); + m_settingsCache.reset(); + m_state = ProcessState::Inactive; + } + + void VersionExplorer::FlushLogs() + { + if (m_logs.empty()) + { + return; + } + + const QTextCursor oldCursor = m_ui->textEdit->textCursor(); + QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); + + m_ui->textEdit->moveCursor(QTextCursor::End); + QTextCursor textCursor = m_ui->textEdit->textCursor(); + + while (!m_logs.empty()) + { + auto line = "\n" + m_logs.front(); + + m_logs.pop_front(); + + textCursor.insertText(line.c_str()); + } + + scrollBar->setValue(scrollBar->maximum()); + m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); + + } + + bool VersionExplorer::CaptureLogFromTraceBus(const char* window, const char* message) + { + if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) + { + return true; + } + + AZStd::string msg = message; + if (msg.ends_with("\n")) + { + msg = msg.substr(0, msg.size() - 1); + } + + m_logs.push_back(msg); + return m_ui->updateReportingOnly->isChecked(); + } + + bool VersionExplorer::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Error): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool VersionExplorer::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Warning): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool VersionExplorer::OnException(const char* message) + { + AZStd::string msg = AZStd::string::format("(Exception): %s", message); + return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); + } + + bool VersionExplorer::OnPrintf(const char* window, const char* message) + { + return CaptureLogFromTraceBus(window, message); + } + + void VersionExplorer::closeEvent(QCloseEvent* event) + { + m_keepEditorAlive.reset(); + + AzQtComponents::StyledDialog::closeEvent(event); + } + +#include + +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h new file mode 100644 index 0000000000..acb28a7dba --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h @@ -0,0 +1,180 @@ +/* + * 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 + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") +#include +AZ_POP_DISABLE_WARNING + +#include +#include +#include + +#include +#include + +#include +#include +#include +#endif + +class QPushButton; + +namespace Ui +{ + class VersionExplorer; +} + +namespace AzQtComponents +{ + class StyledBusyLabel; +} + +namespace ScriptCanvasEditor +{ + //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow + //! the upgrade tool to work even if the editor is not in the foreground + class EditorKeepAlive + { + public: + EditorKeepAlive(); + ~EditorKeepAlive(); + + private: + int m_keepEditorActive; + ICVar* m_edKeepEditorActive; + }; + + //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog + class VersionExplorer + : public AzQtComponents::StyledDialog + , private AZ::SystemTickBus::Handler + , private UpgradeNotifications::Bus::Handler + , private AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + AZ_CLASS_ALLOCATOR(VersionExplorer, AZ::SystemAllocator, 0); + + explicit VersionExplorer(QWidget* parent = nullptr); + ~VersionExplorer(); + + private: + + static constexpr int ColumnAsset = 0; + static constexpr int ColumnAction = 1; + static constexpr int ColumnBrowse = 2; + static constexpr int ColumnStatus = 3; + + void OnScan(); + void OnClose(); + + enum class ProcessState + { + Inactive, + Backup, + Scan, + Upgrade, + }; + ProcessState m_state = ProcessState::Inactive; + + void DoScan(); + void ScanComplete(const AZ::Data::Asset&); + + void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); + + void OnUpgradeAll(); + + // SystemTickBus::Handler + void OnSystemTick() override; + // + + // AZ::Debug::TranceMessageBus::Handler + bool OnException(const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + // + + bool CaptureLogFromTraceBus(const char* window, const char* message); + + enum class OperationResult + { + Success, + Failure, + }; + + void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); + + bool IsUpgrading() const; + + bool m_inProgress = false; + // scan fields + size_t m_currentAssetRowIndex = 0; + size_t m_inspectedAssets = 0; + size_t m_failedAssets = 0; + size_t m_discoveredAssets = 0; + + IUpgradeRequests::AssetList m_assetsToInspect; + IUpgradeRequests::AssetList::iterator m_inspectingAsset; + using UpgradeAssets = AZStd::vector>; + UpgradeAssets m_assetsToUpgrade; + UpgradeAssets::iterator m_inProgressAsset; + + AZ::Data::Asset m_currentAsset; + + AZStd::unique_ptr m_ui; + + AZStd::unique_ptr m_settingsCache; + + // upgrade fields + AZStd::recursive_mutex m_mutex; + bool m_upgradeComplete = false; + AZ::Data::Asset m_upgradeAsset; + int m_upgradeAssetIndex = 0; + OperationResult m_upgradeResult; + AZStd::string m_upgradeMessage; + AZStd::string m_tmpFileName; + + AZStd::unique_ptr m_keepEditorAlive; + + AZStd::deque m_logs; + + AZ::Entity* m_scriptCanvasEntity = nullptr; + + bool m_isUpgradingSingleGraph = false; + + void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); + + void FlushLogs(); + + void FinalizeUpgrade(); + void FinalizeScan(); + + void BackupComplete(); + AZStd::string BackupGraph(const AZ::Data::Asset&); + void UpgradeGraph(const AZ::Data::Asset&); + + void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); + void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; + + void OnSourceFileReleased(AZ::Data::Asset asset); + + void closeEvent(QCloseEvent* event) override; + + bool m_overwriteAll = false; + void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); + + void Log(const char* format, ...); + }; +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp new file mode 100644 index 0000000000..b96a5c6d0c --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -0,0 +1,1023 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace VersionExplorerCpp +{ + class FileEventHandler + : public AZ::IO::FileIOEventBus::Handler + { + public: + int m_errorCode = 0; + AZStd::string m_fileName; + + FileEventHandler() + { + BusConnect(); + } + + ~FileEventHandler() + { + BusDisconnect(); + } + + void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override + { + m_errorCode = errorCode; + + if (fileName) + { + m_fileName = fileName; + } + } + }; +} + +namespace ScriptCanvasEditor +{ + EditorKeepAlive::EditorKeepAlive() + { + ISystem* system = nullptr; + CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); + + m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); + + if (m_edKeepEditorActive) + { + m_keepEditorActive = m_edKeepEditorActive->GetIVal(); + m_edKeepEditorActive->Set(1); + } + } + + EditorKeepAlive::~EditorKeepAlive() + { + if (m_edKeepEditorActive) + { + m_edKeepEditorActive->Set(m_keepEditorActive); + } + } + + Modifier::Modifier(QWidget* parent /*= nullptr*/) + : AzQtComponents::StyledDialog(parent) + , m_ui(new Ui::Modifier()) + { + m_ui->setupUi(this); + + m_ui->tableWidget->horizontalHeader()->setVisible(false); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); + m_ui->tableWidget->setColumnWidth(3, 22); + + m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); + + connect(m_ui->scanButton, &QPushButton::pressed, this, &Modifier::OnScan); + connect(m_ui->closeButton, &QPushButton::pressed, this, &Modifier::OnClose); + connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &Modifier::OnUpgradeAll); + + m_ui->progressBar->setValue(0); + m_ui->progressBar->setVisible(false); + + m_keepEditorAlive = AZStd::make_unique(); + m_inspectingAsset = m_assetsToInspect.end(); + + } + + Modifier::~Modifier() + { + AZ::SystemTickBus::Handler::BusDisconnect(); + + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + + } + + void Modifier::Log(const char* format, ...) + { + if (m_ui->verbose->isChecked()) + { + char sBuffer[2048]; + va_list ArgList; + va_start(ArgList, format); + azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); + sBuffer[sizeof(sBuffer) - 1] = '\0'; + va_end(ArgList); + + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); + } + } + + void Modifier::OnClose() + { + reject(); + } + + bool Modifier::IsUpgrading() const + { + return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; + } + + void Modifier::OnSystemTick() + { + switch (m_state) + { + case ProcessState::Scan: + + if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) + { + m_inProgress = true; + AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; + m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); + m_currentAsset.BlockUntilLoadComplete(); + if (m_currentAsset.IsReady()) + { + // The asset is ready, grab its info + m_inProgress = true; + InspectAsset(m_currentAsset, assetToUpgrade); + } + else + { + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem + ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + ++m_currentAssetRowIndex; + + Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); + ++m_failedAssets; + ScanComplete(m_currentAsset); + } + } + break; + + case ProcessState::Upgrade: + { + AZStd::lock_guard lock(m_mutex); + if (m_upgradeComplete) + { + ++m_upgradeAssetIndex; + m_inProgress = false; + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + + if (m_scriptCanvasEntity) + { + m_scriptCanvasEntity->Deactivate(); + m_scriptCanvasEntity = nullptr; + } + + GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); + + if (!m_isUpgradingSingleGraph) + { + if (m_inProgressAsset != m_assetsToUpgrade.end()) + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + } + + if (m_inProgressAsset == m_assetsToUpgrade.end()) + { + FinalizeUpgrade(); + } + } + else + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + m_inProgress = false; + m_state = ProcessState::Inactive; + m_settingsCache.reset(); + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + m_isUpgradingSingleGraph = false; + + if (m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(false); + } + + m_upgradeComplete = false; + } + + if (!IsUpgrading() && m_state == ProcessState::Upgrade) + { + AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); + // Make the backup + if (errorMessage.empty()) + { + Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); + QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); + spinner->SetIsBusy(true); + } + } + + // Upgrade the graph + UpgradeGraph(*m_inProgressAsset); + } + else + { + Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); + GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); + } + + } + break; + } + default: + break; + } + + FlushLogs(); + + AZ::Data::AssetManager::Instance().DispatchEvents(); + AZ::SystemTickBus::ExecuteQueuedEvents(); + } + + // Backup + + void Modifier::OnUpgradeAll() + { + m_state = ProcessState::Upgrade; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + AZ::Interface::Get()->SetIsUpgrading(true); + AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); + m_inProgressAsset = m_assetsToUpgrade.begin(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + AZ::SystemTickBus::Handler::BusConnect(); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + m_keepEditorAlive = AZStd::make_unique(); + } + + AZStd::string Modifier::BackupGraph(const AZ::Data::Asset& asset) + { + if (!m_ui->makeBackupCheckbox->isChecked()) + { + // considered a success + return ""; + } + + QDateTime theTime = QDateTime::currentDateTime(); + QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); + + AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); + char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); + backupPath = backupPathCStr; + + if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) + { + if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); + return "Failed to create backup folder"; + } + } + + AZStd::string devRoot = "@devroot@"; + AZStd::string devAssets = "@devassets@"; + + char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); + + char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); + + AZStd::string relativePath = devAssetsCStr; + AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AZStd::string sourceFilePath; + + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound{}; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); + if (sourceInfoFound) + { + AZStd::string assetPath; + AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); + + sourceFilePath = assetPath; + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Modifier::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); + return "Failed to find source file"; + } + + devRoot = devRootCStr; + AzFramework::StringFunc::Path::Normalize(devRoot); + + relativePath = sourceFilePath; + AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AzFramework::StringFunc::Path::Normalize(relativePath); + AzFramework::StringFunc::Path::Normalize(backupPath); + + AZStd::string targetFilePath = backupPath; + targetFilePath += relativePath; + + if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Modifier::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return "Failed to copy source file to backup location"; + } + + Log("Modifier::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return ""; + } + + void Modifier::UpgradeGraph(const AZ::Data::Asset& asset) + { + m_inProgress = true; + m_upgradeComplete = false; + Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); + m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); + m_scriptCanvasEntity = nullptr; + + UpgradeNotifications::Bus::Handler::BusConnect(); + + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "Modifier::UpgradeGraph The Script Canvas asset must have a valid entity"); + if (!scriptCanvasEntity) + { + return; + } + + AZ::Entity* queryEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); + if (queryEntity) + { + if (queryEntity->GetState() == AZ::Entity::State::Active) + { + queryEntity->Deactivate(); + } + + scriptCanvasEntity = queryEntity; + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) + { + scriptCanvasEntity->Init(); + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) + { + scriptCanvasEntity->Activate(); + } + + AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + if (graphComponent) + { + m_scriptCanvasEntity = scriptCanvasEntity; + + graphComponent->UpgradeGraph + ( asset + , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_ui->verbose->isChecked()); + } + } + + AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); + } + + void Modifier::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + if (!fullPathFound) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); + } + + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + this->OnSourceFileReleased(asset); + }); + streamer->QueueRequest(flushRequest); + } + + void Modifier::OnSourceFileReleased(AZ::Data::Asset asset) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + m_tmpFileName.clear(); + AZStd::string tmpFileName; + // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. + // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. + if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); + return; + } + + bool tempSavedSucceeded = false; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + if (fileStream.IsOpen()) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasEditor::ScriptCanvasAssetHandler handler; + tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); + } + + fileStream.Close(); + } + + // attempt to remove temporary file no matter what + m_tmpFileName = tmpFileName; + if (!tempSavedSucceeded) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); + return; + } + + using SCCommandBus = AzToolsFramework::SourceControlCommandBus; + SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, + [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + { + constexpr const size_t k_maxAttemps = 10; + + if (!info.IsReadOnly()) + { + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + if (m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + int result = QMessageBox::No; + if (!m_overwriteAll) + { + QMessageBox mb(QMessageBox::Warning, + QObject::tr("Failed to Save Upgraded File"), + QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), + QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); + + result = mb.exec(); + if (result == QMessageBox::YesToAll) + { + m_overwriteAll = true; + } + } + + if (result == QMessageBox::Yes || m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + } + } + }); + } + + void Modifier::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target + , size_t remainingAttempts) + { + VersionExplorerCpp::FileEventHandler fileEventHandler; + + if (remainingAttempts == 0) + { + // all attempts failed, give up + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); + GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); + } + else if (remainingAttempts == 2) + { + // before the final attempt, flush all caches + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); + streamer->SetRequestCompleteCallback(flushRequest + , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction( + [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + else + { + // the actual move attempt + auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); + if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) + { + m_tmpFileName.clear(); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + // Bump the slice asset up in the asset processor's queue. + AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); + AZ::SystemTickBus::QueueFunction([this, asset]() + { + GraphUpgradeComplete(asset, OperationResult::Success, ""); + }); + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + } + } + + void Modifier::GraphUpgradeComplete + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + AZStd::lock_guard lock(m_mutex); + m_upgradeComplete = true; + m_upgradeResult = result; + m_upgradeMessage = message; + m_upgradeAsset = asset; + + if (!m_tmpFileName.empty()) + { + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); + + if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) + { + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); + } + } + + if (m_upgradeResult == OperationResult::Failure) + { + AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); + } + + m_tmpFileName.clear(); + } + + void Modifier::GraphUpgradeCompleteUIUpdate + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + QString text = asset.GetHint().c_str(); + QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); + + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); + QString assetName = asset.GetHint().c_str(); + + if (label->text().compare(assetName) == 0) + { + m_ui->tableWidget->removeCellWidget(row, ColumnAction); + m_ui->tableWidget->removeCellWidget(row, ColumnStatus); + + QToolButton* doneButton = new QToolButton(this); + doneButton->setToolTip("Upgrade complete"); + if (result == OperationResult::Success) + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); + } + else + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); + doneButton->setToolTip(message.data()); + } + + m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); + } + } + } + } + + void Modifier::FinalizeUpgrade() + { + Log("FinalizeUpgrade!"); + m_inProgress = false; + m_assetsToUpgrade.clear(); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(true); + m_keepEditorAlive.reset(); + m_ui->progressBar->setVisible(false); + + // Manual correction + size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); + if (assetsThatNeedManualInspection > 0) + { + m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); + } + else + { + m_ui->spinner->SetText("Upgrade complete."); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Interface::Get()->SetIsUpgrading(false); + m_settingsCache.reset(); + } + + // Scanning + + void Modifier::OnScan() + { + m_assetsToUpgrade.clear(); + m_assetsToInspect.clear(); + m_ui->tableWidget->setRowCount(0); + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); + m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); + DoScan(); + } + + void Modifier::DoScan() + { + m_state = ProcessState::Scan; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + + AZ::SystemTickBus::Handler::BusConnect(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + if (!m_assetsToInspect.empty()) + { + m_discoveredAssets = m_assetsToInspect.size(); + m_failedAssets = 0; + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + m_ui->progressFrame->setVisible(true); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); + m_ui->progressBar->setValue(0); + + m_ui->spinner->SetIsBusy(true); + m_ui->spinner->SetBusyIconSize(32); + + m_ui->scanButton->setEnabled(false); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(false); + + m_inspectingAsset = m_assetsToInspect.begin(); + m_keepEditorAlive = AZStd::make_unique(); + } + } + + void Modifier::BackupComplete() + { + m_currentAssetRowIndex = 0; + m_ui->progressBar->setValue(0); + DoScan(); + } + + void Modifier::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) + { + Log("InspectAsset: %s", asset.GetHint().c_str()); + AZ::Entity* scriptCanvasEntity = nullptr; + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + if (!scriptCanvasAsset) + { + Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + return; + } + + scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); + } + + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); + bool forceUpgrade = m_ui->forceUpgrade->isChecked(); + ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); + + + if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) + { + ScanComplete(asset); + Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); + return; + } + + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + + if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) + { + m_assetsToUpgrade.push_back(asset); + + AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); + spinner->SetBusyIconSize(16); + + QPushButton* rowGoToButton = new QPushButton(this); + rowGoToButton->setText("Upgrade"); + rowGoToButton->setEnabled(false); + + connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { + + AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { + // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda + UpgradeSingle(rowGoToButton, spinner, assetInfo); + }); + + AZ::SystemTickBus::ExecuteQueuedEvents(); + + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); + } + + char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; + AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); + AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); + AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); + AZ::StringFunc::Path::Normalize(path); + + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; + QByteArray assetNameUtf8 = asset.GetHint().c_str(); + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); + + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + + QToolButton* browseButton = new QToolButton(this); + browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); + browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); + + QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); + connect(browseButton, &QPushButton::clicked, [absolutePath] { + AzQtComponents::ShowFileOnDesktop(absolutePath); + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); + ScanComplete(asset); + ++m_inspectedAssets; + ++m_currentAssetRowIndex; + } + + void Modifier::UpgradeSingle + ( QPushButton* rowGoToButton + , AzQtComponents::StyledBusyLabel* spinner + , AZ::Data::AssetInfo assetInfo) + { + AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset + ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + + if (asset) + { + asset.BlockUntilLoadComplete(); + + if (asset.IsReady()) + { + AZ::Interface::Get()->SetIsUpgrading(true); + m_isUpgradingSingleGraph = true; + m_logs.clear(); + m_ui->textEdit->clear(); + spinner->SetIsBusy(true); + rowGoToButton->setEnabled(false); + + m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() + , [asset](const UpgradeAssets::value_type& assetToUpgrade) + { + return assetToUpgrade.GetId() == asset.GetId(); + }); + + m_state = ProcessState::Upgrade; + AZ::SystemTickBus::Handler::BusConnect(); + } + } + } + + void Modifier::ScanComplete(const AZ::Data::Asset& asset) + { + Log("ScanComplete: %s", asset.GetHint().c_str()); + m_inProgress = false; + m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); + m_ui->scanButton->setEnabled(true); + + m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); + FlushLogs(); + + if (m_inspectingAsset == m_assetsToInspect.end()) + { + AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + } + } + + void Modifier::FinalizeScan() + { + Log("FinalizeScan()"); + + m_ui->spinner->SetIsBusy(false); + m_ui->onlyShowOutdated->setEnabled(true); + + // Enable all the Upgrade buttons + for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) + { + QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); + if (button) + { + button->setEnabled(true); + } + } + + QString spinnerText = QStringLiteral("Scan Complete"); + if (m_assetsToUpgrade.empty()) + { + spinnerText.append(" - No graphs require upgrade!"); + } + else + { + spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" + , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); + } + + + m_ui->spinner->SetText(spinnerText); + m_ui->progressBar->setVisible(false); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + + m_keepEditorAlive.reset(); + m_settingsCache.reset(); + m_state = ProcessState::Inactive; + } + + void Modifier::FlushLogs() + { + if (m_logs.empty()) + { + return; + } + + const QTextCursor oldCursor = m_ui->textEdit->textCursor(); + QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); + + m_ui->textEdit->moveCursor(QTextCursor::End); + QTextCursor textCursor = m_ui->textEdit->textCursor(); + + while (!m_logs.empty()) + { + auto line = "\n" + m_logs.front(); + + m_logs.pop_front(); + + textCursor.insertText(line.c_str()); + } + + scrollBar->setValue(scrollBar->maximum()); + m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); + + } + + bool Modifier::CaptureLogFromTraceBus(const char* window, const char* message) + { + if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) + { + return true; + } + + AZStd::string msg = message; + if (msg.ends_with("\n")) + { + msg = msg.substr(0, msg.size() - 1); + } + + m_logs.push_back(msg); + return m_ui->updateReportingOnly->isChecked(); + } + + bool Modifier::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Error): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool Modifier::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Warning): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool Modifier::OnException(const char* message) + { + AZStd::string msg = AZStd::string::format("(Exception): %s", message); + return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); + } + + bool Modifier::OnPrintf(const char* window, const char* message) + { + return CaptureLogFromTraceBus(window, message); + } + + void Modifier::closeEvent(QCloseEvent* event) + { + m_keepEditorAlive.reset(); + + AzQtComponents::StyledDialog::closeEvent(event); + } + +#include + +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h new file mode 100644 index 0000000000..5f379d682a --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -0,0 +1,167 @@ +/* + * 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 + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") +#include +AZ_POP_DISABLE_WARNING + +#include +#include +#include + +#include +#include + +#include +#include +#include +#endif + +class QPushButton; + +namespace Ui +{ + class Modifier; +} + +namespace AzQtComponents +{ + class StyledBusyLabel; +} + +namespace ScriptCanvasEditor +{ + //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog + class Modifier + : public AzQtComponents::StyledDialog + , private AZ::SystemTickBus::Handler + , private UpgradeNotifications::Bus::Handler + , private AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0); + + explicit Modifier(QWidget* parent = nullptr); + ~Modifier(); + + private: + + static constexpr int ColumnAsset = 0; + static constexpr int ColumnAction = 1; + static constexpr int ColumnBrowse = 2; + static constexpr int ColumnStatus = 3; + + void OnScan(); + void OnClose(); + + enum class ProcessState + { + Inactive, + Backup, + Scan, + Upgrade, + }; + ProcessState m_state = ProcessState::Inactive; + + void DoScan(); + void ScanComplete(const AZ::Data::Asset&); + + void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); + + void OnUpgradeAll(); + + // SystemTickBus::Handler + void OnSystemTick() override; + // + + // AZ::Debug::TranceMessageBus::Handler + bool OnException(const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + // + + bool CaptureLogFromTraceBus(const char* window, const char* message); + + enum class OperationResult + { + Success, + Failure, + }; + + void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); + + bool IsUpgrading() const; + + bool m_inProgress = false; + // scan fields + size_t m_currentAssetRowIndex = 0; + size_t m_inspectedAssets = 0; + size_t m_failedAssets = 0; + size_t m_discoveredAssets = 0; + + IUpgradeRequests::AssetList m_assetsToInspect; + IUpgradeRequests::AssetList::iterator m_inspectingAsset; + using UpgradeAssets = AZStd::vector>; + UpgradeAssets m_assetsToUpgrade; + UpgradeAssets::iterator m_inProgressAsset; + + AZ::Data::Asset m_currentAsset; + + AZStd::unique_ptr m_ui; + + AZStd::unique_ptr m_settingsCache; + + // upgrade fields + AZStd::recursive_mutex m_mutex; + bool m_upgradeComplete = false; + AZ::Data::Asset m_upgradeAsset; + int m_upgradeAssetIndex = 0; + OperationResult m_upgradeResult; + AZStd::string m_upgradeMessage; + AZStd::string m_tmpFileName; + + AZStd::unique_ptr m_keepEditorAlive; + + AZStd::deque m_logs; + + AZ::Entity* m_scriptCanvasEntity = nullptr; + + bool m_isUpgradingSingleGraph = false; + + void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); + + void FlushLogs(); + + void FinalizeUpgrade(); + void FinalizeScan(); + + void BackupComplete(); + AZStd::string BackupGraph(const AZ::Data::Asset&); + void UpgradeGraph(const AZ::Data::Asset&); + + void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); + void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; + + void OnSourceFileReleased(AZ::Data::Asset asset); + + void closeEvent(QCloseEvent* event) override; + + bool m_overwriteAll = false; + void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); + + void Log(const char* format, ...); + }; +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp new file mode 100644 index 0000000000..29f5f8f530 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp @@ -0,0 +1,1023 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace VersionExplorerCpp +{ + class FileEventHandler + : public AZ::IO::FileIOEventBus::Handler + { + public: + int m_errorCode = 0; + AZStd::string m_fileName; + + FileEventHandler() + { + BusConnect(); + } + + ~FileEventHandler() + { + BusDisconnect(); + } + + void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override + { + m_errorCode = errorCode; + + if (fileName) + { + m_fileName = fileName; + } + } + }; +} + +namespace ScriptCanvasEditor +{ + EditorKeepAlive::EditorKeepAlive() + { + ISystem* system = nullptr; + CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); + + m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); + + if (m_edKeepEditorActive) + { + m_keepEditorActive = m_edKeepEditorActive->GetIVal(); + m_edKeepEditorActive->Set(1); + } + } + + EditorKeepAlive::~EditorKeepAlive() + { + if (m_edKeepEditorActive) + { + m_edKeepEditorActive->Set(m_keepEditorActive); + } + } + + Scanner::Scanner(QWidget* parent /*= nullptr*/) + : AzQtComponents::StyledDialog(parent) + , m_ui(new Ui::Scanner()) + { + m_ui->setupUi(this); + + m_ui->tableWidget->horizontalHeader()->setVisible(false); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); + m_ui->tableWidget->setColumnWidth(3, 22); + + m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); + + connect(m_ui->scanButton, &QPushButton::pressed, this, &Scanner::OnScan); + connect(m_ui->closeButton, &QPushButton::pressed, this, &Scanner::OnClose); + connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &Scanner::OnUpgradeAll); + + m_ui->progressBar->setValue(0); + m_ui->progressBar->setVisible(false); + + m_keepEditorAlive = AZStd::make_unique(); + m_inspectingAsset = m_assetsToInspect.end(); + + } + + Scanner::~Scanner() + { + AZ::SystemTickBus::Handler::BusDisconnect(); + + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + + } + + void Scanner::Log(const char* format, ...) + { + if (m_ui->verbose->isChecked()) + { + char sBuffer[2048]; + va_list ArgList; + va_start(ArgList, format); + azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); + sBuffer[sizeof(sBuffer) - 1] = '\0'; + va_end(ArgList); + + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); + } + } + + void Scanner::OnClose() + { + reject(); + } + + bool Scanner::IsUpgrading() const + { + return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; + } + + void Scanner::OnSystemTick() + { + switch (m_state) + { + case ProcessState::Scan: + + if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) + { + m_inProgress = true; + AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; + m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); + m_currentAsset.BlockUntilLoadComplete(); + if (m_currentAsset.IsReady()) + { + // The asset is ready, grab its info + m_inProgress = true; + InspectAsset(m_currentAsset, assetToUpgrade); + } + else + { + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem + ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + ++m_currentAssetRowIndex; + + Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); + ++m_failedAssets; + ScanComplete(m_currentAsset); + } + } + break; + + case ProcessState::Upgrade: + { + AZStd::lock_guard lock(m_mutex); + if (m_upgradeComplete) + { + ++m_upgradeAssetIndex; + m_inProgress = false; + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + + if (m_scriptCanvasEntity) + { + m_scriptCanvasEntity->Deactivate(); + m_scriptCanvasEntity = nullptr; + } + + GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); + + if (!m_isUpgradingSingleGraph) + { + if (m_inProgressAsset != m_assetsToUpgrade.end()) + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + } + + if (m_inProgressAsset == m_assetsToUpgrade.end()) + { + FinalizeUpgrade(); + } + } + else + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + m_inProgress = false; + m_state = ProcessState::Inactive; + m_settingsCache.reset(); + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + m_isUpgradingSingleGraph = false; + + if (m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(false); + } + + m_upgradeComplete = false; + } + + if (!IsUpgrading() && m_state == ProcessState::Upgrade) + { + AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); + // Make the backup + if (errorMessage.empty()) + { + Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); + QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); + spinner->SetIsBusy(true); + } + } + + // Upgrade the graph + UpgradeGraph(*m_inProgressAsset); + } + else + { + Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); + GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); + } + + } + break; + } + default: + break; + } + + FlushLogs(); + + AZ::Data::AssetManager::Instance().DispatchEvents(); + AZ::SystemTickBus::ExecuteQueuedEvents(); + } + + // Backup + + void Scanner::OnUpgradeAll() + { + m_state = ProcessState::Upgrade; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + AZ::Interface::Get()->SetIsUpgrading(true); + AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); + m_inProgressAsset = m_assetsToUpgrade.begin(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + AZ::SystemTickBus::Handler::BusConnect(); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + m_keepEditorAlive = AZStd::make_unique(); + } + + AZStd::string Scanner::BackupGraph(const AZ::Data::Asset& asset) + { + if (!m_ui->makeBackupCheckbox->isChecked()) + { + // considered a success + return ""; + } + + QDateTime theTime = QDateTime::currentDateTime(); + QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); + + AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); + char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); + backupPath = backupPathCStr; + + if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) + { + if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); + return "Failed to create backup folder"; + } + } + + AZStd::string devRoot = "@devroot@"; + AZStd::string devAssets = "@devassets@"; + + char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); + + char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); + + AZStd::string relativePath = devAssetsCStr; + AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AZStd::string sourceFilePath; + + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound{}; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); + if (sourceInfoFound) + { + AZStd::string assetPath; + AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); + + sourceFilePath = assetPath; + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Scanner::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); + return "Failed to find source file"; + } + + devRoot = devRootCStr; + AzFramework::StringFunc::Path::Normalize(devRoot); + + relativePath = sourceFilePath; + AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AzFramework::StringFunc::Path::Normalize(relativePath); + AzFramework::StringFunc::Path::Normalize(backupPath); + + AZStd::string targetFilePath = backupPath; + targetFilePath += relativePath; + + if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Scanner::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return "Failed to copy source file to backup location"; + } + + Log("Scanner::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return ""; + } + + void Scanner::UpgradeGraph(const AZ::Data::Asset& asset) + { + m_inProgress = true; + m_upgradeComplete = false; + Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); + m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); + m_scriptCanvasEntity = nullptr; + + UpgradeNotifications::Bus::Handler::BusConnect(); + + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "Scanner::UpgradeGraph The Script Canvas asset must have a valid entity"); + if (!scriptCanvasEntity) + { + return; + } + + AZ::Entity* queryEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); + if (queryEntity) + { + if (queryEntity->GetState() == AZ::Entity::State::Active) + { + queryEntity->Deactivate(); + } + + scriptCanvasEntity = queryEntity; + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) + { + scriptCanvasEntity->Init(); + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) + { + scriptCanvasEntity->Activate(); + } + + AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + if (graphComponent) + { + m_scriptCanvasEntity = scriptCanvasEntity; + + graphComponent->UpgradeGraph + ( asset + , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_ui->verbose->isChecked()); + } + } + + AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); + } + + void Scanner::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + if (!fullPathFound) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); + } + + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + this->OnSourceFileReleased(asset); + }); + streamer->QueueRequest(flushRequest); + } + + void Scanner::OnSourceFileReleased(AZ::Data::Asset asset) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + m_tmpFileName.clear(); + AZStd::string tmpFileName; + // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. + // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. + if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); + return; + } + + bool tempSavedSucceeded = false; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + if (fileStream.IsOpen()) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasEditor::ScriptCanvasAssetHandler handler; + tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); + } + + fileStream.Close(); + } + + // attempt to remove temporary file no matter what + m_tmpFileName = tmpFileName; + if (!tempSavedSucceeded) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); + return; + } + + using SCCommandBus = AzToolsFramework::SourceControlCommandBus; + SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, + [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + { + constexpr const size_t k_maxAttemps = 10; + + if (!info.IsReadOnly()) + { + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + if (m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + int result = QMessageBox::No; + if (!m_overwriteAll) + { + QMessageBox mb(QMessageBox::Warning, + QObject::tr("Failed to Save Upgraded File"), + QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), + QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); + + result = mb.exec(); + if (result == QMessageBox::YesToAll) + { + m_overwriteAll = true; + } + } + + if (result == QMessageBox::Yes || m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + } + } + }); + } + + void Scanner::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target + , size_t remainingAttempts) + { + VersionExplorerCpp::FileEventHandler fileEventHandler; + + if (remainingAttempts == 0) + { + // all attempts failed, give up + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); + GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); + } + else if (remainingAttempts == 2) + { + // before the final attempt, flush all caches + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); + streamer->SetRequestCompleteCallback(flushRequest + , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction( + [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + else + { + // the actual move attempt + auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); + if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) + { + m_tmpFileName.clear(); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + // Bump the slice asset up in the asset processor's queue. + AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); + AZ::SystemTickBus::QueueFunction([this, asset]() + { + GraphUpgradeComplete(asset, OperationResult::Success, ""); + }); + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + } + } + + void Scanner::GraphUpgradeComplete + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + AZStd::lock_guard lock(m_mutex); + m_upgradeComplete = true; + m_upgradeResult = result; + m_upgradeMessage = message; + m_upgradeAsset = asset; + + if (!m_tmpFileName.empty()) + { + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); + + if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) + { + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); + } + } + + if (m_upgradeResult == OperationResult::Failure) + { + AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); + } + + m_tmpFileName.clear(); + } + + void Scanner::GraphUpgradeCompleteUIUpdate + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + QString text = asset.GetHint().c_str(); + QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); + + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); + QString assetName = asset.GetHint().c_str(); + + if (label->text().compare(assetName) == 0) + { + m_ui->tableWidget->removeCellWidget(row, ColumnAction); + m_ui->tableWidget->removeCellWidget(row, ColumnStatus); + + QToolButton* doneButton = new QToolButton(this); + doneButton->setToolTip("Upgrade complete"); + if (result == OperationResult::Success) + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); + } + else + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); + doneButton->setToolTip(message.data()); + } + + m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); + } + } + } + } + + void Scanner::FinalizeUpgrade() + { + Log("FinalizeUpgrade!"); + m_inProgress = false; + m_assetsToUpgrade.clear(); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(true); + m_keepEditorAlive.reset(); + m_ui->progressBar->setVisible(false); + + // Manual correction + size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); + if (assetsThatNeedManualInspection > 0) + { + m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); + } + else + { + m_ui->spinner->SetText("Upgrade complete."); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Interface::Get()->SetIsUpgrading(false); + m_settingsCache.reset(); + } + + // Scanning + + void Scanner::OnScan() + { + m_assetsToUpgrade.clear(); + m_assetsToInspect.clear(); + m_ui->tableWidget->setRowCount(0); + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); + m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); + DoScan(); + } + + void Scanner::DoScan() + { + m_state = ProcessState::Scan; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + + AZ::SystemTickBus::Handler::BusConnect(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + if (!m_assetsToInspect.empty()) + { + m_discoveredAssets = m_assetsToInspect.size(); + m_failedAssets = 0; + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + m_ui->progressFrame->setVisible(true); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); + m_ui->progressBar->setValue(0); + + m_ui->spinner->SetIsBusy(true); + m_ui->spinner->SetBusyIconSize(32); + + m_ui->scanButton->setEnabled(false); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(false); + + m_inspectingAsset = m_assetsToInspect.begin(); + m_keepEditorAlive = AZStd::make_unique(); + } + } + + void Scanner::BackupComplete() + { + m_currentAssetRowIndex = 0; + m_ui->progressBar->setValue(0); + DoScan(); + } + + void Scanner::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) + { + Log("InspectAsset: %s", asset.GetHint().c_str()); + AZ::Entity* scriptCanvasEntity = nullptr; + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + if (!scriptCanvasAsset) + { + Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + return; + } + + scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); + } + + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); + bool forceUpgrade = m_ui->forceUpgrade->isChecked(); + ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); + + + if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) + { + ScanComplete(asset); + Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); + return; + } + + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + + if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) + { + m_assetsToUpgrade.push_back(asset); + + AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); + spinner->SetBusyIconSize(16); + + QPushButton* rowGoToButton = new QPushButton(this); + rowGoToButton->setText("Upgrade"); + rowGoToButton->setEnabled(false); + + connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { + + AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { + // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda + UpgradeSingle(rowGoToButton, spinner, assetInfo); + }); + + AZ::SystemTickBus::ExecuteQueuedEvents(); + + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); + } + + char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; + AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); + AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); + AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); + AZ::StringFunc::Path::Normalize(path); + + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; + QByteArray assetNameUtf8 = asset.GetHint().c_str(); + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); + + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + + QToolButton* browseButton = new QToolButton(this); + browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); + browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); + + QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); + connect(browseButton, &QPushButton::clicked, [absolutePath] { + AzQtComponents::ShowFileOnDesktop(absolutePath); + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); + ScanComplete(asset); + ++m_inspectedAssets; + ++m_currentAssetRowIndex; + } + + void Scanner::UpgradeSingle + ( QPushButton* rowGoToButton + , AzQtComponents::StyledBusyLabel* spinner + , AZ::Data::AssetInfo assetInfo) + { + AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset + ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + + if (asset) + { + asset.BlockUntilLoadComplete(); + + if (asset.IsReady()) + { + AZ::Interface::Get()->SetIsUpgrading(true); + m_isUpgradingSingleGraph = true; + m_logs.clear(); + m_ui->textEdit->clear(); + spinner->SetIsBusy(true); + rowGoToButton->setEnabled(false); + + m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() + , [asset](const UpgradeAssets::value_type& assetToUpgrade) + { + return assetToUpgrade.GetId() == asset.GetId(); + }); + + m_state = ProcessState::Upgrade; + AZ::SystemTickBus::Handler::BusConnect(); + } + } + } + + void Scanner::ScanComplete(const AZ::Data::Asset& asset) + { + Log("ScanComplete: %s", asset.GetHint().c_str()); + m_inProgress = false; + m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); + m_ui->scanButton->setEnabled(true); + + m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); + FlushLogs(); + + if (m_inspectingAsset == m_assetsToInspect.end()) + { + AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + } + } + + void Scanner::FinalizeScan() + { + Log("FinalizeScan()"); + + m_ui->spinner->SetIsBusy(false); + m_ui->onlyShowOutdated->setEnabled(true); + + // Enable all the Upgrade buttons + for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) + { + QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); + if (button) + { + button->setEnabled(true); + } + } + + QString spinnerText = QStringLiteral("Scan Complete"); + if (m_assetsToUpgrade.empty()) + { + spinnerText.append(" - No graphs require upgrade!"); + } + else + { + spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" + , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); + } + + + m_ui->spinner->SetText(spinnerText); + m_ui->progressBar->setVisible(false); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + + m_keepEditorAlive.reset(); + m_settingsCache.reset(); + m_state = ProcessState::Inactive; + } + + void Scanner::FlushLogs() + { + if (m_logs.empty()) + { + return; + } + + const QTextCursor oldCursor = m_ui->textEdit->textCursor(); + QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); + + m_ui->textEdit->moveCursor(QTextCursor::End); + QTextCursor textCursor = m_ui->textEdit->textCursor(); + + while (!m_logs.empty()) + { + auto line = "\n" + m_logs.front(); + + m_logs.pop_front(); + + textCursor.insertText(line.c_str()); + } + + scrollBar->setValue(scrollBar->maximum()); + m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); + + } + + bool Scanner::CaptureLogFromTraceBus(const char* window, const char* message) + { + if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) + { + return true; + } + + AZStd::string msg = message; + if (msg.ends_with("\n")) + { + msg = msg.substr(0, msg.size() - 1); + } + + m_logs.push_back(msg); + return m_ui->updateReportingOnly->isChecked(); + } + + bool Scanner::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Error): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool Scanner::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Warning): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool Scanner::OnException(const char* message) + { + AZStd::string msg = AZStd::string::format("(Exception): %s", message); + return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); + } + + bool Scanner::OnPrintf(const char* window, const char* message) + { + return CaptureLogFromTraceBus(window, message); + } + + void Scanner::closeEvent(QCloseEvent* event) + { + m_keepEditorAlive.reset(); + + AzQtComponents::StyledDialog::closeEvent(event); + } + +#include + +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h new file mode 100644 index 0000000000..574b2b2503 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h @@ -0,0 +1,167 @@ +/* + * 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 + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") +#include +AZ_POP_DISABLE_WARNING + +#include +#include +#include + +#include +#include + +#include +#include +#include +#endif + +class QPushButton; + +namespace Ui +{ + class Scanner; +} + +namespace AzQtComponents +{ + class StyledBusyLabel; +} + +namespace ScriptCanvasEditor +{ + //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog + class Scanner + : public AzQtComponents::StyledDialog + , private AZ::SystemTickBus::Handler + , private UpgradeNotifications::Bus::Handler + , private AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + AZ_CLASS_ALLOCATOR(Scanner, AZ::SystemAllocator, 0); + + explicit Scanner(QWidget* parent = nullptr); + ~Scanner(); + + private: + + static constexpr int ColumnAsset = 0; + static constexpr int ColumnAction = 1; + static constexpr int ColumnBrowse = 2; + static constexpr int ColumnStatus = 3; + + void OnScan(); + void OnClose(); + + enum class ProcessState + { + Inactive, + Backup, + Scan, + Upgrade, + }; + ProcessState m_state = ProcessState::Inactive; + + void DoScan(); + void ScanComplete(const AZ::Data::Asset&); + + void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); + + void OnUpgradeAll(); + + // SystemTickBus::Handler + void OnSystemTick() override; + // + + // AZ::Debug::TranceMessageBus::Handler + bool OnException(const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + // + + bool CaptureLogFromTraceBus(const char* window, const char* message); + + enum class OperationResult + { + Success, + Failure, + }; + + void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); + + bool IsUpgrading() const; + + bool m_inProgress = false; + // scan fields + size_t m_currentAssetRowIndex = 0; + size_t m_inspectedAssets = 0; + size_t m_failedAssets = 0; + size_t m_discoveredAssets = 0; + + IUpgradeRequests::AssetList m_assetsToInspect; + IUpgradeRequests::AssetList::iterator m_inspectingAsset; + using UpgradeAssets = AZStd::vector>; + UpgradeAssets m_assetsToUpgrade; + UpgradeAssets::iterator m_inProgressAsset; + + AZ::Data::Asset m_currentAsset; + + AZStd::unique_ptr m_ui; + + AZStd::unique_ptr m_settingsCache; + + // upgrade fields + AZStd::recursive_mutex m_mutex; + bool m_upgradeComplete = false; + AZ::Data::Asset m_upgradeAsset; + int m_upgradeAssetIndex = 0; + OperationResult m_upgradeResult; + AZStd::string m_upgradeMessage; + AZStd::string m_tmpFileName; + + AZStd::unique_ptr m_keepEditorAlive; + + AZStd::deque m_logs; + + AZ::Entity* m_scriptCanvasEntity = nullptr; + + bool m_isUpgradingSingleGraph = false; + + void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); + + void FlushLogs(); + + void FinalizeUpgrade(); + void FinalizeScan(); + + void BackupComplete(); + AZStd::string BackupGraph(const AZ::Data::Asset&); + void UpgradeGraph(const AZ::Data::Asset&); + + void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); + void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; + + void OnSourceFileReleased(AZ::Data::Asset asset); + + void closeEvent(QCloseEvent* event) override; + + bool m_overwriteAll = false; + void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); + + void Log(const char* format, ...); + }; +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp deleted file mode 100644 index 5e6858c993..0000000000 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp +++ /dev/null @@ -1,697 +0,0 @@ -/* - * 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 "UpgradeTool.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -#include "UpgradeHelper.h" - -namespace ScriptCanvasEditor -{ - UpgradeTool::UpgradeTool(QWidget* parent /*= nullptr*/) - : AzQtComponents::StyledDialog(parent) - , m_ui(new Ui::UpgradeTool()) - { - m_ui->setupUi(this); - - AzQtComponents::CheckBox::applyToggleSwitchStyle(m_ui->doNotAskCheckbox); - AzQtComponents::CheckBox::applyToggleSwitchStyle(m_ui->makeBackupCheckbox); - - m_ui->progressFrame->setVisible(false); - - connect(m_ui->upgradeButton, &QPushButton::pressed, this, &UpgradeTool::OnUpgrade); - connect(m_ui->notNowButton, &QPushButton::pressed, this, &UpgradeTool::OnNoThanks); - - UpgradeNotifications::Bus::Handler::BusConnect(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - resize(700, 100); - } - - void UpgradeTool::OnNoThanks() - { - DisconnectBuses(); - - UpdateSettings(); - - reject(); - } - - void UpgradeTool::UpdateSettings() - { - auto userSettings = AZ::UserSettings::CreateFind(AZ_CRC("ScriptCanvasPreviewSettings", 0x1c5a2965), AZ::UserSettings::CT_LOCAL); - if (userSettings) - { - userSettings->m_showUpgradeDialog = !m_ui->doNotAskCheckbox->isChecked(); - - AZ::UserSettingsOwnerRequestBus::Event(AZ::UserSettings::CT_LOCAL, &AZ::UserSettingsOwnerRequests::SaveSettings); - } - } - - UpgradeTool::~UpgradeTool() - { - DisconnectBuses(); - } - - void UpgradeTool::DisconnectBuses() - { - UpgradeNotifications::Bus::Handler::BusDisconnect(); - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - } - - void UpgradeTool::closeEvent(QCloseEvent* event) - { - // m_keepEditorAlive.reset(); - - DisconnectBuses(); - - UpgradeNotifications::Bus::Broadcast(&UpgradeNotifications::OnUpgradeCancelled); - - AzQtComponents::StyledDialog::closeEvent(event); - } - - bool UpgradeTool::HasBackup() const - { - return m_ui->makeBackupCheckbox->isChecked(); - } - - void UpgradeTool::OnUpgrade() - { - setWindowFlag(Qt::WindowCloseButtonHint, false); - - // m_keepEditorAlive = AZStd::make_unique(); - - UpdateSettings(); - - UpgradeNotifications::Bus::Broadcast(&UpgradeNotifications::OnUpgradeStart); - - m_assetsToUpgrade.clear(); - - IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); - m_assetsToUpgrade = upgradeRequests->GetAssetsToUpgrade(); - - AZ::SystemTickBus::Handler::BusConnect(); - - if (m_ui->makeBackupCheckbox->isChecked()) - { - if (!DoBackup()) - { - // There was a problem, ask if the user wants to keep going or abort - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Backup Failed"), - QObject::tr("Failed to backup your Script Canvas graphs, do you want to proceed with upgrade?"), - QMessageBox::Yes | QMessageBox::No, this); - - if (mb.exec() == QMessageBox::Yes) - { - DoUpgrade(); - } - } - } - else - { - DoUpgrade(); - } - } - - bool UpgradeTool::DoBackup() - { - if (!m_assetsToUpgrade.empty()) - { - m_state = UpgradeState::Backup; - - m_inProgressAsset = m_assetsToUpgrade.begin(); - - m_ui->progressFrame->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - - m_ui->spinner->SetIsBusy(true); - m_ui->spinner->SetBusyIconSize(32); - - m_ui->upgradeButton->setEnabled(false); - m_ui->notNowButton->setEnabled(false); - m_ui->doNotAskCheckbox->setEnabled(false); - m_ui->makeBackupCheckbox->setEnabled(false); - - // Make the folder for the backup - - QDateTime theTime = QDateTime::currentDateTime(); - QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); - - m_backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); - char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(m_backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); - m_backupPath = backupPathCStr; - - if (!AZ::IO::FileIOBase::GetInstance()->Exists(m_backupPath.c_str())) - { - if (AZ::IO::FileIOBase::GetInstance()->CreatePath(m_backupPath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Error("Script Canvas", false, "Failed to create backup folder %s", m_backupPath.c_str()); - - return false; - } - } - } - - return true; - } - - void UpgradeTool::BackupComplete() - { - m_currentAssetIndex = 0; - m_ui->progressBar->setValue(0); - - DoUpgrade(); - } - - void UpgradeTool::DoUpgrade() - { - m_state = UpgradeState::Upgrade; - - if (!m_assetsToUpgrade.empty()) - { - m_ui->progressFrame->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - - m_ui->spinner->SetIsBusy(true); - m_ui->spinner->SetBusyIconSize(32); - - m_ui->upgradeButton->setEnabled(false); - m_ui->notNowButton->setEnabled(false); - m_ui->doNotAskCheckbox->setEnabled(false); - m_ui->makeBackupCheckbox->setEnabled(false); - - m_inProgressAsset = m_assetsToUpgrade.begin(); - } - } - - void UpgradeTool::OnAssetReady(AZ::Data::Asset asset) - { - // Start asset upgrade job when current asset is unassigned only - // If current asset is present, there is ongoing progress handling this asset already - if (IsOnReadyAssetForCurrentProcess(asset.GetId())) - { - m_inProgress = true; - m_currentAsset = asset; - m_scriptCanvasEntity = AssetUpgradeJob(asset); - if (!m_scriptCanvasEntity) - { - ResetUpgradeCurrentAsset(); - } - } - } - - void UpgradeTool::OnAssetError(AZ::Data::Asset asset) - { - // Reset upgrade target when script canvas entity is unassigned only. - // If script canvas entity is present, we should let the conversion progress finish itself. - if (IsCurrentProcessFreeToAbort(asset.GetId())) - { - AZ_TracePrintf("Script Canvas", "Asset fails to get load: %s\n", asset.GetHint().c_str()); - ResetUpgradeCurrentAsset(); - } - } - - void UpgradeTool::OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType) - { - // Reset upgrade target when script canvas entity is unassigned only. - // If script canvas entity is present, we should let the conversion progress finish itself. - if (IsCurrentProcessFreeToAbort(assetId)) - { - AZ_TracePrintf("Script Canvas", "Asset gets unloaded: %s\n", m_inProgressAsset->m_relativePath.c_str()); - ResetUpgradeCurrentAsset(); - } - } - - - void UpgradeTool::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool skipped /*=false*/) - { - if (!skipped) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - - AZStd::string tmpFileName; - bool tmpFilesaved = false; - - // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. - // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. - if (AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) - { - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); - - if (fileStream.IsOpen()) - { - if (asset.GetType() == azrtti_typeid()) - { - tmpFilesaved = AZ::Utils::SaveObjectToStream(fileStream, AZ::DataStream::ST_XML, &asset.GetAs()->GetScriptCanvasData()); - } - - fileStream.Close(); - } - - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, &asset, fullPath, tmpFileName, tmpFilesaved](bool /*success*/, const AzToolsFramework::SourceControlFileInfo& info) - { - if (!info.IsReadOnly()) - { - if (tmpFilesaved) - { - PerformMove(asset, tmpFileName, fullPath); - } - } - else - { - if (m_overwriteAll) - { - MakeWriteable(info); - - if (tmpFilesaved) - { - PerformMove(asset, tmpFileName, fullPath); - } - } - else - { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) - { - MakeWriteable(info); - - if (tmpFilesaved) - { - PerformMove(asset, tmpFileName, fullPath); - } - } - - } - } - }); - } - } - else - { - // We skipped the upgrade (it's up to date), just mark it complete - AZ::SystemTickBus::QueueFunction([this, asset]() { UpgradeComplete(asset, true); }); - - } - - } - - void UpgradeTool::MakeWriteable(const AzToolsFramework::SourceControlFileInfo& info) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - } - - void UpgradeTool::PerformMove(AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target) - { - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - - AZ::SystemTickBus::QueueFunction([this, &asset]() { UpgradeComplete(asset); }); - } - else - { - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, &asset, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, &asset, source, target]() { RetryMove(asset, source, target); }); - }); - streamer->QueueRequest(flushRequest); - } - } - - bool UpgradeTool::IsOnReadyAssetForCurrentProcess(const AZ::Data::AssetId& assetId) - { - return !m_currentAsset && m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgressAsset->m_assetId == assetId; - } - - bool UpgradeTool::IsCurrentProcessFreeToAbort(const AZ::Data::AssetId& assetId) - { - return !m_scriptCanvasEntity && m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgressAsset->m_assetId == assetId; - } - - bool UpgradeTool::IsUpgradeCompleteForAllAssets() - { - return !m_inProgress && !m_currentAsset && !m_scriptCanvasEntity && m_inProgressAsset == m_assetsToUpgrade.end(); - } - - bool UpgradeTool::IsUpgradeCompleteForCurrentAsset() - { - return !m_inProgress && !m_currentAsset && !m_scriptCanvasEntity && m_inProgressAsset != m_assetsToUpgrade.end(); - } - - void UpgradeTool::ResetUpgradeCurrentAsset() - { - AZ::Data::AssetBus::MultiHandler::BusDisconnect(m_currentAsset.GetId()); - - if (m_scriptCanvasEntity) - { - m_scriptCanvasEntity->Deactivate(); - m_scriptCanvasEntity = nullptr; - } - - if (m_inProgressAsset != m_assetsToUpgrade.end()) - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - } - - m_currentAsset.Release(); - m_currentAsset = {}; - m_inProgress = false; - } - - void UpgradeTool::OnSystemTick() - { - switch (m_state) - { - case UpgradeTool::UpgradeState::Upgrade: - - if (IsUpgradeCompleteForCurrentAsset()) - { - m_inProgress = true; - AZ::Data::AssetInfo& assetToUpgrade = *m_inProgressAsset; - - if (!AZ::Data::AssetBus::MultiHandler::BusIsConnectedId(assetToUpgrade.m_assetId)) - { - AZ::Data::AssetBus::MultiHandler::BusConnect(assetToUpgrade.m_assetId); - } - - auto asset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::Default); - asset.BlockUntilLoadComplete(); - - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(assetToUpgrade.m_relativePath); - streamer->SetRequestCompleteCallback(flushRequest, []([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - }); - streamer->QueueRequest(flushRequest); - - if (asset.IsReady() || asset.GetStatus() == AZ::Data::AssetData::AssetStatus::ReadyPreNotify) - { - m_currentAsset = asset; - m_scriptCanvasEntity = AssetUpgradeJob(asset); - if (!m_scriptCanvasEntity) - { - ResetUpgradeCurrentAsset(); - } - } - - m_ui->spinner->SetText(QObject::tr("%1").arg(assetToUpgrade.m_relativePath.c_str())); - } - else if (IsUpgradeCompleteForAllAssets()) - { - FinalizeUpgrade(); - } - break; - - case UpgradeTool::UpgradeState::Backup: - - if (m_inProgressAsset != m_assetsToUpgrade.end()) - { - AZ::Data::AssetInfo& assetToBackup = *m_inProgressAsset; - - m_ui->spinner->SetText(QObject::tr("%1").arg(assetToBackup.m_relativePath.c_str())); - - BackupAsset(assetToBackup); - - m_ui->progressBar->setValue(aznumeric_cast(++m_currentAssetIndex)); - } - else - { - BackupComplete(); - } - break; - - default: - break; - } - - AZ::Data::AssetManager::Instance().DispatchEvents(); - AZ::SystemTickBus::ExecuteQueuedEvents(); - - } - - void UpgradeTool::BackupAsset(const AZ::Data::AssetInfo& assetInfo) - { - - AZStd::string devRoot = "@devroot@"; - AZStd::string devAssets = "@devassets@"; - - char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); - - char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); - - AZStd::string relativePath = devAssetsCStr; - AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string sourceFilePath; - - // Using this to get the watch folder - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo2; - bool sourceInfoFound{}; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetInfo.m_relativePath.c_str(), assetInfo2, watchFolder); - if (sourceInfoFound) - { - AZStd::string assetPath; - AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - - sourceFilePath = assetPath; - } - - devRoot = devRootCStr; - AzFramework::StringFunc::Path::Normalize(devRoot); - - relativePath = sourceFilePath; - AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string targetFilePath; - AzFramework::StringFunc::Path::Join(m_backupPath.c_str(), relativePath.c_str(), targetFilePath); - - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Error) - { - AZStd::string filename; - AzFramework::StringFunc::Path::GetFileName(sourceFilePath.c_str(), filename); - AZ_TracePrintf("Script Canvas", "Backup: %s -> %s\n", filename.c_str(), targetFilePath.c_str()); - } - else - { - AZ_TracePrintf("Script Canvas", "(Error) Failed to create backup: %s -> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - } - - ++m_inProgressAsset; - } - - void UpgradeTool::UpgradeComplete(const AZ::Data::Asset& asset, bool skipped /*= false*/) - { - m_ui->progressBar->setValue(aznumeric_cast(++m_currentAssetIndex)); - - ResetUpgradeCurrentAsset(); - - if (!skipped) - { - AZStd::string filename; - AzFramework::StringFunc::Path::GetFileName(asset.GetHint().c_str(), filename); - AZ_TracePrintf("Script Canvas", "%s -> Upgraded and Saved!\n", filename.c_str()); - } - } - - void UpgradeTool::FinalizeUpgrade() - { - setWindowFlag(Qt::WindowCloseButtonHint, true); - - AZ::SystemTickBus::Handler::BusDisconnect(); - - m_currentAsset = {}; - - SaveLog(); - - UpgradeNotifications::Bus::Broadcast(&UpgradeNotifications::OnUpgradeComplete); - - AZ_TracePrintf("Script Canvas", "\nUpgrade Complete!\n"); - - DisconnectBuses(); - - accept(); - } - - void UpgradeTool::SaveLog() - { - AZStd::string outputFileName = AZStd::string::format("@devroot@/ScriptCanvasUpgradeReport.html"); - - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(outputFileName.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - - AZStd::string endPath = resolvedBuffer; - AZ::StringFunc::Path::Normalize(endPath); - - AZ::IO::SystemFile outputFile; - if (!outputFile.Open(endPath.c_str(), - AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY)) - { - AZ_Error("Script Canvas", false, "Failed to open file for writing: %s", endPath.c_str()); - return; - } - - QDateTime theTime = QDateTime::currentDateTime(); - AZStd::string timeStamp = theTime.toString("yyyy-MM-dd [HH.mm.ss]").toUtf8().data(); - - AZStd::string header = "\n\n\n\n\n"; - header.append(AZStd::string::format("Log captured: %s
\n", timeStamp.c_str()).c_str()); - - outputFile.Write(header.c_str(), header.size()); - for (auto& log : m_logs) - { - AZStd::string logText = AZStd::string::format("%s
", log.c_str()); - AzFramework::StringFunc::Replace(logText, "\n", "
\n"); - outputFile.Write(logText.data(), logText.size()); - } - AZStd::string footer = "\n\n"; - outputFile.Write(footer.c_str(), footer.size()); - - - - outputFile.Close(); - } - - AZ::Entity* UpgradeTool::AssetUpgradeJob(AZ::Data::Asset&) - { - return nullptr; - } - - void UpgradeTool::RetryMove(AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target) - { - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - - AZ::SystemTickBus::QueueFunction([this, &asset]() { UpgradeComplete(asset); }); - } - else - { - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, &asset, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, &asset, source, target]() { RetryMove(asset, source, target); }); - }); - streamer->QueueRequest(flushRequest); - - - //AZ::SystemTickBus::QueueFunction([this, &asset, source, target]() { RetryMove(asset, source, target); }); - } - } - - void UpgradeTool::CaptureLogFromTraceBus(const char* /*window*/, const char* message) - { - AZStd::string msg = message; - if (msg.ends_with("\n")) - { - msg = msg.substr(0, msg.size() - 1); - } - - m_logs.push_back(msg); - } - - bool UpgradeTool::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Error): %s
", message); - CaptureLogFromTraceBus(window, msg.c_str()); - - return false; - } - - bool UpgradeTool::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Warning): %s
", message); - CaptureLogFromTraceBus(window, msg.c_str()); - - return false; - } - - bool UpgradeTool::OnException(const char* message) - { - AZStd::string msg = AZStd::string::format("(Exception): %s
", message); - CaptureLogFromTraceBus("Script Canvas", msg.c_str()); - - return false; - } - - bool UpgradeTool::OnPrintf(const char* window, const char* message) - { - CaptureLogFromTraceBus(window, message); - return false; - } - -#include - -} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h deleted file mode 100644 index be00198457..0000000000 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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 - * - */ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include - -AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") -#include -AZ_POP_DISABLE_WARNING - -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#endif - -class QPushButton; - -namespace Ui -{ - class UpgradeTool; -} - -namespace ScriptCanvasEditor -{ - class KeepEditorAlive; - - //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog - class UpgradeTool - : public AzQtComponents::StyledDialog - , private AZ::SystemTickBus::Handler - , private AZ::Data::AssetBus::MultiHandler - , private UpgradeNotifications::Bus::Handler - , private AZ::Debug::TraceMessageBus::Handler - { - Q_OBJECT - - public: - AZ_CLASS_ALLOCATOR(UpgradeTool, AZ::SystemAllocator, 0); - - UpgradeTool(QWidget* parent = nullptr); - ~UpgradeTool(); - - size_t& UpgradedGraphCount() { return m_upgradedAssets; } - size_t& SkippedGraphCount() { return m_skippedAssets; } - - bool HasBackup() const; - - private: - - bool IsOnReadyAssetForCurrentProcess(const AZ::Data::AssetId& assetId); - bool IsCurrentProcessFreeToAbort(const AZ::Data::AssetId& assetId); - bool IsUpgradeCompleteForAllAssets(); - bool IsUpgradeCompleteForCurrentAsset(); - void ResetUpgradeCurrentAsset(); - - void OnUpgrade(); - void OnNoThanks(); - void UpdateSettings(); - - enum class UpgradeState - { - Inactive, - Backup, - Upgrade - }; - UpgradeState m_state = UpgradeState::Inactive; - - bool DoBackup(); - void BackupAsset(const AZ::Data::AssetInfo& assetInfo); - void BackupComplete(); - - void DoUpgrade(); - void UpgradeComplete(const AZ::Data::Asset&, bool skipped = false); - - AZ::Entity* AssetUpgradeJob(AZ::Data::Asset& asset); - - // SystemTickBus::Handler - void OnSystemTick() override; - // - - // AssetBus::Handler - void OnAssetReady(AZ::Data::Asset asset) override; - void OnAssetError(AZ::Data::Asset asset) override; - void OnAssetUnloaded(const AZ::Data::AssetId assetId, const AZ::Data::AssetType assetType) override; - // - - // AZ::Debug::TranceMessageBus::Handler - bool OnException(const char* /*message*/) override; - bool OnPrintf(const char* /*window*/, const char* /*message*/) override; - bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - // - - void CaptureLogFromTraceBus(const char* window, const char* message); - - void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; - - void RetryMove(AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target); - - void SaveLog(); - - bool m_inProgress = false; - size_t m_currentAssetIndex = 0; - - size_t m_upgradedAssets = 0; - size_t m_skippedAssets = 0; - - IUpgradeRequests::AssetList m_assetsToUpgrade; - IUpgradeRequests::AssetList::iterator m_inProgressAsset; - - AZ::Data::Asset m_currentAsset; - - AZStd::unique_ptr m_ui; - AZStd::recursive_mutex m_mutex; - - // AZStd::unique_ptr m_keepEditorAlive; - - AZStd::vector m_logs; - - AZ::Entity* m_scriptCanvasEntity = nullptr; - - AZStd::string m_backupPath; - - void FinalizeUpgrade(); - void DisconnectBuses(); - - void closeEvent(QCloseEvent* event) override; - - bool m_overwriteAll = false; - void MakeWriteable(const AzToolsFramework::SourceControlFileInfo& info); - void PerformMove(AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target); - }; -} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.ui deleted file mode 100644 index 78a63ce727..0000000000 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.ui +++ /dev/null @@ -1,260 +0,0 @@ - - - UpgradeTool - - - Qt::WindowModal - - - - 0 - 0 - 801 - 328 - - - - - 0 - 0 - - - - Script Canvas Upgrade - - - - 5 - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Script Canvas graphs are now compiled into Lua by the Asset Processor! In order to complete this upgrade, all graphs in your current project must be updated.</p><p>This upgrading is making changes to the underlying Script Canvas graph format. Depending on the number of scripts you've created this process could take a few minutes to complete. </p><p>This upgrade is required for any projects saved on 1.26 or earlier.</p><p>If you choose &quot;Not now&quot;, your project may not work correctly.</p></body></html> - - - false - - - true - - - - - - - - 0 - 80 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - 0 - 0 - - - - - 0 - 0 - - - - false - - - background-color: rgb(47, 47, 47); - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - 0 - 0 - - - - - 32 - 32 - - - - false - - - - - - - - 0 - 0 - - - - - - - 24 - - - true - - - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::MinimumExpanding - - - - 20 - 0 - - - - - - - - - - - - Backup my source graphs - - - true - - - - - - - Do not ask me again - - - - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Upgrade - - - - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Not now - - - false - - - - - - - - - - - - - - - - AzQtComponents::StyledBusyLabel - QWidget -
AzQtComponents/Components/StyledBusyLabel.h
- 1 -
-
- - -
diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h index acb28a7dba..7ce1920dbb 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h @@ -10,21 +10,17 @@ #if !defined(Q_MOC_RUN) #include - AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") #include AZ_POP_DISABLE_WARNING - #include #include +#include #include - +#include +#include #include #include - -#include -#include -#include #endif class QPushButton; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp new file mode 100644 index 0000000000..6c9acea25c --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp @@ -0,0 +1,1023 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace VersionExplorerCpp +{ + class FileEventHandler + : public AZ::IO::FileIOEventBus::Handler + { + public: + int m_errorCode = 0; + AZStd::string m_fileName; + + FileEventHandler() + { + BusConnect(); + } + + ~FileEventHandler() + { + BusDisconnect(); + } + + void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override + { + m_errorCode = errorCode; + + if (fileName) + { + m_fileName = fileName; + } + } + }; +} + +namespace ScriptCanvasEditor +{ + EditorKeepAlive::EditorKeepAlive() + { + ISystem* system = nullptr; + CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); + + m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); + + if (m_edKeepEditorActive) + { + m_keepEditorActive = m_edKeepEditorActive->GetIVal(); + m_edKeepEditorActive->Set(1); + } + } + + EditorKeepAlive::~EditorKeepAlive() + { + if (m_edKeepEditorActive) + { + m_edKeepEditorActive->Set(m_keepEditorActive); + } + } + + VersionExplorerLog::VersionExplorerLog(QWidget* parent /*= nullptr*/) + : AzQtComponents::StyledDialog(parent) + , m_ui(new Ui::VersionExplorerLog()) + { + m_ui->setupUi(this); + + m_ui->tableWidget->horizontalHeader()->setVisible(false); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); + m_ui->tableWidget->setColumnWidth(3, 22); + + m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); + + connect(m_ui->scanButton, &QPushButton::pressed, this, &VersionExplorerLog::OnScan); + connect(m_ui->closeButton, &QPushButton::pressed, this, &VersionExplorerLog::OnClose); + connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &VersionExplorerLog::OnUpgradeAll); + + m_ui->progressBar->setValue(0); + m_ui->progressBar->setVisible(false); + + m_keepEditorAlive = AZStd::make_unique(); + m_inspectingAsset = m_assetsToInspect.end(); + + } + + VersionExplorerLog::~VersionExplorerLog() + { + AZ::SystemTickBus::Handler::BusDisconnect(); + + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + + } + + void VersionExplorerLog::Log(const char* format, ...) + { + if (m_ui->verbose->isChecked()) + { + char sBuffer[2048]; + va_list ArgList; + va_start(ArgList, format); + azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); + sBuffer[sizeof(sBuffer) - 1] = '\0'; + va_end(ArgList); + + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); + } + } + + void VersionExplorerLog::OnClose() + { + reject(); + } + + bool VersionExplorerLog::IsUpgrading() const + { + return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; + } + + void VersionExplorerLog::OnSystemTick() + { + switch (m_state) + { + case ProcessState::Scan: + + if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) + { + m_inProgress = true; + AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; + m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); + m_currentAsset.BlockUntilLoadComplete(); + if (m_currentAsset.IsReady()) + { + // The asset is ready, grab its info + m_inProgress = true; + InspectAsset(m_currentAsset, assetToUpgrade); + } + else + { + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem + ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + ++m_currentAssetRowIndex; + + Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); + ++m_failedAssets; + ScanComplete(m_currentAsset); + } + } + break; + + case ProcessState::Upgrade: + { + AZStd::lock_guard lock(m_mutex); + if (m_upgradeComplete) + { + ++m_upgradeAssetIndex; + m_inProgress = false; + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + + if (m_scriptCanvasEntity) + { + m_scriptCanvasEntity->Deactivate(); + m_scriptCanvasEntity = nullptr; + } + + GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); + + if (!m_isUpgradingSingleGraph) + { + if (m_inProgressAsset != m_assetsToUpgrade.end()) + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + } + + if (m_inProgressAsset == m_assetsToUpgrade.end()) + { + FinalizeUpgrade(); + } + } + else + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + m_inProgress = false; + m_state = ProcessState::Inactive; + m_settingsCache.reset(); + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + m_isUpgradingSingleGraph = false; + + if (m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(false); + } + + m_upgradeComplete = false; + } + + if (!IsUpgrading() && m_state == ProcessState::Upgrade) + { + AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); + // Make the backup + if (errorMessage.empty()) + { + Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); + QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); + spinner->SetIsBusy(true); + } + } + + // Upgrade the graph + UpgradeGraph(*m_inProgressAsset); + } + else + { + Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); + GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); + } + + } + break; + } + default: + break; + } + + FlushLogs(); + + AZ::Data::AssetManager::Instance().DispatchEvents(); + AZ::SystemTickBus::ExecuteQueuedEvents(); + } + + // Backup + + void VersionExplorerLog::OnUpgradeAll() + { + m_state = ProcessState::Upgrade; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + AZ::Interface::Get()->SetIsUpgrading(true); + AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); + m_inProgressAsset = m_assetsToUpgrade.begin(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + AZ::SystemTickBus::Handler::BusConnect(); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + m_keepEditorAlive = AZStd::make_unique(); + } + + AZStd::string VersionExplorerLog::BackupGraph(const AZ::Data::Asset& asset) + { + if (!m_ui->makeBackupCheckbox->isChecked()) + { + // considered a success + return ""; + } + + QDateTime theTime = QDateTime::currentDateTime(); + QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); + + AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); + char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); + backupPath = backupPathCStr; + + if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) + { + if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); + return "Failed to create backup folder"; + } + } + + AZStd::string devRoot = "@devroot@"; + AZStd::string devAssets = "@devassets@"; + + char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); + + char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); + + AZStd::string relativePath = devAssetsCStr; + AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AZStd::string sourceFilePath; + + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound{}; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); + if (sourceInfoFound) + { + AZStd::string assetPath; + AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); + + sourceFilePath = assetPath; + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorerLog::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); + return "Failed to find source file"; + } + + devRoot = devRootCStr; + AzFramework::StringFunc::Path::Normalize(devRoot); + + relativePath = sourceFilePath; + AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AzFramework::StringFunc::Path::Normalize(relativePath); + AzFramework::StringFunc::Path::Normalize(backupPath); + + AZStd::string targetFilePath = backupPath; + targetFilePath += relativePath; + + if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorerLog::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return "Failed to copy source file to backup location"; + } + + Log("VersionExplorerLog::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return ""; + } + + void VersionExplorerLog::UpgradeGraph(const AZ::Data::Asset& asset) + { + m_inProgress = true; + m_upgradeComplete = false; + Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); + m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); + m_scriptCanvasEntity = nullptr; + + UpgradeNotifications::Bus::Handler::BusConnect(); + + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "VersionExplorerLog::UpgradeGraph The Script Canvas asset must have a valid entity"); + if (!scriptCanvasEntity) + { + return; + } + + AZ::Entity* queryEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); + if (queryEntity) + { + if (queryEntity->GetState() == AZ::Entity::State::Active) + { + queryEntity->Deactivate(); + } + + scriptCanvasEntity = queryEntity; + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) + { + scriptCanvasEntity->Init(); + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) + { + scriptCanvasEntity->Activate(); + } + + AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + if (graphComponent) + { + m_scriptCanvasEntity = scriptCanvasEntity; + + graphComponent->UpgradeGraph + ( asset + , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_ui->verbose->isChecked()); + } + } + + AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); + } + + void VersionExplorerLog::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + if (!fullPathFound) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); + } + + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + this->OnSourceFileReleased(asset); + }); + streamer->QueueRequest(flushRequest); + } + + void VersionExplorerLog::OnSourceFileReleased(AZ::Data::Asset asset) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + m_tmpFileName.clear(); + AZStd::string tmpFileName; + // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. + // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. + if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); + return; + } + + bool tempSavedSucceeded = false; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + if (fileStream.IsOpen()) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasEditor::ScriptCanvasAssetHandler handler; + tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); + } + + fileStream.Close(); + } + + // attempt to remove temporary file no matter what + m_tmpFileName = tmpFileName; + if (!tempSavedSucceeded) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); + return; + } + + using SCCommandBus = AzToolsFramework::SourceControlCommandBus; + SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, + [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + { + constexpr const size_t k_maxAttemps = 10; + + if (!info.IsReadOnly()) + { + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + if (m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + int result = QMessageBox::No; + if (!m_overwriteAll) + { + QMessageBox mb(QMessageBox::Warning, + QObject::tr("Failed to Save Upgraded File"), + QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), + QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); + + result = mb.exec(); + if (result == QMessageBox::YesToAll) + { + m_overwriteAll = true; + } + } + + if (result == QMessageBox::Yes || m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + } + } + }); + } + + void VersionExplorerLog::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target + , size_t remainingAttempts) + { + VersionExplorerCpp::FileEventHandler fileEventHandler; + + if (remainingAttempts == 0) + { + // all attempts failed, give up + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); + GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); + } + else if (remainingAttempts == 2) + { + // before the final attempt, flush all caches + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); + streamer->SetRequestCompleteCallback(flushRequest + , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction( + [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + else + { + // the actual move attempt + auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); + if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) + { + m_tmpFileName.clear(); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + // Bump the slice asset up in the asset processor's queue. + AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); + AZ::SystemTickBus::QueueFunction([this, asset]() + { + GraphUpgradeComplete(asset, OperationResult::Success, ""); + }); + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + } + } + + void VersionExplorerLog::GraphUpgradeComplete + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + AZStd::lock_guard lock(m_mutex); + m_upgradeComplete = true; + m_upgradeResult = result; + m_upgradeMessage = message; + m_upgradeAsset = asset; + + if (!m_tmpFileName.empty()) + { + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); + + if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) + { + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); + } + } + + if (m_upgradeResult == OperationResult::Failure) + { + AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); + } + + m_tmpFileName.clear(); + } + + void VersionExplorerLog::GraphUpgradeCompleteUIUpdate + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + QString text = asset.GetHint().c_str(); + QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); + + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); + QString assetName = asset.GetHint().c_str(); + + if (label->text().compare(assetName) == 0) + { + m_ui->tableWidget->removeCellWidget(row, ColumnAction); + m_ui->tableWidget->removeCellWidget(row, ColumnStatus); + + QToolButton* doneButton = new QToolButton(this); + doneButton->setToolTip("Upgrade complete"); + if (result == OperationResult::Success) + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); + } + else + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); + doneButton->setToolTip(message.data()); + } + + m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); + } + } + } + } + + void VersionExplorerLog::FinalizeUpgrade() + { + Log("FinalizeUpgrade!"); + m_inProgress = false; + m_assetsToUpgrade.clear(); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(true); + m_keepEditorAlive.reset(); + m_ui->progressBar->setVisible(false); + + // Manual correction + size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); + if (assetsThatNeedManualInspection > 0) + { + m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); + } + else + { + m_ui->spinner->SetText("Upgrade complete."); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + AZ::Interface::Get()->SetIsUpgrading(false); + m_settingsCache.reset(); + } + + // Scanning + + void VersionExplorerLog::OnScan() + { + m_assetsToUpgrade.clear(); + m_assetsToInspect.clear(); + m_ui->tableWidget->setRowCount(0); + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); + m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); + DoScan(); + } + + void VersionExplorerLog::DoScan() + { + m_state = ProcessState::Scan; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + + AZ::SystemTickBus::Handler::BusConnect(); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + if (!m_assetsToInspect.empty()) + { + m_discoveredAssets = m_assetsToInspect.size(); + m_failedAssets = 0; + m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; + m_ui->progressFrame->setVisible(true); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); + m_ui->progressBar->setValue(0); + + m_ui->spinner->SetIsBusy(true); + m_ui->spinner->SetBusyIconSize(32); + + m_ui->scanButton->setEnabled(false); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(false); + + m_inspectingAsset = m_assetsToInspect.begin(); + m_keepEditorAlive = AZStd::make_unique(); + } + } + + void VersionExplorerLog::BackupComplete() + { + m_currentAssetRowIndex = 0; + m_ui->progressBar->setValue(0); + DoScan(); + } + + void VersionExplorerLog::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) + { + Log("InspectAsset: %s", asset.GetHint().c_str()); + AZ::Entity* scriptCanvasEntity = nullptr; + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + if (!scriptCanvasAsset) + { + Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + return; + } + + scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); + } + + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); + bool forceUpgrade = m_ui->forceUpgrade->isChecked(); + ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); + + + if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) + { + ScanComplete(asset); + Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); + return; + } + + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + + if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) + { + m_assetsToUpgrade.push_back(asset); + + AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); + spinner->SetBusyIconSize(16); + + QPushButton* rowGoToButton = new QPushButton(this); + rowGoToButton->setText("Upgrade"); + rowGoToButton->setEnabled(false); + + connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { + + AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { + // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda + UpgradeSingle(rowGoToButton, spinner, assetInfo); + }); + + AZ::SystemTickBus::ExecuteQueuedEvents(); + + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); + } + + char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; + AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); + AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); + AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); + AZ::StringFunc::Path::Normalize(path); + + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; + QByteArray assetNameUtf8 = asset.GetHint().c_str(); + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); + + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + + QToolButton* browseButton = new QToolButton(this); + browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); + browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); + + QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); + connect(browseButton, &QPushButton::clicked, [absolutePath] { + AzQtComponents::ShowFileOnDesktop(absolutePath); + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); + ScanComplete(asset); + ++m_inspectedAssets; + ++m_currentAssetRowIndex; + } + + void VersionExplorerLog::UpgradeSingle + ( QPushButton* rowGoToButton + , AzQtComponents::StyledBusyLabel* spinner + , AZ::Data::AssetInfo assetInfo) + { + AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset + ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + + if (asset) + { + asset.BlockUntilLoadComplete(); + + if (asset.IsReady()) + { + AZ::Interface::Get()->SetIsUpgrading(true); + m_isUpgradingSingleGraph = true; + m_logs.clear(); + m_ui->textEdit->clear(); + spinner->SetIsBusy(true); + rowGoToButton->setEnabled(false); + + m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() + , [asset](const UpgradeAssets::value_type& assetToUpgrade) + { + return assetToUpgrade.GetId() == asset.GetId(); + }); + + m_state = ProcessState::Upgrade; + AZ::SystemTickBus::Handler::BusConnect(); + } + } + } + + void VersionExplorerLog::ScanComplete(const AZ::Data::Asset& asset) + { + Log("ScanComplete: %s", asset.GetHint().c_str()); + m_inProgress = false; + m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); + m_ui->scanButton->setEnabled(true); + + m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); + FlushLogs(); + + if (m_inspectingAsset == m_assetsToInspect.end()) + { + AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + } + } + + void VersionExplorerLog::FinalizeScan() + { + Log("FinalizeScan()"); + + m_ui->spinner->SetIsBusy(false); + m_ui->onlyShowOutdated->setEnabled(true); + + // Enable all the Upgrade buttons + for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) + { + QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); + if (button) + { + button->setEnabled(true); + } + } + + QString spinnerText = QStringLiteral("Scan Complete"); + if (m_assetsToUpgrade.empty()) + { + spinnerText.append(" - No graphs require upgrade!"); + } + else + { + spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" + , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); + } + + + m_ui->spinner->SetText(spinnerText); + m_ui->progressBar->setVisible(false); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + UpgradeNotifications::Bus::Handler::BusDisconnect(); + + m_keepEditorAlive.reset(); + m_settingsCache.reset(); + m_state = ProcessState::Inactive; + } + + void VersionExplorerLog::FlushLogs() + { + if (m_logs.empty()) + { + return; + } + + const QTextCursor oldCursor = m_ui->textEdit->textCursor(); + QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); + + m_ui->textEdit->moveCursor(QTextCursor::End); + QTextCursor textCursor = m_ui->textEdit->textCursor(); + + while (!m_logs.empty()) + { + auto line = "\n" + m_logs.front(); + + m_logs.pop_front(); + + textCursor.insertText(line.c_str()); + } + + scrollBar->setValue(scrollBar->maximum()); + m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); + + } + + bool VersionExplorerLog::CaptureLogFromTraceBus(const char* window, const char* message) + { + if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) + { + return true; + } + + AZStd::string msg = message; + if (msg.ends_with("\n")) + { + msg = msg.substr(0, msg.size() - 1); + } + + m_logs.push_back(msg); + return m_ui->updateReportingOnly->isChecked(); + } + + bool VersionExplorerLog::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Error): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool VersionExplorerLog::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + AZStd::string msg = AZStd::string::format("(Warning): %s", message); + return CaptureLogFromTraceBus(window, msg.c_str()); + } + + bool VersionExplorerLog::OnException(const char* message) + { + AZStd::string msg = AZStd::string::format("(Exception): %s", message); + return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); + } + + bool VersionExplorerLog::OnPrintf(const char* window, const char* message) + { + return CaptureLogFromTraceBus(window, message); + } + + void VersionExplorerLog::closeEvent(QCloseEvent* event) + { + m_keepEditorAlive.reset(); + + AzQtComponents::StyledDialog::closeEvent(event); + } + +#include + +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h new file mode 100644 index 0000000000..498b2f7745 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h @@ -0,0 +1,167 @@ +/* + * 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 + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") +#include +AZ_POP_DISABLE_WARNING + +#include +#include +#include + +#include +#include + +#include +#include +#include +#endif + +class QPushButton; + +namespace Ui +{ + class VersionExplorerLog; +} + +namespace AzQtComponents +{ + class StyledBusyLabel; +} + +namespace ScriptCanvasEditor +{ + //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog + class VersionExplorerLog + : public AzQtComponents::StyledDialog + , private AZ::SystemTickBus::Handler + , private UpgradeNotifications::Bus::Handler + , private AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + AZ_CLASS_ALLOCATOR(VersionExplorerLog, AZ::SystemAllocator, 0); + + explicit VersionExplorerLog(QWidget* parent = nullptr); + ~VersionExplorerLog(); + + private: + + static constexpr int ColumnAsset = 0; + static constexpr int ColumnAction = 1; + static constexpr int ColumnBrowse = 2; + static constexpr int ColumnStatus = 3; + + void OnScan(); + void OnClose(); + + enum class ProcessState + { + Inactive, + Backup, + Scan, + Upgrade, + }; + ProcessState m_state = ProcessState::Inactive; + + void DoScan(); + void ScanComplete(const AZ::Data::Asset&); + + void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); + + void OnUpgradeAll(); + + // SystemTickBus::Handler + void OnSystemTick() override; + // + + // AZ::Debug::TranceMessageBus::Handler + bool OnException(const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + // + + bool CaptureLogFromTraceBus(const char* window, const char* message); + + enum class OperationResult + { + Success, + Failure, + }; + + void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); + + bool IsUpgrading() const; + + bool m_inProgress = false; + // scan fields + size_t m_currentAssetRowIndex = 0; + size_t m_inspectedAssets = 0; + size_t m_failedAssets = 0; + size_t m_discoveredAssets = 0; + + IUpgradeRequests::AssetList m_assetsToInspect; + IUpgradeRequests::AssetList::iterator m_inspectingAsset; + using UpgradeAssets = AZStd::vector>; + UpgradeAssets m_assetsToUpgrade; + UpgradeAssets::iterator m_inProgressAsset; + + AZ::Data::Asset m_currentAsset; + + AZStd::unique_ptr m_ui; + + AZStd::unique_ptr m_settingsCache; + + // upgrade fields + AZStd::recursive_mutex m_mutex; + bool m_upgradeComplete = false; + AZ::Data::Asset m_upgradeAsset; + int m_upgradeAssetIndex = 0; + OperationResult m_upgradeResult; + AZStd::string m_upgradeMessage; + AZStd::string m_tmpFileName; + + AZStd::unique_ptr m_keepEditorAlive; + + AZStd::deque m_logs; + + AZ::Entity* m_scriptCanvasEntity = nullptr; + + bool m_isUpgradingSingleGraph = false; + + void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); + + void FlushLogs(); + + void FinalizeUpgrade(); + void FinalizeScan(); + + void BackupComplete(); + AZStd::string BackupGraph(const AZ::Data::Asset&); + void UpgradeGraph(const AZ::Data::Asset&); + + void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); + void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; + + void OnSourceFileReleased(AZ::Data::Asset asset); + + void closeEvent(QCloseEvent* event) override; + + bool m_overwriteAll = false; + void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); + + void Log(const char* format, ...); + }; +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h new file mode 100644 index 0000000000..4bed23c74e --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h @@ -0,0 +1,19 @@ +#include + +namespace ScriptCanvasEditor +{ + class VersionExplorerNotificationsTraits : public AZ::EBusTraits + { + public: + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusHandlerPolicy::Multiple; + using BusIdType = VersionExplorerNotificationsTraits*; + }; + using VersionExplorerNotificationsBus = AZ:EBus; + + class VersionExplorerRequestsTraits : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy = AZ::EBusHandlerPolicy::Single; + }; + using VersionExplorerRequestsBus = AZ:EBus; +} diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake index 52b1cc4772..dbffe99afd 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake @@ -262,12 +262,17 @@ set(FILES Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui - Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp - Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h - Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.ui + Editor/View/Windows/Tools/UpgradeTool/Scanner.h + Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp + Editor/View/Windows/Tools/UpgradeTool/Modifier.h + Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp + Editor/View/Windows/Tools/UpgradeTool/FileSaver.h + Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui + Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h + Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp Editor/Framework/ScriptCanvasGraphUtilities.inl Editor/Framework/ScriptCanvasGraphUtilities.h Editor/Framework/ScriptCanvasTraceUtilities.h From 30d27f23eee9de032a7aaa4750324f9be36ca78a Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 10 Sep 2021 12:52:54 -0700 Subject: [PATCH 02/24] rename version explorer to view Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/{VersionExplorer.cpp => View.cpp} | 0 .../View/Windows/Tools/UpgradeTool/{VersionExplorer.h => View.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/{VersionExplorer.cpp => View.cpp} (100%) rename Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/{VersionExplorer.h => View.h} (100%) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp similarity index 100% rename from Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp rename to Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h similarity index 100% rename from Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h rename to Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h From e558e7b0ffcc098dd1b4ff2e90fcc481af1e6997 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 10 Sep 2021 12:54:25 -0700 Subject: [PATCH 03/24] rename version explorer ui to view Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/{VersionExplorer.ui => View.ui} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/{VersionExplorer.ui => View.ui} (100%) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui similarity index 100% rename from Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui rename to Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui From e0f93ea159d7e7dfc4f641c2b797e87253cf9340 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 10 Sep 2021 13:19:55 -0700 Subject: [PATCH 04/24] view traits wip before rename Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Tools/UpgradeTool/VersionExplorerTraits.h | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h index 4bed23c74e..2b23c711dd 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h @@ -2,18 +2,21 @@ namespace ScriptCanvasEditor { - class VersionExplorerNotificationsTraits : public AZ::EBusTraits + namespace VersionExplorer { - public: - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusHandlerPolicy::Multiple; - using BusIdType = VersionExplorerNotificationsTraits*; - }; - using VersionExplorerNotificationsBus = AZ:EBus; + class RequestsTraits : public AZ::EBusTraits + { + public: + static const AZ::EBusAddressPolicy HandlerPolicy = AZ::EBusAddressPolicy::Single; + }; + using RequestsBus = AZ::EBus; - class VersionExplorerRequestsTraits : public AZ::EBusTraits - { - public: - static const AZ::EBusHandlerPolicy = AZ::EBusHandlerPolicy::Single; - }; - using VersionExplorerRequestsBus = AZ:EBus; + class NotificationsTraits : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + using BusIdType = NotificationsTraits*; + }; + using NotificationsBus = AZ::EBus; + } } From b6eb9123e545052cd2f35f8d2d21db22b9dcf2b5 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 10 Sep 2021 19:38:28 -0700 Subject: [PATCH 05/24] version explorer refactor wip Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/View/Windows/MainWindow.cpp | 4 +- .../Code/Editor/View/Windows/MainWindow.h | 2 +- .../Windows/Tools/UpgradeTool/FileSaver.cpp | 980 +--------- .../Windows/Tools/UpgradeTool/FileSaver.h | 167 +- .../View/Windows/Tools/UpgradeTool/Model.cpp | 25 + .../View/Windows/Tools/UpgradeTool/Model.h | 33 + .../Windows/Tools/UpgradeTool/ModelTraits.h | 31 + .../Windows/Tools/UpgradeTool/Modifier.cpp | 1005 +--------- .../View/Windows/Tools/UpgradeTool/Modifier.h | 154 +- .../Windows/Tools/UpgradeTool/Scanner.cpp | 1005 +--------- .../View/Windows/Tools/UpgradeTool/Scanner.h | 154 +- .../Tools/UpgradeTool/VersionExplorerLog.cpp | 1008 +--------- .../Tools/UpgradeTool/VersionExplorerLog.h | 172 +- .../Tools/UpgradeTool/VersionExplorerTraits.h | 22 - .../View/Windows/Tools/UpgradeTool/View.cpp | 1735 ++++++++--------- .../View/Windows/Tools/UpgradeTool/View.h | 220 +-- .../View/Windows/Tools/UpgradeTool/View.ui | 4 +- .../Windows/Tools/UpgradeTool/ViewTraits.h | 26 + .../Code/scriptcanvasgem_editor_files.cmake | 26 +- 19 files changed, 1154 insertions(+), 5619 deletions(-) create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h delete mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 856cceb508..33a58c18a7 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -134,7 +134,7 @@ #include #include #include -#include +#include #include @@ -3436,7 +3436,7 @@ namespace ScriptCanvasEditor void MainWindow::RunUpgradeTool() { - VersionExplorer* versionExplorer = aznew VersionExplorer(this); + auto versionExplorer = aznew VersionExplorer::View(this); versionExplorer->exec(); // Manual correction diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index ed00254677..54557c3691 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -51,7 +51,7 @@ #include -#include +#include #if SCRIPTCANVAS_EDITOR #include diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp index eb182ed291..7a7c4fe5a3 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp @@ -6,35 +6,10 @@ * */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include -namespace VersionExplorerCpp +namespace FileSaverCpp { class FileEventHandler : public AZ::IO::FileIOEventBus::Handler @@ -67,957 +42,8 @@ namespace VersionExplorerCpp namespace ScriptCanvasEditor { - EditorKeepAlive::EditorKeepAlive() + namespace VersionExplorer { - ISystem* system = nullptr; - CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - - m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - - if (m_edKeepEditorActive) - { - m_keepEditorActive = m_edKeepEditorActive->GetIVal(); - m_edKeepEditorActive->Set(1); - } - } - - EditorKeepAlive::~EditorKeepAlive() - { - if (m_edKeepEditorActive) - { - m_edKeepEditorActive->Set(m_keepEditorActive); - } - } - - VersionExplorer::VersionExplorer(QWidget* parent /*= nullptr*/) - : AzQtComponents::StyledDialog(parent) - , m_ui(new Ui::VersionExplorer()) - { - m_ui->setupUi(this); - - m_ui->tableWidget->horizontalHeader()->setVisible(false); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); - m_ui->tableWidget->setColumnWidth(3, 22); - - m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); - - connect(m_ui->scanButton, &QPushButton::pressed, this, &VersionExplorer::OnScan); - connect(m_ui->closeButton, &QPushButton::pressed, this, &VersionExplorer::OnClose); - connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &VersionExplorer::OnUpgradeAll); - - m_ui->progressBar->setValue(0); - m_ui->progressBar->setVisible(false); - - m_keepEditorAlive = AZStd::make_unique(); - m_inspectingAsset = m_assetsToInspect.end(); } - - VersionExplorer::~VersionExplorer() - { - AZ::SystemTickBus::Handler::BusDisconnect(); - - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - - } - - void VersionExplorer::Log(const char* format, ...) - { - if (m_ui->verbose->isChecked()) - { - char sBuffer[2048]; - va_list ArgList; - va_start(ArgList, format); - azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); - sBuffer[sizeof(sBuffer) - 1] = '\0'; - va_end(ArgList); - - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); - } - } - - void VersionExplorer::OnClose() - { - reject(); - } - - bool VersionExplorer::IsUpgrading() const - { - return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; - } - - void VersionExplorer::OnSystemTick() - { - switch (m_state) - { - case ProcessState::Scan: - - if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) - { - m_inProgress = true; - AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; - m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); - m_currentAsset.BlockUntilLoadComplete(); - if (m_currentAsset.IsReady()) - { - // The asset is ready, grab its info - m_inProgress = true; - InspectAsset(m_currentAsset, assetToUpgrade); - } - else - { - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem - ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - ++m_currentAssetRowIndex; - - Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); - ++m_failedAssets; - ScanComplete(m_currentAsset); - } - } - break; - - case ProcessState::Upgrade: - { - AZStd::lock_guard lock(m_mutex); - if (m_upgradeComplete) - { - ++m_upgradeAssetIndex; - m_inProgress = false; - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - - if (m_scriptCanvasEntity) - { - m_scriptCanvasEntity->Deactivate(); - m_scriptCanvasEntity = nullptr; - } - - GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); - - if (!m_isUpgradingSingleGraph) - { - if (m_inProgressAsset != m_assetsToUpgrade.end()) - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - } - - if (m_inProgressAsset == m_assetsToUpgrade.end()) - { - FinalizeUpgrade(); - } - } - else - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - m_inProgress = false; - m_state = ProcessState::Inactive; - m_settingsCache.reset(); - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - } - - m_isUpgradingSingleGraph = false; - - if (m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(false); - } - - m_upgradeComplete = false; - } - - if (!IsUpgrading() && m_state == ProcessState::Upgrade) - { - AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); - // Make the backup - if (errorMessage.empty()) - { - Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); - QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); - spinner->SetIsBusy(true); - } - } - - // Upgrade the graph - UpgradeGraph(*m_inProgressAsset); - } - else - { - Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); - GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); - } - - } - break; - } - default: - break; - } - - FlushLogs(); - - AZ::Data::AssetManager::Instance().DispatchEvents(); - AZ::SystemTickBus::ExecuteQueuedEvents(); - } - - // Backup - - void VersionExplorer::OnUpgradeAll() - { - m_state = ProcessState::Upgrade; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - AZ::Interface::Get()->SetIsUpgrading(true); - AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); - m_inProgressAsset = m_assetsToUpgrade.begin(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - AZ::SystemTickBus::Handler::BusConnect(); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - m_keepEditorAlive = AZStd::make_unique(); - } - - AZStd::string VersionExplorer::BackupGraph(const AZ::Data::Asset& asset) - { - if (!m_ui->makeBackupCheckbox->isChecked()) - { - // considered a success - return ""; - } - - QDateTime theTime = QDateTime::currentDateTime(); - QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); - - AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); - char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); - backupPath = backupPathCStr; - - if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) - { - if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); - return "Failed to create backup folder"; - } - } - - AZStd::string devRoot = "@devroot@"; - AZStd::string devAssets = "@devassets@"; - - char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); - - char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); - - AZStd::string relativePath = devAssetsCStr; - AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string sourceFilePath; - - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo; - bool sourceInfoFound{}; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); - if (sourceInfoFound) - { - AZStd::string assetPath; - AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - - sourceFilePath = assetPath; - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); - return "Failed to find source file"; - } - - devRoot = devRootCStr; - AzFramework::StringFunc::Path::Normalize(devRoot); - - relativePath = sourceFilePath; - AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AzFramework::StringFunc::Path::Normalize(relativePath); - AzFramework::StringFunc::Path::Normalize(backupPath); - - AZStd::string targetFilePath = backupPath; - targetFilePath += relativePath; - - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return "Failed to copy source file to backup location"; - } - - Log("VersionExplorer::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return ""; - } - - void VersionExplorer::UpgradeGraph(const AZ::Data::Asset& asset) - { - m_inProgress = true; - m_upgradeComplete = false; - Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); - m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); - m_scriptCanvasEntity = nullptr; - - UpgradeNotifications::Bus::Handler::BusConnect(); - - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" - , azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) - { - return; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "VersionExplorer::UpgradeGraph The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return; - } - - AZ::Entity* queryEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); - if (queryEntity) - { - if (queryEntity->GetState() == AZ::Entity::State::Active) - { - queryEntity->Deactivate(); - } - - scriptCanvasEntity = queryEntity; - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) - { - scriptCanvasEntity->Init(); - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) - { - scriptCanvasEntity->Activate(); - } - - AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - if (graphComponent) - { - m_scriptCanvasEntity = scriptCanvasEntity; - - graphComponent->UpgradeGraph - ( asset - , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_ui->verbose->isChecked()); - } - } - - AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); - } - - void VersionExplorer::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - if (!fullPathFound) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); - } - - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - this->OnSourceFileReleased(asset); - }); - streamer->QueueRequest(flushRequest); - } - - void VersionExplorer::OnSourceFileReleased(AZ::Data::Asset asset) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - m_tmpFileName.clear(); - AZStd::string tmpFileName; - // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. - // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. - if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); - return; - } - - bool tempSavedSucceeded = false; - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); - if (fileStream.IsOpen()) - { - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasEditor::ScriptCanvasAssetHandler handler; - tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); - } - - fileStream.Close(); - } - - // attempt to remove temporary file no matter what - m_tmpFileName = tmpFileName; - if (!tempSavedSucceeded) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); - return; - } - - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) - { - constexpr const size_t k_maxAttemps = 10; - - if (!info.IsReadOnly()) - { - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - if (m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - } - } - }); - } - - void VersionExplorer::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target - , size_t remainingAttempts) - { - VersionExplorerCpp::FileEventHandler fileEventHandler; - - if (remainingAttempts == 0) - { - // all attempts failed, give up - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); - GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); - } - else if (remainingAttempts == 2) - { - // before the final attempt, flush all caches - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); - streamer->SetRequestCompleteCallback(flushRequest - , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction( - [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - else - { - // the actual move attempt - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - m_tmpFileName.clear(); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - AZ::SystemTickBus::QueueFunction([this, asset]() - { - GraphUpgradeComplete(asset, OperationResult::Success, ""); - }); - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - } - } - - void VersionExplorer::GraphUpgradeComplete - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - AZStd::lock_guard lock(m_mutex); - m_upgradeComplete = true; - m_upgradeResult = result; - m_upgradeMessage = message; - m_upgradeAsset = asset; - - if (!m_tmpFileName.empty()) - { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); - - if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) - { - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); - } - } - - if (m_upgradeResult == OperationResult::Failure) - { - AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); - } - - m_tmpFileName.clear(); - } - - void VersionExplorer::GraphUpgradeCompleteUIUpdate - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - QString text = asset.GetHint().c_str(); - QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); - - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); - QString assetName = asset.GetHint().c_str(); - - if (label->text().compare(assetName) == 0) - { - m_ui->tableWidget->removeCellWidget(row, ColumnAction); - m_ui->tableWidget->removeCellWidget(row, ColumnStatus); - - QToolButton* doneButton = new QToolButton(this); - doneButton->setToolTip("Upgrade complete"); - if (result == OperationResult::Success) - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); - } - else - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); - doneButton->setToolTip(message.data()); - } - - m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); - } - } - } - } - - void VersionExplorer::FinalizeUpgrade() - { - Log("FinalizeUpgrade!"); - m_inProgress = false; - m_assetsToUpgrade.clear(); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(true); - m_keepEditorAlive.reset(); - m_ui->progressBar->setVisible(false); - - // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - if (assetsThatNeedManualInspection > 0) - { - m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); - } - else - { - m_ui->spinner->SetText("Upgrade complete."); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Interface::Get()->SetIsUpgrading(false); - m_settingsCache.reset(); - } - - // Scanning - - void VersionExplorer::OnScan() - { - m_assetsToUpgrade.clear(); - m_assetsToInspect.clear(); - m_ui->tableWidget->setRowCount(0); - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); - m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); - DoScan(); - } - - void VersionExplorer::DoScan() - { - m_state = ProcessState::Scan; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - - AZ::SystemTickBus::Handler::BusConnect(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - if (!m_assetsToInspect.empty()) - { - m_discoveredAssets = m_assetsToInspect.size(); - m_failedAssets = 0; - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - m_ui->progressFrame->setVisible(true); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); - m_ui->progressBar->setValue(0); - - m_ui->spinner->SetIsBusy(true); - m_ui->spinner->SetBusyIconSize(32); - - m_ui->scanButton->setEnabled(false); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(false); - - m_inspectingAsset = m_assetsToInspect.begin(); - m_keepEditorAlive = AZStd::make_unique(); - } - } - - void VersionExplorer::BackupComplete() - { - m_currentAssetRowIndex = 0; - m_ui->progressBar->setValue(0); - DoScan(); - } - - void VersionExplorer::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) - { - Log("InspectAsset: %s", asset.GetHint().c_str()); - AZ::Entity* scriptCanvasEntity = nullptr; - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - if (!scriptCanvasAsset) - { - Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); - return; - } - - scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); - } - - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); - bool forceUpgrade = m_ui->forceUpgrade->isChecked(); - ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); - - - if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) - { - ScanComplete(asset); - Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); - return; - } - - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - - if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) - { - m_assetsToUpgrade.push_back(asset); - - AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); - spinner->SetBusyIconSize(16); - - QPushButton* rowGoToButton = new QPushButton(this); - rowGoToButton->setText("Upgrade"); - rowGoToButton->setEnabled(false); - - connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { - - AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { - // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda - UpgradeSingle(rowGoToButton, spinner, assetInfo); - }); - - AZ::SystemTickBus::ExecuteQueuedEvents(); - - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); - } - - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); - AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); - AZ::StringFunc::Path::Normalize(path); - - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - QByteArray assetNameUtf8 = asset.GetHint().c_str(); - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); - - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); - - QToolButton* browseButton = new QToolButton(this); - browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); - browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); - - QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); - connect(browseButton, &QPushButton::clicked, [absolutePath] { - AzQtComponents::ShowFileOnDesktop(absolutePath); - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); - ScanComplete(asset); - ++m_inspectedAssets; - ++m_currentAssetRowIndex; - } - - void VersionExplorer::UpgradeSingle - ( QPushButton* rowGoToButton - , AzQtComponents::StyledBusyLabel* spinner - , AZ::Data::AssetInfo assetInfo) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset - ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - - if (asset) - { - asset.BlockUntilLoadComplete(); - - if (asset.IsReady()) - { - AZ::Interface::Get()->SetIsUpgrading(true); - m_isUpgradingSingleGraph = true; - m_logs.clear(); - m_ui->textEdit->clear(); - spinner->SetIsBusy(true); - rowGoToButton->setEnabled(false); - - m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() - , [asset](const UpgradeAssets::value_type& assetToUpgrade) - { - return assetToUpgrade.GetId() == asset.GetId(); - }); - - m_state = ProcessState::Upgrade; - AZ::SystemTickBus::Handler::BusConnect(); - } - } - } - - void VersionExplorer::ScanComplete(const AZ::Data::Asset& asset) - { - Log("ScanComplete: %s", asset.GetHint().c_str()); - m_inProgress = false; - m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - m_ui->scanButton->setEnabled(true); - - m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); - FlushLogs(); - - if (m_inspectingAsset == m_assetsToInspect.end()) - { - AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - } - } - - void VersionExplorer::FinalizeScan() - { - Log("FinalizeScan()"); - - m_ui->spinner->SetIsBusy(false); - m_ui->onlyShowOutdated->setEnabled(true); - - // Enable all the Upgrade buttons - for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) - { - QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); - if (button) - { - button->setEnabled(true); - } - } - - QString spinnerText = QStringLiteral("Scan Complete"); - if (m_assetsToUpgrade.empty()) - { - spinnerText.append(" - No graphs require upgrade!"); - } - else - { - spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" - , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); - } - - - m_ui->spinner->SetText(spinnerText); - m_ui->progressBar->setVisible(false); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - - m_keepEditorAlive.reset(); - m_settingsCache.reset(); - m_state = ProcessState::Inactive; - } - - void VersionExplorer::FlushLogs() - { - if (m_logs.empty()) - { - return; - } - - const QTextCursor oldCursor = m_ui->textEdit->textCursor(); - QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); - - m_ui->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = m_ui->textEdit->textCursor(); - - while (!m_logs.empty()) - { - auto line = "\n" + m_logs.front(); - - m_logs.pop_front(); - - textCursor.insertText(line.c_str()); - } - - scrollBar->setValue(scrollBar->maximum()); - m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); - - } - - bool VersionExplorer::CaptureLogFromTraceBus(const char* window, const char* message) - { - if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) - { - return true; - } - - AZStd::string msg = message; - if (msg.ends_with("\n")) - { - msg = msg.substr(0, msg.size() - 1); - } - - m_logs.push_back(msg); - return m_ui->updateReportingOnly->isChecked(); - } - - bool VersionExplorer::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Error): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool VersionExplorer::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Warning): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool VersionExplorer::OnException(const char* message) - { - AZStd::string msg = AZStd::string::format("(Exception): %s", message); - return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); - } - - bool VersionExplorer::OnPrintf(const char* window, const char* message) - { - return CaptureLogFromTraceBus(window, message); - } - - void VersionExplorer::closeEvent(QCloseEvent* event) - { - m_keepEditorAlive.reset(); - - AzQtComponents::StyledDialog::closeEvent(event); - } - -#include - } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h index acb28a7dba..e1ab92acbc 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h @@ -8,173 +8,16 @@ #pragma once -#if !defined(Q_MOC_RUN) -#include - -AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") -#include -AZ_POP_DISABLE_WARNING - -#include -#include -#include - -#include #include -#include -#include -#include -#endif - -class QPushButton; - -namespace Ui -{ - class VersionExplorer; -} - -namespace AzQtComponents -{ - class StyledBusyLabel; -} - namespace ScriptCanvasEditor { - //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow - //! the upgrade tool to work even if the editor is not in the foreground - class EditorKeepAlive + namespace VersionExplorer { - public: - EditorKeepAlive(); - ~EditorKeepAlive(); - - private: - int m_keepEditorActive; - ICVar* m_edKeepEditorActive; - }; - - //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog - class VersionExplorer - : public AzQtComponents::StyledDialog - , private AZ::SystemTickBus::Handler - , private UpgradeNotifications::Bus::Handler - , private AZ::Debug::TraceMessageBus::Handler - { - Q_OBJECT - - public: - AZ_CLASS_ALLOCATOR(VersionExplorer, AZ::SystemAllocator, 0); - - explicit VersionExplorer(QWidget* parent = nullptr); - ~VersionExplorer(); - - private: - - static constexpr int ColumnAsset = 0; - static constexpr int ColumnAction = 1; - static constexpr int ColumnBrowse = 2; - static constexpr int ColumnStatus = 3; - - void OnScan(); - void OnClose(); - - enum class ProcessState + class FileSaver { - Inactive, - Backup, - Scan, - Upgrade, + public: + AZ_CLASS_ALLOCATOR(FileSaver, AZ::SystemAllocator, 0); }; - ProcessState m_state = ProcessState::Inactive; - - void DoScan(); - void ScanComplete(const AZ::Data::Asset&); - - void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); - - void OnUpgradeAll(); - - // SystemTickBus::Handler - void OnSystemTick() override; - // - - // AZ::Debug::TranceMessageBus::Handler - bool OnException(const char* /*message*/) override; - bool OnPrintf(const char* /*window*/, const char* /*message*/) override; - bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - // - - bool CaptureLogFromTraceBus(const char* window, const char* message); - - enum class OperationResult - { - Success, - Failure, - }; - - void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); - - bool IsUpgrading() const; - - bool m_inProgress = false; - // scan fields - size_t m_currentAssetRowIndex = 0; - size_t m_inspectedAssets = 0; - size_t m_failedAssets = 0; - size_t m_discoveredAssets = 0; - - IUpgradeRequests::AssetList m_assetsToInspect; - IUpgradeRequests::AssetList::iterator m_inspectingAsset; - using UpgradeAssets = AZStd::vector>; - UpgradeAssets m_assetsToUpgrade; - UpgradeAssets::iterator m_inProgressAsset; - - AZ::Data::Asset m_currentAsset; - - AZStd::unique_ptr m_ui; - - AZStd::unique_ptr m_settingsCache; - - // upgrade fields - AZStd::recursive_mutex m_mutex; - bool m_upgradeComplete = false; - AZ::Data::Asset m_upgradeAsset; - int m_upgradeAssetIndex = 0; - OperationResult m_upgradeResult; - AZStd::string m_upgradeMessage; - AZStd::string m_tmpFileName; - - AZStd::unique_ptr m_keepEditorAlive; - - AZStd::deque m_logs; - - AZ::Entity* m_scriptCanvasEntity = nullptr; - - bool m_isUpgradingSingleGraph = false; - - void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); - - void FlushLogs(); - - void FinalizeUpgrade(); - void FinalizeScan(); - - void BackupComplete(); - AZStd::string BackupGraph(const AZ::Data::Asset&); - void UpgradeGraph(const AZ::Data::Asset&); - - void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); - void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; - - void OnSourceFileReleased(AZ::Data::Asset asset); - - void closeEvent(QCloseEvent* event) override; - - bool m_overwriteAll = false; - void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); - - void Log(const char* format, ...); - }; + } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp new file mode 100644 index 0000000000..710d6863f5 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp @@ -0,0 +1,25 @@ +/* + * 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 + +namespace ModifierCpp +{ + +} + +namespace ScriptCanvasEditor +{ + namespace VersionExplorer + { + const AZStd::vector* Model::GetLogs() + { + return &m_log.GetEntries(); + } + } +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h new file mode 100644 index 0000000000..44da70e85c --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h @@ -0,0 +1,33 @@ +/* + * 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 + * + */ + +#pragma once +#include +#include +#include + +namespace ScriptCanvasEditor +{ + namespace VersionExplorer + { + //! Handles model change requests, state queries; sends state change notifications + class Model + : public ModelRequestsBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(Model, AZ::SystemAllocator, 0); + + const AZStd::vector* GetLogs(); + + private: + Log m_log; + + AZStd::unique_ptr m_settingsCache; + }; + } +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h new file mode 100644 index 0000000000..e66cdac13e --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -0,0 +1,31 @@ +/* + * 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 + * + */ +#pragma once + +#include + +namespace ScriptCanvasEditor +{ + namespace VersionExplorer + { + class ModelRequestsTraits + : public AZ::EBusTraits + { + public: + virtual const AZStd::vector* GetLogs(); + }; + using ModelRequestsBus = AZ::EBus; + + class ModelNotificationsTraits + : public AZ::EBusTraits + { + public: + }; + using ModelNotificationsBus = AZ::EBus; + } +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index b96a5c6d0c..a0067e1a5f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -6,1018 +6,17 @@ * */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -namespace VersionExplorerCpp +namespace ModifierCpp { - class FileEventHandler - : public AZ::IO::FileIOEventBus::Handler - { - public: - int m_errorCode = 0; - AZStd::string m_fileName; - FileEventHandler() - { - BusConnect(); - } - - ~FileEventHandler() - { - BusDisconnect(); - } - - void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override - { - m_errorCode = errorCode; - - if (fileName) - { - m_fileName = fileName; - } - } - }; } namespace ScriptCanvasEditor { - EditorKeepAlive::EditorKeepAlive() + namespace VersionExplorer { - ISystem* system = nullptr; - CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - - m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - - if (m_edKeepEditorActive) - { - m_keepEditorActive = m_edKeepEditorActive->GetIVal(); - m_edKeepEditorActive->Set(1); - } - } - - EditorKeepAlive::~EditorKeepAlive() - { - if (m_edKeepEditorActive) - { - m_edKeepEditorActive->Set(m_keepEditorActive); - } - } - - Modifier::Modifier(QWidget* parent /*= nullptr*/) - : AzQtComponents::StyledDialog(parent) - , m_ui(new Ui::Modifier()) - { - m_ui->setupUi(this); - - m_ui->tableWidget->horizontalHeader()->setVisible(false); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); - m_ui->tableWidget->setColumnWidth(3, 22); - - m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); - - connect(m_ui->scanButton, &QPushButton::pressed, this, &Modifier::OnScan); - connect(m_ui->closeButton, &QPushButton::pressed, this, &Modifier::OnClose); - connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &Modifier::OnUpgradeAll); - - m_ui->progressBar->setValue(0); - m_ui->progressBar->setVisible(false); - - m_keepEditorAlive = AZStd::make_unique(); - m_inspectingAsset = m_assetsToInspect.end(); } - - Modifier::~Modifier() - { - AZ::SystemTickBus::Handler::BusDisconnect(); - - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - - } - - void Modifier::Log(const char* format, ...) - { - if (m_ui->verbose->isChecked()) - { - char sBuffer[2048]; - va_list ArgList; - va_start(ArgList, format); - azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); - sBuffer[sizeof(sBuffer) - 1] = '\0'; - va_end(ArgList); - - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); - } - } - - void Modifier::OnClose() - { - reject(); - } - - bool Modifier::IsUpgrading() const - { - return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; - } - - void Modifier::OnSystemTick() - { - switch (m_state) - { - case ProcessState::Scan: - - if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) - { - m_inProgress = true; - AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; - m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); - m_currentAsset.BlockUntilLoadComplete(); - if (m_currentAsset.IsReady()) - { - // The asset is ready, grab its info - m_inProgress = true; - InspectAsset(m_currentAsset, assetToUpgrade); - } - else - { - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem - ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - ++m_currentAssetRowIndex; - - Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); - ++m_failedAssets; - ScanComplete(m_currentAsset); - } - } - break; - - case ProcessState::Upgrade: - { - AZStd::lock_guard lock(m_mutex); - if (m_upgradeComplete) - { - ++m_upgradeAssetIndex; - m_inProgress = false; - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - - if (m_scriptCanvasEntity) - { - m_scriptCanvasEntity->Deactivate(); - m_scriptCanvasEntity = nullptr; - } - - GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); - - if (!m_isUpgradingSingleGraph) - { - if (m_inProgressAsset != m_assetsToUpgrade.end()) - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - } - - if (m_inProgressAsset == m_assetsToUpgrade.end()) - { - FinalizeUpgrade(); - } - } - else - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - m_inProgress = false; - m_state = ProcessState::Inactive; - m_settingsCache.reset(); - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - } - - m_isUpgradingSingleGraph = false; - - if (m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(false); - } - - m_upgradeComplete = false; - } - - if (!IsUpgrading() && m_state == ProcessState::Upgrade) - { - AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); - // Make the backup - if (errorMessage.empty()) - { - Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); - QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); - spinner->SetIsBusy(true); - } - } - - // Upgrade the graph - UpgradeGraph(*m_inProgressAsset); - } - else - { - Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); - GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); - } - - } - break; - } - default: - break; - } - - FlushLogs(); - - AZ::Data::AssetManager::Instance().DispatchEvents(); - AZ::SystemTickBus::ExecuteQueuedEvents(); - } - - // Backup - - void Modifier::OnUpgradeAll() - { - m_state = ProcessState::Upgrade; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - AZ::Interface::Get()->SetIsUpgrading(true); - AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); - m_inProgressAsset = m_assetsToUpgrade.begin(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - AZ::SystemTickBus::Handler::BusConnect(); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - m_keepEditorAlive = AZStd::make_unique(); - } - - AZStd::string Modifier::BackupGraph(const AZ::Data::Asset& asset) - { - if (!m_ui->makeBackupCheckbox->isChecked()) - { - // considered a success - return ""; - } - - QDateTime theTime = QDateTime::currentDateTime(); - QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); - - AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); - char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); - backupPath = backupPathCStr; - - if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) - { - if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); - return "Failed to create backup folder"; - } - } - - AZStd::string devRoot = "@devroot@"; - AZStd::string devAssets = "@devassets@"; - - char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); - - char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); - - AZStd::string relativePath = devAssetsCStr; - AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string sourceFilePath; - - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo; - bool sourceInfoFound{}; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); - if (sourceInfoFound) - { - AZStd::string assetPath; - AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - - sourceFilePath = assetPath; - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Modifier::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); - return "Failed to find source file"; - } - - devRoot = devRootCStr; - AzFramework::StringFunc::Path::Normalize(devRoot); - - relativePath = sourceFilePath; - AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AzFramework::StringFunc::Path::Normalize(relativePath); - AzFramework::StringFunc::Path::Normalize(backupPath); - - AZStd::string targetFilePath = backupPath; - targetFilePath += relativePath; - - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Modifier::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return "Failed to copy source file to backup location"; - } - - Log("Modifier::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return ""; - } - - void Modifier::UpgradeGraph(const AZ::Data::Asset& asset) - { - m_inProgress = true; - m_upgradeComplete = false; - Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); - m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); - m_scriptCanvasEntity = nullptr; - - UpgradeNotifications::Bus::Handler::BusConnect(); - - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" - , azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) - { - return; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "Modifier::UpgradeGraph The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return; - } - - AZ::Entity* queryEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); - if (queryEntity) - { - if (queryEntity->GetState() == AZ::Entity::State::Active) - { - queryEntity->Deactivate(); - } - - scriptCanvasEntity = queryEntity; - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) - { - scriptCanvasEntity->Init(); - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) - { - scriptCanvasEntity->Activate(); - } - - AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - if (graphComponent) - { - m_scriptCanvasEntity = scriptCanvasEntity; - - graphComponent->UpgradeGraph - ( asset - , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_ui->verbose->isChecked()); - } - } - - AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); - } - - void Modifier::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - if (!fullPathFound) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); - } - - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - this->OnSourceFileReleased(asset); - }); - streamer->QueueRequest(flushRequest); - } - - void Modifier::OnSourceFileReleased(AZ::Data::Asset asset) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - m_tmpFileName.clear(); - AZStd::string tmpFileName; - // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. - // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. - if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); - return; - } - - bool tempSavedSucceeded = false; - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); - if (fileStream.IsOpen()) - { - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasEditor::ScriptCanvasAssetHandler handler; - tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); - } - - fileStream.Close(); - } - - // attempt to remove temporary file no matter what - m_tmpFileName = tmpFileName; - if (!tempSavedSucceeded) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); - return; - } - - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) - { - constexpr const size_t k_maxAttemps = 10; - - if (!info.IsReadOnly()) - { - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - if (m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - } - } - }); - } - - void Modifier::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target - , size_t remainingAttempts) - { - VersionExplorerCpp::FileEventHandler fileEventHandler; - - if (remainingAttempts == 0) - { - // all attempts failed, give up - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); - GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); - } - else if (remainingAttempts == 2) - { - // before the final attempt, flush all caches - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); - streamer->SetRequestCompleteCallback(flushRequest - , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction( - [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - else - { - // the actual move attempt - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - m_tmpFileName.clear(); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - AZ::SystemTickBus::QueueFunction([this, asset]() - { - GraphUpgradeComplete(asset, OperationResult::Success, ""); - }); - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - } - } - - void Modifier::GraphUpgradeComplete - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - AZStd::lock_guard lock(m_mutex); - m_upgradeComplete = true; - m_upgradeResult = result; - m_upgradeMessage = message; - m_upgradeAsset = asset; - - if (!m_tmpFileName.empty()) - { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); - - if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) - { - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); - } - } - - if (m_upgradeResult == OperationResult::Failure) - { - AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); - } - - m_tmpFileName.clear(); - } - - void Modifier::GraphUpgradeCompleteUIUpdate - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - QString text = asset.GetHint().c_str(); - QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); - - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); - QString assetName = asset.GetHint().c_str(); - - if (label->text().compare(assetName) == 0) - { - m_ui->tableWidget->removeCellWidget(row, ColumnAction); - m_ui->tableWidget->removeCellWidget(row, ColumnStatus); - - QToolButton* doneButton = new QToolButton(this); - doneButton->setToolTip("Upgrade complete"); - if (result == OperationResult::Success) - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); - } - else - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); - doneButton->setToolTip(message.data()); - } - - m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); - } - } - } - } - - void Modifier::FinalizeUpgrade() - { - Log("FinalizeUpgrade!"); - m_inProgress = false; - m_assetsToUpgrade.clear(); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(true); - m_keepEditorAlive.reset(); - m_ui->progressBar->setVisible(false); - - // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - if (assetsThatNeedManualInspection > 0) - { - m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); - } - else - { - m_ui->spinner->SetText("Upgrade complete."); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Interface::Get()->SetIsUpgrading(false); - m_settingsCache.reset(); - } - - // Scanning - - void Modifier::OnScan() - { - m_assetsToUpgrade.clear(); - m_assetsToInspect.clear(); - m_ui->tableWidget->setRowCount(0); - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); - m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); - DoScan(); - } - - void Modifier::DoScan() - { - m_state = ProcessState::Scan; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - - AZ::SystemTickBus::Handler::BusConnect(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - if (!m_assetsToInspect.empty()) - { - m_discoveredAssets = m_assetsToInspect.size(); - m_failedAssets = 0; - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - m_ui->progressFrame->setVisible(true); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); - m_ui->progressBar->setValue(0); - - m_ui->spinner->SetIsBusy(true); - m_ui->spinner->SetBusyIconSize(32); - - m_ui->scanButton->setEnabled(false); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(false); - - m_inspectingAsset = m_assetsToInspect.begin(); - m_keepEditorAlive = AZStd::make_unique(); - } - } - - void Modifier::BackupComplete() - { - m_currentAssetRowIndex = 0; - m_ui->progressBar->setValue(0); - DoScan(); - } - - void Modifier::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) - { - Log("InspectAsset: %s", asset.GetHint().c_str()); - AZ::Entity* scriptCanvasEntity = nullptr; - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - if (!scriptCanvasAsset) - { - Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); - return; - } - - scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); - } - - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); - bool forceUpgrade = m_ui->forceUpgrade->isChecked(); - ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); - - - if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) - { - ScanComplete(asset); - Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); - return; - } - - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - - if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) - { - m_assetsToUpgrade.push_back(asset); - - AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); - spinner->SetBusyIconSize(16); - - QPushButton* rowGoToButton = new QPushButton(this); - rowGoToButton->setText("Upgrade"); - rowGoToButton->setEnabled(false); - - connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { - - AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { - // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda - UpgradeSingle(rowGoToButton, spinner, assetInfo); - }); - - AZ::SystemTickBus::ExecuteQueuedEvents(); - - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); - } - - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); - AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); - AZ::StringFunc::Path::Normalize(path); - - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - QByteArray assetNameUtf8 = asset.GetHint().c_str(); - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); - - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); - - QToolButton* browseButton = new QToolButton(this); - browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); - browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); - - QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); - connect(browseButton, &QPushButton::clicked, [absolutePath] { - AzQtComponents::ShowFileOnDesktop(absolutePath); - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); - ScanComplete(asset); - ++m_inspectedAssets; - ++m_currentAssetRowIndex; - } - - void Modifier::UpgradeSingle - ( QPushButton* rowGoToButton - , AzQtComponents::StyledBusyLabel* spinner - , AZ::Data::AssetInfo assetInfo) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset - ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - - if (asset) - { - asset.BlockUntilLoadComplete(); - - if (asset.IsReady()) - { - AZ::Interface::Get()->SetIsUpgrading(true); - m_isUpgradingSingleGraph = true; - m_logs.clear(); - m_ui->textEdit->clear(); - spinner->SetIsBusy(true); - rowGoToButton->setEnabled(false); - - m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() - , [asset](const UpgradeAssets::value_type& assetToUpgrade) - { - return assetToUpgrade.GetId() == asset.GetId(); - }); - - m_state = ProcessState::Upgrade; - AZ::SystemTickBus::Handler::BusConnect(); - } - } - } - - void Modifier::ScanComplete(const AZ::Data::Asset& asset) - { - Log("ScanComplete: %s", asset.GetHint().c_str()); - m_inProgress = false; - m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - m_ui->scanButton->setEnabled(true); - - m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); - FlushLogs(); - - if (m_inspectingAsset == m_assetsToInspect.end()) - { - AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - } - } - - void Modifier::FinalizeScan() - { - Log("FinalizeScan()"); - - m_ui->spinner->SetIsBusy(false); - m_ui->onlyShowOutdated->setEnabled(true); - - // Enable all the Upgrade buttons - for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) - { - QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); - if (button) - { - button->setEnabled(true); - } - } - - QString spinnerText = QStringLiteral("Scan Complete"); - if (m_assetsToUpgrade.empty()) - { - spinnerText.append(" - No graphs require upgrade!"); - } - else - { - spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" - , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); - } - - - m_ui->spinner->SetText(spinnerText); - m_ui->progressBar->setVisible(false); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - - m_keepEditorAlive.reset(); - m_settingsCache.reset(); - m_state = ProcessState::Inactive; - } - - void Modifier::FlushLogs() - { - if (m_logs.empty()) - { - return; - } - - const QTextCursor oldCursor = m_ui->textEdit->textCursor(); - QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); - - m_ui->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = m_ui->textEdit->textCursor(); - - while (!m_logs.empty()) - { - auto line = "\n" + m_logs.front(); - - m_logs.pop_front(); - - textCursor.insertText(line.c_str()); - } - - scrollBar->setValue(scrollBar->maximum()); - m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); - - } - - bool Modifier::CaptureLogFromTraceBus(const char* window, const char* message) - { - if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) - { - return true; - } - - AZStd::string msg = message; - if (msg.ends_with("\n")) - { - msg = msg.substr(0, msg.size() - 1); - } - - m_logs.push_back(msg); - return m_ui->updateReportingOnly->isChecked(); - } - - bool Modifier::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Error): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool Modifier::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Warning): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool Modifier::OnException(const char* message) - { - AZStd::string msg = AZStd::string::format("(Exception): %s", message); - return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); - } - - bool Modifier::OnPrintf(const char* window, const char* message) - { - return CaptureLogFromTraceBus(window, message); - } - - void Modifier::closeEvent(QCloseEvent* event) - { - m_keepEditorAlive.reset(); - - AzQtComponents::StyledDialog::closeEvent(event); - } - -#include - } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h index 5f379d682a..e5a40ff096 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -8,160 +8,16 @@ #pragma once -#if !defined(Q_MOC_RUN) -#include - -AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") -#include -AZ_POP_DISABLE_WARNING - -#include -#include -#include - -#include #include -#include -#include -#include -#endif - -class QPushButton; - -namespace Ui -{ - class Modifier; -} - -namespace AzQtComponents -{ - class StyledBusyLabel; -} - namespace ScriptCanvasEditor { - //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog - class Modifier - : public AzQtComponents::StyledDialog - , private AZ::SystemTickBus::Handler - , private UpgradeNotifications::Bus::Handler - , private AZ::Debug::TraceMessageBus::Handler + namespace VersionExplorer { - Q_OBJECT - - public: - AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0); - - explicit Modifier(QWidget* parent = nullptr); - ~Modifier(); - - private: - - static constexpr int ColumnAsset = 0; - static constexpr int ColumnAction = 1; - static constexpr int ColumnBrowse = 2; - static constexpr int ColumnStatus = 3; - - void OnScan(); - void OnClose(); - - enum class ProcessState + class Modifier { - Inactive, - Backup, - Scan, - Upgrade, + public: + AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0); }; - ProcessState m_state = ProcessState::Inactive; - - void DoScan(); - void ScanComplete(const AZ::Data::Asset&); - - void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); - - void OnUpgradeAll(); - - // SystemTickBus::Handler - void OnSystemTick() override; - // - - // AZ::Debug::TranceMessageBus::Handler - bool OnException(const char* /*message*/) override; - bool OnPrintf(const char* /*window*/, const char* /*message*/) override; - bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - // - - bool CaptureLogFromTraceBus(const char* window, const char* message); - - enum class OperationResult - { - Success, - Failure, - }; - - void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); - - bool IsUpgrading() const; - - bool m_inProgress = false; - // scan fields - size_t m_currentAssetRowIndex = 0; - size_t m_inspectedAssets = 0; - size_t m_failedAssets = 0; - size_t m_discoveredAssets = 0; - - IUpgradeRequests::AssetList m_assetsToInspect; - IUpgradeRequests::AssetList::iterator m_inspectingAsset; - using UpgradeAssets = AZStd::vector>; - UpgradeAssets m_assetsToUpgrade; - UpgradeAssets::iterator m_inProgressAsset; - - AZ::Data::Asset m_currentAsset; - - AZStd::unique_ptr m_ui; - - AZStd::unique_ptr m_settingsCache; - - // upgrade fields - AZStd::recursive_mutex m_mutex; - bool m_upgradeComplete = false; - AZ::Data::Asset m_upgradeAsset; - int m_upgradeAssetIndex = 0; - OperationResult m_upgradeResult; - AZStd::string m_upgradeMessage; - AZStd::string m_tmpFileName; - - AZStd::unique_ptr m_keepEditorAlive; - - AZStd::deque m_logs; - - AZ::Entity* m_scriptCanvasEntity = nullptr; - - bool m_isUpgradingSingleGraph = false; - - void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); - - void FlushLogs(); - - void FinalizeUpgrade(); - void FinalizeScan(); - - void BackupComplete(); - AZStd::string BackupGraph(const AZ::Data::Asset&); - void UpgradeGraph(const AZ::Data::Asset&); - - void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); - void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; - - void OnSourceFileReleased(AZ::Data::Asset asset); - - void closeEvent(QCloseEvent* event) override; - - bool m_overwriteAll = false; - void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); - - void Log(const char* format, ...); - }; + } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp index 29f5f8f530..f74c27004b 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp @@ -6,1018 +6,17 @@ * */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -namespace VersionExplorerCpp +namespace ScannerCpp { - class FileEventHandler - : public AZ::IO::FileIOEventBus::Handler - { - public: - int m_errorCode = 0; - AZStd::string m_fileName; - FileEventHandler() - { - BusConnect(); - } - - ~FileEventHandler() - { - BusDisconnect(); - } - - void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override - { - m_errorCode = errorCode; - - if (fileName) - { - m_fileName = fileName; - } - } - }; } namespace ScriptCanvasEditor { - EditorKeepAlive::EditorKeepAlive() + namespace VersionExplorer { - ISystem* system = nullptr; - CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - - m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - - if (m_edKeepEditorActive) - { - m_keepEditorActive = m_edKeepEditorActive->GetIVal(); - m_edKeepEditorActive->Set(1); - } - } - - EditorKeepAlive::~EditorKeepAlive() - { - if (m_edKeepEditorActive) - { - m_edKeepEditorActive->Set(m_keepEditorActive); - } - } - - Scanner::Scanner(QWidget* parent /*= nullptr*/) - : AzQtComponents::StyledDialog(parent) - , m_ui(new Ui::Scanner()) - { - m_ui->setupUi(this); - - m_ui->tableWidget->horizontalHeader()->setVisible(false); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); - m_ui->tableWidget->setColumnWidth(3, 22); - - m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); - - connect(m_ui->scanButton, &QPushButton::pressed, this, &Scanner::OnScan); - connect(m_ui->closeButton, &QPushButton::pressed, this, &Scanner::OnClose); - connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &Scanner::OnUpgradeAll); - - m_ui->progressBar->setValue(0); - m_ui->progressBar->setVisible(false); - - m_keepEditorAlive = AZStd::make_unique(); - m_inspectingAsset = m_assetsToInspect.end(); } - - Scanner::~Scanner() - { - AZ::SystemTickBus::Handler::BusDisconnect(); - - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - - } - - void Scanner::Log(const char* format, ...) - { - if (m_ui->verbose->isChecked()) - { - char sBuffer[2048]; - va_list ArgList; - va_start(ArgList, format); - azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); - sBuffer[sizeof(sBuffer) - 1] = '\0'; - va_end(ArgList); - - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); - } - } - - void Scanner::OnClose() - { - reject(); - } - - bool Scanner::IsUpgrading() const - { - return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; - } - - void Scanner::OnSystemTick() - { - switch (m_state) - { - case ProcessState::Scan: - - if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) - { - m_inProgress = true; - AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; - m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); - m_currentAsset.BlockUntilLoadComplete(); - if (m_currentAsset.IsReady()) - { - // The asset is ready, grab its info - m_inProgress = true; - InspectAsset(m_currentAsset, assetToUpgrade); - } - else - { - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem - ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - ++m_currentAssetRowIndex; - - Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); - ++m_failedAssets; - ScanComplete(m_currentAsset); - } - } - break; - - case ProcessState::Upgrade: - { - AZStd::lock_guard lock(m_mutex); - if (m_upgradeComplete) - { - ++m_upgradeAssetIndex; - m_inProgress = false; - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - - if (m_scriptCanvasEntity) - { - m_scriptCanvasEntity->Deactivate(); - m_scriptCanvasEntity = nullptr; - } - - GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); - - if (!m_isUpgradingSingleGraph) - { - if (m_inProgressAsset != m_assetsToUpgrade.end()) - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - } - - if (m_inProgressAsset == m_assetsToUpgrade.end()) - { - FinalizeUpgrade(); - } - } - else - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - m_inProgress = false; - m_state = ProcessState::Inactive; - m_settingsCache.reset(); - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - } - - m_isUpgradingSingleGraph = false; - - if (m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(false); - } - - m_upgradeComplete = false; - } - - if (!IsUpgrading() && m_state == ProcessState::Upgrade) - { - AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); - // Make the backup - if (errorMessage.empty()) - { - Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); - QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); - spinner->SetIsBusy(true); - } - } - - // Upgrade the graph - UpgradeGraph(*m_inProgressAsset); - } - else - { - Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); - GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); - } - - } - break; - } - default: - break; - } - - FlushLogs(); - - AZ::Data::AssetManager::Instance().DispatchEvents(); - AZ::SystemTickBus::ExecuteQueuedEvents(); - } - - // Backup - - void Scanner::OnUpgradeAll() - { - m_state = ProcessState::Upgrade; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - AZ::Interface::Get()->SetIsUpgrading(true); - AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); - m_inProgressAsset = m_assetsToUpgrade.begin(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - AZ::SystemTickBus::Handler::BusConnect(); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - m_keepEditorAlive = AZStd::make_unique(); - } - - AZStd::string Scanner::BackupGraph(const AZ::Data::Asset& asset) - { - if (!m_ui->makeBackupCheckbox->isChecked()) - { - // considered a success - return ""; - } - - QDateTime theTime = QDateTime::currentDateTime(); - QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); - - AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); - char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); - backupPath = backupPathCStr; - - if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) - { - if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); - return "Failed to create backup folder"; - } - } - - AZStd::string devRoot = "@devroot@"; - AZStd::string devAssets = "@devassets@"; - - char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); - - char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); - - AZStd::string relativePath = devAssetsCStr; - AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string sourceFilePath; - - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo; - bool sourceInfoFound{}; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); - if (sourceInfoFound) - { - AZStd::string assetPath; - AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - - sourceFilePath = assetPath; - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Scanner::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); - return "Failed to find source file"; - } - - devRoot = devRootCStr; - AzFramework::StringFunc::Path::Normalize(devRoot); - - relativePath = sourceFilePath; - AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AzFramework::StringFunc::Path::Normalize(relativePath); - AzFramework::StringFunc::Path::Normalize(backupPath); - - AZStd::string targetFilePath = backupPath; - targetFilePath += relativePath; - - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Scanner::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return "Failed to copy source file to backup location"; - } - - Log("Scanner::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return ""; - } - - void Scanner::UpgradeGraph(const AZ::Data::Asset& asset) - { - m_inProgress = true; - m_upgradeComplete = false; - Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); - m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); - m_scriptCanvasEntity = nullptr; - - UpgradeNotifications::Bus::Handler::BusConnect(); - - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" - , azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) - { - return; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "Scanner::UpgradeGraph The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return; - } - - AZ::Entity* queryEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); - if (queryEntity) - { - if (queryEntity->GetState() == AZ::Entity::State::Active) - { - queryEntity->Deactivate(); - } - - scriptCanvasEntity = queryEntity; - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) - { - scriptCanvasEntity->Init(); - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) - { - scriptCanvasEntity->Activate(); - } - - AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - if (graphComponent) - { - m_scriptCanvasEntity = scriptCanvasEntity; - - graphComponent->UpgradeGraph - ( asset - , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_ui->verbose->isChecked()); - } - } - - AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); - } - - void Scanner::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - if (!fullPathFound) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); - } - - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - this->OnSourceFileReleased(asset); - }); - streamer->QueueRequest(flushRequest); - } - - void Scanner::OnSourceFileReleased(AZ::Data::Asset asset) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - m_tmpFileName.clear(); - AZStd::string tmpFileName; - // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. - // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. - if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); - return; - } - - bool tempSavedSucceeded = false; - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); - if (fileStream.IsOpen()) - { - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasEditor::ScriptCanvasAssetHandler handler; - tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); - } - - fileStream.Close(); - } - - // attempt to remove temporary file no matter what - m_tmpFileName = tmpFileName; - if (!tempSavedSucceeded) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); - return; - } - - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) - { - constexpr const size_t k_maxAttemps = 10; - - if (!info.IsReadOnly()) - { - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - if (m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - } - } - }); - } - - void Scanner::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target - , size_t remainingAttempts) - { - VersionExplorerCpp::FileEventHandler fileEventHandler; - - if (remainingAttempts == 0) - { - // all attempts failed, give up - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); - GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); - } - else if (remainingAttempts == 2) - { - // before the final attempt, flush all caches - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); - streamer->SetRequestCompleteCallback(flushRequest - , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction( - [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - else - { - // the actual move attempt - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - m_tmpFileName.clear(); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - AZ::SystemTickBus::QueueFunction([this, asset]() - { - GraphUpgradeComplete(asset, OperationResult::Success, ""); - }); - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - } - } - - void Scanner::GraphUpgradeComplete - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - AZStd::lock_guard lock(m_mutex); - m_upgradeComplete = true; - m_upgradeResult = result; - m_upgradeMessage = message; - m_upgradeAsset = asset; - - if (!m_tmpFileName.empty()) - { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); - - if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) - { - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); - } - } - - if (m_upgradeResult == OperationResult::Failure) - { - AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); - } - - m_tmpFileName.clear(); - } - - void Scanner::GraphUpgradeCompleteUIUpdate - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - QString text = asset.GetHint().c_str(); - QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); - - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); - QString assetName = asset.GetHint().c_str(); - - if (label->text().compare(assetName) == 0) - { - m_ui->tableWidget->removeCellWidget(row, ColumnAction); - m_ui->tableWidget->removeCellWidget(row, ColumnStatus); - - QToolButton* doneButton = new QToolButton(this); - doneButton->setToolTip("Upgrade complete"); - if (result == OperationResult::Success) - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); - } - else - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); - doneButton->setToolTip(message.data()); - } - - m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); - } - } - } - } - - void Scanner::FinalizeUpgrade() - { - Log("FinalizeUpgrade!"); - m_inProgress = false; - m_assetsToUpgrade.clear(); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(true); - m_keepEditorAlive.reset(); - m_ui->progressBar->setVisible(false); - - // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - if (assetsThatNeedManualInspection > 0) - { - m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); - } - else - { - m_ui->spinner->SetText("Upgrade complete."); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Interface::Get()->SetIsUpgrading(false); - m_settingsCache.reset(); - } - - // Scanning - - void Scanner::OnScan() - { - m_assetsToUpgrade.clear(); - m_assetsToInspect.clear(); - m_ui->tableWidget->setRowCount(0); - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); - m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); - DoScan(); - } - - void Scanner::DoScan() - { - m_state = ProcessState::Scan; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - - AZ::SystemTickBus::Handler::BusConnect(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - if (!m_assetsToInspect.empty()) - { - m_discoveredAssets = m_assetsToInspect.size(); - m_failedAssets = 0; - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - m_ui->progressFrame->setVisible(true); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); - m_ui->progressBar->setValue(0); - - m_ui->spinner->SetIsBusy(true); - m_ui->spinner->SetBusyIconSize(32); - - m_ui->scanButton->setEnabled(false); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(false); - - m_inspectingAsset = m_assetsToInspect.begin(); - m_keepEditorAlive = AZStd::make_unique(); - } - } - - void Scanner::BackupComplete() - { - m_currentAssetRowIndex = 0; - m_ui->progressBar->setValue(0); - DoScan(); - } - - void Scanner::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) - { - Log("InspectAsset: %s", asset.GetHint().c_str()); - AZ::Entity* scriptCanvasEntity = nullptr; - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - if (!scriptCanvasAsset) - { - Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); - return; - } - - scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); - } - - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); - bool forceUpgrade = m_ui->forceUpgrade->isChecked(); - ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); - - - if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) - { - ScanComplete(asset); - Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); - return; - } - - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - - if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) - { - m_assetsToUpgrade.push_back(asset); - - AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); - spinner->SetBusyIconSize(16); - - QPushButton* rowGoToButton = new QPushButton(this); - rowGoToButton->setText("Upgrade"); - rowGoToButton->setEnabled(false); - - connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { - - AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { - // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda - UpgradeSingle(rowGoToButton, spinner, assetInfo); - }); - - AZ::SystemTickBus::ExecuteQueuedEvents(); - - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); - } - - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); - AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); - AZ::StringFunc::Path::Normalize(path); - - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - QByteArray assetNameUtf8 = asset.GetHint().c_str(); - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); - - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); - - QToolButton* browseButton = new QToolButton(this); - browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); - browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); - - QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); - connect(browseButton, &QPushButton::clicked, [absolutePath] { - AzQtComponents::ShowFileOnDesktop(absolutePath); - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); - ScanComplete(asset); - ++m_inspectedAssets; - ++m_currentAssetRowIndex; - } - - void Scanner::UpgradeSingle - ( QPushButton* rowGoToButton - , AzQtComponents::StyledBusyLabel* spinner - , AZ::Data::AssetInfo assetInfo) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset - ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - - if (asset) - { - asset.BlockUntilLoadComplete(); - - if (asset.IsReady()) - { - AZ::Interface::Get()->SetIsUpgrading(true); - m_isUpgradingSingleGraph = true; - m_logs.clear(); - m_ui->textEdit->clear(); - spinner->SetIsBusy(true); - rowGoToButton->setEnabled(false); - - m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() - , [asset](const UpgradeAssets::value_type& assetToUpgrade) - { - return assetToUpgrade.GetId() == asset.GetId(); - }); - - m_state = ProcessState::Upgrade; - AZ::SystemTickBus::Handler::BusConnect(); - } - } - } - - void Scanner::ScanComplete(const AZ::Data::Asset& asset) - { - Log("ScanComplete: %s", asset.GetHint().c_str()); - m_inProgress = false; - m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - m_ui->scanButton->setEnabled(true); - - m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); - FlushLogs(); - - if (m_inspectingAsset == m_assetsToInspect.end()) - { - AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - } - } - - void Scanner::FinalizeScan() - { - Log("FinalizeScan()"); - - m_ui->spinner->SetIsBusy(false); - m_ui->onlyShowOutdated->setEnabled(true); - - // Enable all the Upgrade buttons - for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) - { - QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); - if (button) - { - button->setEnabled(true); - } - } - - QString spinnerText = QStringLiteral("Scan Complete"); - if (m_assetsToUpgrade.empty()) - { - spinnerText.append(" - No graphs require upgrade!"); - } - else - { - spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" - , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); - } - - - m_ui->spinner->SetText(spinnerText); - m_ui->progressBar->setVisible(false); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - - m_keepEditorAlive.reset(); - m_settingsCache.reset(); - m_state = ProcessState::Inactive; - } - - void Scanner::FlushLogs() - { - if (m_logs.empty()) - { - return; - } - - const QTextCursor oldCursor = m_ui->textEdit->textCursor(); - QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); - - m_ui->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = m_ui->textEdit->textCursor(); - - while (!m_logs.empty()) - { - auto line = "\n" + m_logs.front(); - - m_logs.pop_front(); - - textCursor.insertText(line.c_str()); - } - - scrollBar->setValue(scrollBar->maximum()); - m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); - - } - - bool Scanner::CaptureLogFromTraceBus(const char* window, const char* message) - { - if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) - { - return true; - } - - AZStd::string msg = message; - if (msg.ends_with("\n")) - { - msg = msg.substr(0, msg.size() - 1); - } - - m_logs.push_back(msg); - return m_ui->updateReportingOnly->isChecked(); - } - - bool Scanner::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Error): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool Scanner::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Warning): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool Scanner::OnException(const char* message) - { - AZStd::string msg = AZStd::string::format("(Exception): %s", message); - return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); - } - - bool Scanner::OnPrintf(const char* window, const char* message) - { - return CaptureLogFromTraceBus(window, message); - } - - void Scanner::closeEvent(QCloseEvent* event) - { - m_keepEditorAlive.reset(); - - AzQtComponents::StyledDialog::closeEvent(event); - } - -#include - } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h index 574b2b2503..19642a07f1 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h @@ -8,160 +8,16 @@ #pragma once -#if !defined(Q_MOC_RUN) -#include - -AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") -#include -AZ_POP_DISABLE_WARNING - -#include -#include -#include - -#include #include -#include -#include -#include -#endif - -class QPushButton; - -namespace Ui -{ - class Scanner; -} - -namespace AzQtComponents -{ - class StyledBusyLabel; -} - namespace ScriptCanvasEditor { - //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog - class Scanner - : public AzQtComponents::StyledDialog - , private AZ::SystemTickBus::Handler - , private UpgradeNotifications::Bus::Handler - , private AZ::Debug::TraceMessageBus::Handler + namespace VersionExplorer { - Q_OBJECT - - public: - AZ_CLASS_ALLOCATOR(Scanner, AZ::SystemAllocator, 0); - - explicit Scanner(QWidget* parent = nullptr); - ~Scanner(); - - private: - - static constexpr int ColumnAsset = 0; - static constexpr int ColumnAction = 1; - static constexpr int ColumnBrowse = 2; - static constexpr int ColumnStatus = 3; - - void OnScan(); - void OnClose(); - - enum class ProcessState + class Scanner { - Inactive, - Backup, - Scan, - Upgrade, + public: + AZ_CLASS_ALLOCATOR(Scanner, AZ::SystemAllocator, 0); }; - ProcessState m_state = ProcessState::Inactive; - - void DoScan(); - void ScanComplete(const AZ::Data::Asset&); - - void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); - - void OnUpgradeAll(); - - // SystemTickBus::Handler - void OnSystemTick() override; - // - - // AZ::Debug::TranceMessageBus::Handler - bool OnException(const char* /*message*/) override; - bool OnPrintf(const char* /*window*/, const char* /*message*/) override; - bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - // - - bool CaptureLogFromTraceBus(const char* window, const char* message); - - enum class OperationResult - { - Success, - Failure, - }; - - void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); - - bool IsUpgrading() const; - - bool m_inProgress = false; - // scan fields - size_t m_currentAssetRowIndex = 0; - size_t m_inspectedAssets = 0; - size_t m_failedAssets = 0; - size_t m_discoveredAssets = 0; - - IUpgradeRequests::AssetList m_assetsToInspect; - IUpgradeRequests::AssetList::iterator m_inspectingAsset; - using UpgradeAssets = AZStd::vector>; - UpgradeAssets m_assetsToUpgrade; - UpgradeAssets::iterator m_inProgressAsset; - - AZ::Data::Asset m_currentAsset; - - AZStd::unique_ptr m_ui; - - AZStd::unique_ptr m_settingsCache; - - // upgrade fields - AZStd::recursive_mutex m_mutex; - bool m_upgradeComplete = false; - AZ::Data::Asset m_upgradeAsset; - int m_upgradeAssetIndex = 0; - OperationResult m_upgradeResult; - AZStd::string m_upgradeMessage; - AZStd::string m_tmpFileName; - - AZStd::unique_ptr m_keepEditorAlive; - - AZStd::deque m_logs; - - AZ::Entity* m_scriptCanvasEntity = nullptr; - - bool m_isUpgradingSingleGraph = false; - - void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); - - void FlushLogs(); - - void FinalizeUpgrade(); - void FinalizeScan(); - - void BackupComplete(); - AZStd::string BackupGraph(const AZ::Data::Asset&); - void UpgradeGraph(const AZ::Data::Asset&); - - void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); - void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; - - void OnSourceFileReleased(AZ::Data::Asset asset); - - void closeEvent(QCloseEvent* event) override; - - bool m_overwriteAll = false; - void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); - - void Log(const char* format, ...); - }; + } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp index 6c9acea25c..be4b619bfd 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp @@ -6,1018 +6,94 @@ * */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -namespace VersionExplorerCpp +namespace LoggerCpp { - class FileEventHandler - : public AZ::IO::FileIOEventBus::Handler - { - public: - int m_errorCode = 0; - AZStd::string m_fileName; - FileEventHandler() - { - BusConnect(); - } - - ~FileEventHandler() - { - BusDisconnect(); - } - - void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override - { - m_errorCode = errorCode; - - if (fileName) - { - m_fileName = fileName; - } - } - }; } namespace ScriptCanvasEditor { - EditorKeepAlive::EditorKeepAlive() + namespace VersionExplorer { - ISystem* system = nullptr; - CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - - m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - - if (m_edKeepEditorActive) + void Log::Activate() { - m_keepEditorActive = m_edKeepEditorActive->GetIVal(); - m_edKeepEditorActive->Set(1); + AZ::Debug::TraceMessageBus::Handler::BusConnect(); } - } - EditorKeepAlive::~EditorKeepAlive() - { - if (m_edKeepEditorActive) + void Log::AddEntry(const char* format, ...) { - m_edKeepEditorActive->Set(m_keepEditorActive); - } - } - - VersionExplorerLog::VersionExplorerLog(QWidget* parent /*= nullptr*/) - : AzQtComponents::StyledDialog(parent) - , m_ui(new Ui::VersionExplorerLog()) - { - m_ui->setupUi(this); - - m_ui->tableWidget->horizontalHeader()->setVisible(false); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); - m_ui->tableWidget->setColumnWidth(3, 22); - - m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); - - connect(m_ui->scanButton, &QPushButton::pressed, this, &VersionExplorerLog::OnScan); - connect(m_ui->closeButton, &QPushButton::pressed, this, &VersionExplorerLog::OnClose); - connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &VersionExplorerLog::OnUpgradeAll); - - m_ui->progressBar->setValue(0); - m_ui->progressBar->setVisible(false); - - m_keepEditorAlive = AZStd::make_unique(); - m_inspectingAsset = m_assetsToInspect.end(); - - } - - VersionExplorerLog::~VersionExplorerLog() - { - AZ::SystemTickBus::Handler::BusDisconnect(); - - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - - } - - void VersionExplorerLog::Log(const char* format, ...) - { - if (m_ui->verbose->isChecked()) - { - char sBuffer[2048]; - va_list ArgList; - va_start(ArgList, format); - azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); - sBuffer[sizeof(sBuffer) - 1] = '\0'; - va_end(ArgList); - - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); - } - } - - void VersionExplorerLog::OnClose() - { - reject(); - } - - bool VersionExplorerLog::IsUpgrading() const - { - return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; - } - - void VersionExplorerLog::OnSystemTick() - { - switch (m_state) - { - case ProcessState::Scan: - - if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) + if (m_isVerbose) { - m_inProgress = true; - AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; - m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); - m_currentAsset.BlockUntilLoadComplete(); - if (m_currentAsset.IsReady()) - { - // The asset is ready, grab its info - m_inProgress = true; - InspectAsset(m_currentAsset, assetToUpgrade); - } - else - { - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem - ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - ++m_currentAssetRowIndex; - - Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); - ++m_failedAssets; - ScanComplete(m_currentAsset); - } - } - break; - - case ProcessState::Upgrade: - { - AZStd::lock_guard lock(m_mutex); - if (m_upgradeComplete) - { - ++m_upgradeAssetIndex; - m_inProgress = false; - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - - if (m_scriptCanvasEntity) - { - m_scriptCanvasEntity->Deactivate(); - m_scriptCanvasEntity = nullptr; - } - - GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); - - if (!m_isUpgradingSingleGraph) - { - if (m_inProgressAsset != m_assetsToUpgrade.end()) - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - } - - if (m_inProgressAsset == m_assetsToUpgrade.end()) - { - FinalizeUpgrade(); - } - } - else - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - m_inProgress = false; - m_state = ProcessState::Inactive; - m_settingsCache.reset(); - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - } - - m_isUpgradingSingleGraph = false; - - if (m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(false); - } - - m_upgradeComplete = false; - } - - if (!IsUpgrading() && m_state == ProcessState::Upgrade) - { - AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); - // Make the backup - if (errorMessage.empty()) - { - Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); - QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); - spinner->SetIsBusy(true); - } - } - - // Upgrade the graph - UpgradeGraph(*m_inProgressAsset); - } - else - { - Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); - GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); - } - - } - break; - } - default: - break; - } - - FlushLogs(); - - AZ::Data::AssetManager::Instance().DispatchEvents(); - AZ::SystemTickBus::ExecuteQueuedEvents(); - } - - // Backup - - void VersionExplorerLog::OnUpgradeAll() - { - m_state = ProcessState::Upgrade; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - AZ::Interface::Get()->SetIsUpgrading(true); - AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); - m_inProgressAsset = m_assetsToUpgrade.begin(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - AZ::SystemTickBus::Handler::BusConnect(); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - m_keepEditorAlive = AZStd::make_unique(); - } - - AZStd::string VersionExplorerLog::BackupGraph(const AZ::Data::Asset& asset) - { - if (!m_ui->makeBackupCheckbox->isChecked()) - { - // considered a success - return ""; - } - - QDateTime theTime = QDateTime::currentDateTime(); - QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); - - AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); - char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); - backupPath = backupPathCStr; - - if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) - { - if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); - return "Failed to create backup folder"; + char sBuffer[2048]; + va_list ArgList; + va_start(ArgList, format); + azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); + sBuffer[sizeof(sBuffer) - 1] = '\0'; + va_end(ArgList); + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); } } - AZStd::string devRoot = "@devroot@"; - AZStd::string devAssets = "@devassets@"; - - char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); - - char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); - - AZStd::string relativePath = devAssetsCStr; - AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); - if (relativePath.starts_with("/")) + bool Log::CaptureFromTraceBus(const char* window, const char* message) { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string sourceFilePath; - - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo; - bool sourceInfoFound{}; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); - if (sourceInfoFound) - { - AZStd::string assetPath; - AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - - sourceFilePath = assetPath; - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorerLog::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); - return "Failed to find source file"; - } - - devRoot = devRootCStr; - AzFramework::StringFunc::Path::Normalize(devRoot); - - relativePath = sourceFilePath; - AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AzFramework::StringFunc::Path::Normalize(relativePath); - AzFramework::StringFunc::Path::Normalize(backupPath); - - AZStd::string targetFilePath = backupPath; - targetFilePath += relativePath; - - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorerLog::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return "Failed to copy source file to backup location"; - } - - Log("VersionExplorerLog::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return ""; - } - - void VersionExplorerLog::UpgradeGraph(const AZ::Data::Asset& asset) - { - m_inProgress = true; - m_upgradeComplete = false; - Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); - m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); - m_scriptCanvasEntity = nullptr; - - UpgradeNotifications::Bus::Handler::BusConnect(); - - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" - , azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) + if (m_isExclusiveReportingEnabled && window != ScriptCanvas::k_VersionExplorerWindow) { - return; + return true; } - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "VersionExplorerLog::UpgradeGraph The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) + AZStd::string msg = message; + if (msg.ends_with("\n")) { - return; + msg = msg.substr(0, msg.size() - 1); } - AZ::Entity* queryEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); - if (queryEntity) - { - if (queryEntity->GetState() == AZ::Entity::State::Active) - { - queryEntity->Deactivate(); - } - - scriptCanvasEntity = queryEntity; - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) - { - scriptCanvasEntity->Init(); - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) - { - scriptCanvasEntity->Activate(); - } - - AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - if (graphComponent) - { - m_scriptCanvasEntity = scriptCanvasEntity; - - graphComponent->UpgradeGraph - ( asset - , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_ui->verbose->isChecked()); - } + m_logs.push_back(msg); + return m_isExclusiveReportingEnabled; } - AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); - } - - void VersionExplorerLog::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - if (!fullPathFound) + void Log::Deactivate() { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); } - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + const AZStd::vector& Log::GetEntries() const { - this->OnSourceFileReleased(asset); - }); - streamer->QueueRequest(flushRequest); - } - - void VersionExplorerLog::OnSourceFileReleased(AZ::Data::Asset asset) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - m_tmpFileName.clear(); - AZStd::string tmpFileName; - // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. - // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. - if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); - return; + return m_logs; } - bool tempSavedSucceeded = false; - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); - if (fileStream.IsOpen()) + void Log::SetVersionExporerExclusivity(bool enabled) { - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasEditor::ScriptCanvasAssetHandler handler; - tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); - } - - fileStream.Close(); + m_isExclusiveReportingEnabled = enabled; } - // attempt to remove temporary file no matter what - m_tmpFileName = tmpFileName; - if (!tempSavedSucceeded) + void Log::SetVerbose(bool verbosity) { - GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); - return; + m_isVerbose = verbosity; } - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + bool Log::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) { - constexpr const size_t k_maxAttemps = 10; - - if (!info.IsReadOnly()) - { - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - if (m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - } - } - }); - } - - void VersionExplorerLog::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target - , size_t remainingAttempts) - { - VersionExplorerCpp::FileEventHandler fileEventHandler; - - if (remainingAttempts == 0) - { - // all attempts failed, give up - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); - GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); - } - else if (remainingAttempts == 2) - { - // before the final attempt, flush all caches - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); - streamer->SetRequestCompleteCallback(flushRequest - , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction( - [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - else - { - // the actual move attempt - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - m_tmpFileName.clear(); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - AZ::SystemTickBus::QueueFunction([this, asset]() - { - GraphUpgradeComplete(asset, OperationResult::Success, ""); - }); - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - } - } - - void VersionExplorerLog::GraphUpgradeComplete - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - AZStd::lock_guard lock(m_mutex); - m_upgradeComplete = true; - m_upgradeResult = result; - m_upgradeMessage = message; - m_upgradeAsset = asset; - - if (!m_tmpFileName.empty()) - { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); - - if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) - { - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); - } + AZStd::string msg = AZStd::string::format("(Error): %s", message); + return CaptureFromTraceBus(window, msg.c_str()); } - if (m_upgradeResult == OperationResult::Failure) + bool Log::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) { - AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); + AZStd::string msg = AZStd::string::format("(Warning): %s", message); + return CaptureFromTraceBus(window, msg.c_str()); } - m_tmpFileName.clear(); - } - - void VersionExplorerLog::GraphUpgradeCompleteUIUpdate - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - QString text = asset.GetHint().c_str(); - QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); - - if (!items.isEmpty()) + bool Log::OnException(const char* message) { - for (auto* item : items) - { - int row = item->row(); - QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); - QString assetName = asset.GetHint().c_str(); + AZStd::string msg = AZStd::string::format("(Exception): %s", message); + return CaptureFromTraceBus("Script Canvas", msg.c_str()); + } - if (label->text().compare(assetName) == 0) - { - m_ui->tableWidget->removeCellWidget(row, ColumnAction); - m_ui->tableWidget->removeCellWidget(row, ColumnStatus); - - QToolButton* doneButton = new QToolButton(this); - doneButton->setToolTip("Upgrade complete"); - if (result == OperationResult::Success) - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); - } - else - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); - doneButton->setToolTip(message.data()); - } - - m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); - } - } + bool Log::OnPrintf(const char* window, const char* message) + { + return CaptureFromTraceBus(window, message); } } - - void VersionExplorerLog::FinalizeUpgrade() - { - Log("FinalizeUpgrade!"); - m_inProgress = false; - m_assetsToUpgrade.clear(); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(true); - m_keepEditorAlive.reset(); - m_ui->progressBar->setVisible(false); - - // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - if (assetsThatNeedManualInspection > 0) - { - m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); - } - else - { - m_ui->spinner->SetText("Upgrade complete."); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Interface::Get()->SetIsUpgrading(false); - m_settingsCache.reset(); - } - - // Scanning - - void VersionExplorerLog::OnScan() - { - m_assetsToUpgrade.clear(); - m_assetsToInspect.clear(); - m_ui->tableWidget->setRowCount(0); - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); - m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); - DoScan(); - } - - void VersionExplorerLog::DoScan() - { - m_state = ProcessState::Scan; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - - AZ::SystemTickBus::Handler::BusConnect(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - if (!m_assetsToInspect.empty()) - { - m_discoveredAssets = m_assetsToInspect.size(); - m_failedAssets = 0; - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - m_ui->progressFrame->setVisible(true); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); - m_ui->progressBar->setValue(0); - - m_ui->spinner->SetIsBusy(true); - m_ui->spinner->SetBusyIconSize(32); - - m_ui->scanButton->setEnabled(false); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(false); - - m_inspectingAsset = m_assetsToInspect.begin(); - m_keepEditorAlive = AZStd::make_unique(); - } - } - - void VersionExplorerLog::BackupComplete() - { - m_currentAssetRowIndex = 0; - m_ui->progressBar->setValue(0); - DoScan(); - } - - void VersionExplorerLog::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) - { - Log("InspectAsset: %s", asset.GetHint().c_str()); - AZ::Entity* scriptCanvasEntity = nullptr; - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - if (!scriptCanvasAsset) - { - Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); - return; - } - - scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); - } - - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); - bool forceUpgrade = m_ui->forceUpgrade->isChecked(); - ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); - - - if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) - { - ScanComplete(asset); - Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); - return; - } - - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - - if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) - { - m_assetsToUpgrade.push_back(asset); - - AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); - spinner->SetBusyIconSize(16); - - QPushButton* rowGoToButton = new QPushButton(this); - rowGoToButton->setText("Upgrade"); - rowGoToButton->setEnabled(false); - - connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { - - AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { - // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda - UpgradeSingle(rowGoToButton, spinner, assetInfo); - }); - - AZ::SystemTickBus::ExecuteQueuedEvents(); - - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); - } - - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); - AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); - AZ::StringFunc::Path::Normalize(path); - - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - QByteArray assetNameUtf8 = asset.GetHint().c_str(); - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); - - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); - - QToolButton* browseButton = new QToolButton(this); - browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); - browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); - - QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); - connect(browseButton, &QPushButton::clicked, [absolutePath] { - AzQtComponents::ShowFileOnDesktop(absolutePath); - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); - ScanComplete(asset); - ++m_inspectedAssets; - ++m_currentAssetRowIndex; - } - - void VersionExplorerLog::UpgradeSingle - ( QPushButton* rowGoToButton - , AzQtComponents::StyledBusyLabel* spinner - , AZ::Data::AssetInfo assetInfo) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset - ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - - if (asset) - { - asset.BlockUntilLoadComplete(); - - if (asset.IsReady()) - { - AZ::Interface::Get()->SetIsUpgrading(true); - m_isUpgradingSingleGraph = true; - m_logs.clear(); - m_ui->textEdit->clear(); - spinner->SetIsBusy(true); - rowGoToButton->setEnabled(false); - - m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() - , [asset](const UpgradeAssets::value_type& assetToUpgrade) - { - return assetToUpgrade.GetId() == asset.GetId(); - }); - - m_state = ProcessState::Upgrade; - AZ::SystemTickBus::Handler::BusConnect(); - } - } - } - - void VersionExplorerLog::ScanComplete(const AZ::Data::Asset& asset) - { - Log("ScanComplete: %s", asset.GetHint().c_str()); - m_inProgress = false; - m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - m_ui->scanButton->setEnabled(true); - - m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); - FlushLogs(); - - if (m_inspectingAsset == m_assetsToInspect.end()) - { - AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - } - } - - void VersionExplorerLog::FinalizeScan() - { - Log("FinalizeScan()"); - - m_ui->spinner->SetIsBusy(false); - m_ui->onlyShowOutdated->setEnabled(true); - - // Enable all the Upgrade buttons - for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) - { - QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); - if (button) - { - button->setEnabled(true); - } - } - - QString spinnerText = QStringLiteral("Scan Complete"); - if (m_assetsToUpgrade.empty()) - { - spinnerText.append(" - No graphs require upgrade!"); - } - else - { - spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" - , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); - } - - - m_ui->spinner->SetText(spinnerText); - m_ui->progressBar->setVisible(false); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - - m_keepEditorAlive.reset(); - m_settingsCache.reset(); - m_state = ProcessState::Inactive; - } - - void VersionExplorerLog::FlushLogs() - { - if (m_logs.empty()) - { - return; - } - - const QTextCursor oldCursor = m_ui->textEdit->textCursor(); - QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); - - m_ui->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = m_ui->textEdit->textCursor(); - - while (!m_logs.empty()) - { - auto line = "\n" + m_logs.front(); - - m_logs.pop_front(); - - textCursor.insertText(line.c_str()); - } - - scrollBar->setValue(scrollBar->maximum()); - m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); - - } - - bool VersionExplorerLog::CaptureLogFromTraceBus(const char* window, const char* message) - { - if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) - { - return true; - } - - AZStd::string msg = message; - if (msg.ends_with("\n")) - { - msg = msg.substr(0, msg.size() - 1); - } - - m_logs.push_back(msg); - return m_ui->updateReportingOnly->isChecked(); - } - - bool VersionExplorerLog::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Error): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool VersionExplorerLog::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Warning): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool VersionExplorerLog::OnException(const char* message) - { - AZStd::string msg = AZStd::string::format("(Exception): %s", message); - return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); - } - - bool VersionExplorerLog::OnPrintf(const char* window, const char* message) - { - return CaptureLogFromTraceBus(window, message); - } - - void VersionExplorerLog::closeEvent(QCloseEvent* event) - { - m_keepEditorAlive.reset(); - - AzQtComponents::StyledDialog::closeEvent(event); - } - -#include - } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h index 498b2f7745..1ba8e8c9b1 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h @@ -8,160 +8,36 @@ #pragma once -#if !defined(Q_MOC_RUN) -#include - -AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") -#include -AZ_POP_DISABLE_WARNING - -#include -#include -#include - -#include #include - -#include -#include #include -#endif - -class QPushButton; - -namespace Ui -{ - class VersionExplorerLog; -} - -namespace AzQtComponents -{ - class StyledBusyLabel; -} namespace ScriptCanvasEditor { - //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog - class VersionExplorerLog - : public AzQtComponents::StyledDialog - , private AZ::SystemTickBus::Handler - , private UpgradeNotifications::Bus::Handler - , private AZ::Debug::TraceMessageBus::Handler + namespace VersionExplorer { - Q_OBJECT - - public: - AZ_CLASS_ALLOCATOR(VersionExplorerLog, AZ::SystemAllocator, 0); - - explicit VersionExplorerLog(QWidget* parent = nullptr); - ~VersionExplorerLog(); - - private: - - static constexpr int ColumnAsset = 0; - static constexpr int ColumnAction = 1; - static constexpr int ColumnBrowse = 2; - static constexpr int ColumnStatus = 3; - - void OnScan(); - void OnClose(); - - enum class ProcessState + class Log + : private AZ::Debug::TraceMessageBus::Handler { - Inactive, - Backup, - Scan, - Upgrade, + public: + AZ_CLASS_ALLOCATOR(Log, AZ::SystemAllocator, 0); + + void Activate(); + void AddEntry(const char* format, ...); + void Deactivate(); + const AZStd::vector& GetEntries() const; + void SetVersionExporerExclusivity(bool enabled); + void SetVerbose(bool verbosity); + + private: + bool m_isExclusiveReportingEnabled = false; + bool m_isVerbose = false; + AZStd::vector m_logs; + + bool CaptureFromTraceBus(const char* window, const char* message); + bool OnException(const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; }; - ProcessState m_state = ProcessState::Inactive; - - void DoScan(); - void ScanComplete(const AZ::Data::Asset&); - - void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); - - void OnUpgradeAll(); - - // SystemTickBus::Handler - void OnSystemTick() override; - // - - // AZ::Debug::TranceMessageBus::Handler - bool OnException(const char* /*message*/) override; - bool OnPrintf(const char* /*window*/, const char* /*message*/) override; - bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - // - - bool CaptureLogFromTraceBus(const char* window, const char* message); - - enum class OperationResult - { - Success, - Failure, - }; - - void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); - - bool IsUpgrading() const; - - bool m_inProgress = false; - // scan fields - size_t m_currentAssetRowIndex = 0; - size_t m_inspectedAssets = 0; - size_t m_failedAssets = 0; - size_t m_discoveredAssets = 0; - - IUpgradeRequests::AssetList m_assetsToInspect; - IUpgradeRequests::AssetList::iterator m_inspectingAsset; - using UpgradeAssets = AZStd::vector>; - UpgradeAssets m_assetsToUpgrade; - UpgradeAssets::iterator m_inProgressAsset; - - AZ::Data::Asset m_currentAsset; - - AZStd::unique_ptr m_ui; - - AZStd::unique_ptr m_settingsCache; - - // upgrade fields - AZStd::recursive_mutex m_mutex; - bool m_upgradeComplete = false; - AZ::Data::Asset m_upgradeAsset; - int m_upgradeAssetIndex = 0; - OperationResult m_upgradeResult; - AZStd::string m_upgradeMessage; - AZStd::string m_tmpFileName; - - AZStd::unique_ptr m_keepEditorAlive; - - AZStd::deque m_logs; - - AZ::Entity* m_scriptCanvasEntity = nullptr; - - bool m_isUpgradingSingleGraph = false; - - void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); - - void FlushLogs(); - - void FinalizeUpgrade(); - void FinalizeScan(); - - void BackupComplete(); - AZStd::string BackupGraph(const AZ::Data::Asset&); - void UpgradeGraph(const AZ::Data::Asset&); - - void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); - void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; - - void OnSourceFileReleased(AZ::Data::Asset asset); - - void closeEvent(QCloseEvent* event) override; - - bool m_overwriteAll = false; - void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); - - void Log(const char* format, ...); - }; + } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h deleted file mode 100644 index 2b23c711dd..0000000000 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerTraits.h +++ /dev/null @@ -1,22 +0,0 @@ -#include - -namespace ScriptCanvasEditor -{ - namespace VersionExplorer - { - class RequestsTraits : public AZ::EBusTraits - { - public: - static const AZ::EBusAddressPolicy HandlerPolicy = AZ::EBusAddressPolicy::Single; - }; - using RequestsBus = AZ::EBus; - - class NotificationsTraits : public AZ::EBusTraits - { - public: - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - using BusIdType = NotificationsTraits*; - }; - using NotificationsBus = AZ::EBus; - } -} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp index eb182ed291..bf407765e1 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp @@ -28,996 +28,909 @@ #include #include #include -#include -#include +#include +#include #include #include #include -namespace VersionExplorerCpp -{ - class FileEventHandler - : public AZ::IO::FileIOEventBus::Handler - { - public: - int m_errorCode = 0; - AZStd::string m_fileName; - - FileEventHandler() - { - BusConnect(); - } - - ~FileEventHandler() - { - BusDisconnect(); - } - - void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override - { - m_errorCode = errorCode; - - if (fileName) - { - m_fileName = fileName; - } - } - }; -} - namespace ScriptCanvasEditor { - EditorKeepAlive::EditorKeepAlive() + namespace VersionExplorer { - ISystem* system = nullptr; - CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - - m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - - if (m_edKeepEditorActive) + EditorKeepAlive::EditorKeepAlive() { - m_keepEditorActive = m_edKeepEditorActive->GetIVal(); - m_edKeepEditorActive->Set(1); - } - } + ISystem* system = nullptr; + CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - EditorKeepAlive::~EditorKeepAlive() - { - if (m_edKeepEditorActive) - { - m_edKeepEditorActive->Set(m_keepEditorActive); - } - } + m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - VersionExplorer::VersionExplorer(QWidget* parent /*= nullptr*/) - : AzQtComponents::StyledDialog(parent) - , m_ui(new Ui::VersionExplorer()) - { - m_ui->setupUi(this); - - m_ui->tableWidget->horizontalHeader()->setVisible(false); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); - m_ui->tableWidget->setColumnWidth(3, 22); - - m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); - - connect(m_ui->scanButton, &QPushButton::pressed, this, &VersionExplorer::OnScan); - connect(m_ui->closeButton, &QPushButton::pressed, this, &VersionExplorer::OnClose); - connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &VersionExplorer::OnUpgradeAll); - - m_ui->progressBar->setValue(0); - m_ui->progressBar->setVisible(false); - - m_keepEditorAlive = AZStd::make_unique(); - m_inspectingAsset = m_assetsToInspect.end(); - - } - - VersionExplorer::~VersionExplorer() - { - AZ::SystemTickBus::Handler::BusDisconnect(); - - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - - } - - void VersionExplorer::Log(const char* format, ...) - { - if (m_ui->verbose->isChecked()) - { - char sBuffer[2048]; - va_list ArgList; - va_start(ArgList, format); - azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); - sBuffer[sizeof(sBuffer) - 1] = '\0'; - va_end(ArgList); - - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); - } - } - - void VersionExplorer::OnClose() - { - reject(); - } - - bool VersionExplorer::IsUpgrading() const - { - return m_inProgressAsset != m_assetsToUpgrade.end() && m_inProgress; - } - - void VersionExplorer::OnSystemTick() - { - switch (m_state) - { - case ProcessState::Scan: - - if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) + if (m_edKeepEditorActive) { - m_inProgress = true; - AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; - m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); - m_currentAsset.BlockUntilLoadComplete(); - if (m_currentAsset.IsReady()) - { - // The asset is ready, grab its info - m_inProgress = true; - InspectAsset(m_currentAsset, assetToUpgrade); - } - else - { - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem - ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - ++m_currentAssetRowIndex; + m_keepEditorActive = m_edKeepEditorActive->GetIVal(); + m_edKeepEditorActive->Set(1); + } + } - Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); - ++m_failedAssets; - ScanComplete(m_currentAsset); + EditorKeepAlive::~EditorKeepAlive() + { + if (m_edKeepEditorActive) + { + m_edKeepEditorActive->Set(m_keepEditorActive); + } + } + + View::View(QWidget* parent) + : AzQtComponents::StyledDialog(parent) + , m_ui(new Ui::View()) + { + m_ui->setupUi(this); + m_ui->tableWidget->horizontalHeader()->setVisible(false); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); + m_ui->tableWidget->setColumnWidth(3, 22); + m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); + connect(m_ui->scanButton, &QPushButton::pressed, this, &View::OnScanButtonPress); + connect(m_ui->closeButton, &QPushButton::pressed, this, &View::OnCloseButtonPress); + connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &View::OnUpgradeAllButtonPress); + m_ui->progressBar->setValue(0); + m_ui->progressBar->setVisible(false); + + ViewRequestsBus::Handler::BusConnect(); + ModelNotificationsBus::Handler::BusConnect(); + + // move to model, maybe + m_keepEditorAlive = AZStd::make_unique(); + } + + void View::Log(const char* /*format*/, ...) + { +// if (m_ui->verbose->isChecked()) +// { +// char sBuffer[2048]; +// va_list ArgList; +// va_start(ArgList, format); +// azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); +// sBuffer[sizeof(sBuffer) - 1] = '\0'; +// va_end(ArgList); +// +// AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); +// } + } + + void View::OnCloseButtonPress() + { + reject(); + } + + void View::OnSystemTick() + { +// switch (m_state) +// { +// case ProcessState::Scan: +// +// if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) +// { +// m_inProgress = true; +// AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; +// m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); +// Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); +// m_currentAsset.BlockUntilLoadComplete(); +// if (m_currentAsset.IsReady()) +// { +// // The asset is ready, grab its info +// m_inProgress = true; +// InspectAsset(m_currentAsset, assetToUpgrade); +// } +// else +// { +// m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); +// QTableWidgetItem* rowName = new QTableWidgetItem +// (tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); +// m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); +// ++m_currentAssetRowIndex; +// +// Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); +// ++m_failedAssets; +// ScanComplete(m_currentAsset); +// } +// } +// break; +// +// case ProcessState::Upgrade: +// { +// AZStd::lock_guard lock(m_mutex); +// if (m_upgradeComplete) +// { +// ++m_upgradeAssetIndex; +// m_inProgress = false; +// m_ui->progressBar->setVisible(true); +// m_ui->progressBar->setValue(m_upgradeAssetIndex); +// +// if (m_scriptCanvasEntity) +// { +// m_scriptCanvasEntity->Deactivate(); +// m_scriptCanvasEntity = nullptr; +// } +// +// GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); +// +// if (!m_isUpgradingSingleGraph) +// { +// if (m_inProgressAsset != m_assetsToUpgrade.end()) +// { +// m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); +// } +// +// if (m_inProgressAsset == m_assetsToUpgrade.end()) +// { +// FinalizeUpgrade(); +// } +// } +// else +// { +// m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); +// m_inProgress = false; +// m_state = ProcessState::Inactive; +// // m_settingsCache.reset(); +// AZ::SystemTickBus::Handler::BusDisconnect(); +// +// } +// +// m_isUpgradingSingleGraph = false; +// +// if (m_assetsToUpgrade.empty()) +// { +// m_ui->upgradeAllButton->setEnabled(false); +// } +// +// m_upgradeComplete = false; +// } +// +// if (!IsUpgrading() && m_state == ProcessState::Upgrade) +// { +// AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); +// // Make the backup +// if (errorMessage.empty()) +// { +// Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); +// QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); +// if (!items.isEmpty()) +// { +// for (auto* item : items) +// { +// int row = item->row(); +// AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); +// spinner->SetIsBusy(true); +// } +// } +// +// // Upgrade the graph +// UpgradeGraph(*m_inProgressAsset); +// } +// else +// { +// Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); +// GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); +// } +// +// } +// break; +// } +// default: +// break; +// } +// +// FlushLogs(); +// +// AZ::Data::AssetManager::Instance().DispatchEvents(); +// AZ::SystemTickBus::ExecuteQueuedEvents(); + } + + // Backup + + void View::OnUpgradeAllButtonPress() + { + m_state = ProcessState::Upgrade; + //m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + AZ::Interface::Get()->SetIsUpgrading(true); + AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); + m_inProgressAsset = m_assetsToUpgrade.begin(); + AZ::SystemTickBus::Handler::BusConnect(); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + m_keepEditorAlive = AZStd::make_unique(); + } + + AZStd::string View::BackupGraph(const AZ::Data::Asset& asset) + { + if (!m_ui->makeBackupCheckbox->isChecked()) + { + // considered a success + return ""; + } + + QDateTime theTime = QDateTime::currentDateTime(); + QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); + + AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); + char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); + backupPath = backupPathCStr; + + if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) + { + if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); + return "Failed to create backup folder"; } } - break; - case ProcessState::Upgrade: - { - AZStd::lock_guard lock(m_mutex); - if (m_upgradeComplete) + AZStd::string devRoot = "@devroot@"; + AZStd::string devAssets = "@devassets@"; + + char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); + + char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); + + AZStd::string relativePath = devAssetsCStr; + AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); + if (relativePath.starts_with("/")) { - ++m_upgradeAssetIndex; - m_inProgress = false; - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - - if (m_scriptCanvasEntity) - { - m_scriptCanvasEntity->Deactivate(); - m_scriptCanvasEntity = nullptr; - } - - GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); - - if (!m_isUpgradingSingleGraph) - { - if (m_inProgressAsset != m_assetsToUpgrade.end()) - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - } - - if (m_inProgressAsset == m_assetsToUpgrade.end()) - { - FinalizeUpgrade(); - } - } - else - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - m_inProgress = false; - m_state = ProcessState::Inactive; - m_settingsCache.reset(); - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - } - - m_isUpgradingSingleGraph = false; - - if (m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(false); - } - - m_upgradeComplete = false; + relativePath = relativePath.substr(1, relativePath.size() - 1); } - if (!IsUpgrading() && m_state == ProcessState::Upgrade) + AZStd::string sourceFilePath; + + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound{}; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); + if (sourceInfoFound) { - AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); - // Make the backup - if (errorMessage.empty()) - { - Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); - QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); - spinner->SetIsBusy(true); - } - } + AZStd::string assetPath; + AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - // Upgrade the graph - UpgradeGraph(*m_inProgressAsset); - } - else - { - Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); - GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); - } - - } - break; - } - default: - break; - } - - FlushLogs(); - - AZ::Data::AssetManager::Instance().DispatchEvents(); - AZ::SystemTickBus::ExecuteQueuedEvents(); - } - - // Backup - - void VersionExplorer::OnUpgradeAll() - { - m_state = ProcessState::Upgrade; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - AZ::Interface::Get()->SetIsUpgrading(true); - AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); - m_inProgressAsset = m_assetsToUpgrade.begin(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - AZ::SystemTickBus::Handler::BusConnect(); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - m_ui->progressBar->setValue(m_upgradeAssetIndex); - m_keepEditorAlive = AZStd::make_unique(); - } - - AZStd::string VersionExplorer::BackupGraph(const AZ::Data::Asset& asset) - { - if (!m_ui->makeBackupCheckbox->isChecked()) - { - // considered a success - return ""; - } - - QDateTime theTime = QDateTime::currentDateTime(); - QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); - - AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); - char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); - backupPath = backupPathCStr; - - if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) - { - if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); - return "Failed to create backup folder"; - } - } - - AZStd::string devRoot = "@devroot@"; - AZStd::string devAssets = "@devassets@"; - - char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); - - char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); - - AZStd::string relativePath = devAssetsCStr; - AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string sourceFilePath; - - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo; - bool sourceInfoFound{}; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); - if (sourceInfoFound) - { - AZStd::string assetPath; - AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - - sourceFilePath = assetPath; - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); - return "Failed to find source file"; - } - - devRoot = devRootCStr; - AzFramework::StringFunc::Path::Normalize(devRoot); - - relativePath = sourceFilePath; - AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AzFramework::StringFunc::Path::Normalize(relativePath); - AzFramework::StringFunc::Path::Normalize(backupPath); - - AZStd::string targetFilePath = backupPath; - targetFilePath += relativePath; - - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return "Failed to copy source file to backup location"; - } - - Log("VersionExplorer::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return ""; - } - - void VersionExplorer::UpgradeGraph(const AZ::Data::Asset& asset) - { - m_inProgress = true; - m_upgradeComplete = false; - Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); - m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); - m_scriptCanvasEntity = nullptr; - - UpgradeNotifications::Bus::Handler::BusConnect(); - - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" - , azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) - { - return; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "VersionExplorer::UpgradeGraph The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return; - } - - AZ::Entity* queryEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); - if (queryEntity) - { - if (queryEntity->GetState() == AZ::Entity::State::Active) - { - queryEntity->Deactivate(); - } - - scriptCanvasEntity = queryEntity; - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) - { - scriptCanvasEntity->Init(); - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) - { - scriptCanvasEntity->Activate(); - } - - AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - if (graphComponent) - { - m_scriptCanvasEntity = scriptCanvasEntity; - - graphComponent->UpgradeGraph - ( asset - , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_ui->verbose->isChecked()); - } - } - - AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); - } - - void VersionExplorer::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - if (!fullPathFound) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); - } - - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - this->OnSourceFileReleased(asset); - }); - streamer->QueueRequest(flushRequest); - } - - void VersionExplorer::OnSourceFileReleased(AZ::Data::Asset asset) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - m_tmpFileName.clear(); - AZStd::string tmpFileName; - // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. - // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. - if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); - return; - } - - bool tempSavedSucceeded = false; - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); - if (fileStream.IsOpen()) - { - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasEditor::ScriptCanvasAssetHandler handler; - tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); - } - - fileStream.Close(); - } - - // attempt to remove temporary file no matter what - m_tmpFileName = tmpFileName; - if (!tempSavedSucceeded) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); - return; - } - - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) - { - constexpr const size_t k_maxAttemps = 10; - - if (!info.IsReadOnly()) - { - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + sourceFilePath = assetPath; } else { - if (m_overwriteAll) + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "View::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); + return "Failed to find source file"; + } + + devRoot = devRootCStr; + AzFramework::StringFunc::Path::Normalize(devRoot); + + relativePath = sourceFilePath; + AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); + if (relativePath.starts_with("/")) + { + relativePath = relativePath.substr(1, relativePath.size() - 1); + } + + AzFramework::StringFunc::Path::Normalize(relativePath); + AzFramework::StringFunc::Path::Normalize(backupPath); + + AZStd::string targetFilePath = backupPath; + targetFilePath += relativePath; + + if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "View::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return "Failed to copy source file to backup location"; + } + + Log("View::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return ""; + } + + void View::UpgradeGraph(const AZ::Data::Asset& asset) + { + m_inProgress = true; + m_upgradeComplete = false; + Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); + m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); + m_scriptCanvasEntity = nullptr; + + UpgradeNotifications::Bus::Handler::BusConnect(); + + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "View::UpgradeGraph The Script Canvas asset must have a valid entity"); + if (!scriptCanvasEntity) + { + return; + } + + AZ::Entity* queryEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); + if (queryEntity) + { + if (queryEntity->GetState() == AZ::Entity::State::Active) + { + queryEntity->Deactivate(); + } + + scriptCanvasEntity = queryEntity; + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) + { + scriptCanvasEntity->Init(); + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) + { + scriptCanvasEntity->Activate(); + } + + AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + if (graphComponent) + { + m_scriptCanvasEntity = scriptCanvasEntity; + + graphComponent->UpgradeGraph + (asset + , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_ui->verbose->isChecked()); + } + } + + AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); + } + + void View::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + if (!fullPathFound) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); + } + + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + this->OnSourceFileReleased(asset); + }); + streamer->QueueRequest(flushRequest); + } + + void View::OnSourceFileReleased(AZ::Data::Asset asset) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + m_tmpFileName.clear(); + AZStd::string tmpFileName; + // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. + // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. + if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); + return; + } + + bool tempSavedSucceeded = false; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + if (fileStream.IsOpen()) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasEditor::ScriptCanvasAssetHandler handler; + tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); + } + + fileStream.Close(); + } + + // attempt to remove temporary file no matter what + m_tmpFileName = tmpFileName; + if (!tempSavedSucceeded) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); + return; + } + + using SCCommandBus = AzToolsFramework::SourceControlCommandBus; + SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, + [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + { + constexpr const size_t k_maxAttemps = 10; + + if (!info.IsReadOnly()) { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); } else { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) + if (m_overwriteAll) { AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); } - } - } - }); - } - - void VersionExplorer::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target - , size_t remainingAttempts) - { - VersionExplorerCpp::FileEventHandler fileEventHandler; - - if (remainingAttempts == 0) - { - // all attempts failed, give up - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); - GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); - } - else if (remainingAttempts == 2) - { - // before the final attempt, flush all caches - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); - streamer->SetRequestCompleteCallback(flushRequest - , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction( - [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - else - { - // the actual move attempt - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - m_tmpFileName.clear(); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - AZ::SystemTickBus::QueueFunction([this, asset]() + else { - GraphUpgradeComplete(asset, OperationResult::Success, ""); - }); - } - else + int result = QMessageBox::No; + if (!m_overwriteAll) + { + QMessageBox mb(QMessageBox::Warning, + QObject::tr("Failed to Save Upgraded File"), + QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), + QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); + + result = mb.exec(); + if (result == QMessageBox::YesToAll) + { + m_overwriteAll = true; + } + } + + if (result == QMessageBox::Yes || m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + } + } + }); + } + + void View::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target + , size_t remainingAttempts) + { + // ViewCpp::FileEventHandler fileEventHandler; + + if (remainingAttempts == 0) { + // all attempts failed, give up + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); + GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); + } + else if (remainingAttempts == 2) + { + // before the final attempt, flush all caches AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); + streamer->SetRequestCompleteCallback(flushRequest + , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) { // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); + AZ::SystemTickBus::QueueFunction( + [this, asset, remainingAttempts, source, target]() { PerformMove(asset, source, target, remainingAttempts - 1); }); }); streamer->QueueRequest(flushRequest); } - } - } - - void VersionExplorer::GraphUpgradeComplete - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - AZStd::lock_guard lock(m_mutex); - m_upgradeComplete = true; - m_upgradeResult = result; - m_upgradeMessage = message; - m_upgradeAsset = asset; - - if (!m_tmpFileName.empty()) - { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); - - if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) + else { - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); - } - } - - if (m_upgradeResult == OperationResult::Failure) - { - AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); - } - - m_tmpFileName.clear(); - } - - void VersionExplorer::GraphUpgradeCompleteUIUpdate - ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - QString text = asset.GetHint().c_str(); - QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); - - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); - QString assetName = asset.GetHint().c_str(); - - if (label->text().compare(assetName) == 0) + // the actual move attempt + auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); + if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) { - m_ui->tableWidget->removeCellWidget(row, ColumnAction); - m_ui->tableWidget->removeCellWidget(row, ColumnStatus); - - QToolButton* doneButton = new QToolButton(this); - doneButton->setToolTip("Upgrade complete"); - if (result == OperationResult::Success) + m_tmpFileName.clear(); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + // Bump the slice asset up in the asset processor's queue. + AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); + AZ::SystemTickBus::QueueFunction([this, asset]() { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); - } - else + GraphUpgradeComplete(asset, OperationResult::Success, ""); + }); + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); - doneButton->setToolTip(message.data()); - } - - m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); + // Continue saving. + AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); } } } - } - void VersionExplorer::FinalizeUpgrade() - { - Log("FinalizeUpgrade!"); - m_inProgress = false; - m_assetsToUpgrade.clear(); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(true); - m_keepEditorAlive.reset(); - m_ui->progressBar->setVisible(false); - - // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - if (assetsThatNeedManualInspection > 0) + void View::GraphUpgradeComplete + (const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) { - m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); - } - else - { - m_ui->spinner->SetText("Upgrade complete."); - } + AZStd::lock_guard lock(m_mutex); + m_upgradeComplete = true; + m_upgradeResult = result; + m_upgradeMessage = message; + m_upgradeAsset = asset; - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Interface::Get()->SetIsUpgrading(false); - m_settingsCache.reset(); - } - - // Scanning - - void VersionExplorer::OnScan() - { - m_assetsToUpgrade.clear(); - m_assetsToInspect.clear(); - m_ui->tableWidget->setRowCount(0); - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); - m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); - DoScan(); - } - - void VersionExplorer::DoScan() - { - m_state = ProcessState::Scan; - m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - - AZ::SystemTickBus::Handler::BusConnect(); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - if (!m_assetsToInspect.empty()) - { - m_discoveredAssets = m_assetsToInspect.size(); - m_failedAssets = 0; - m_inspectedAssets = 0; - m_currentAssetRowIndex = 0; - m_ui->progressFrame->setVisible(true); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); - m_ui->progressBar->setValue(0); - - m_ui->spinner->SetIsBusy(true); - m_ui->spinner->SetBusyIconSize(32); - - m_ui->scanButton->setEnabled(false); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(false); - - m_inspectingAsset = m_assetsToInspect.begin(); - m_keepEditorAlive = AZStd::make_unique(); - } - } - - void VersionExplorer::BackupComplete() - { - m_currentAssetRowIndex = 0; - m_ui->progressBar->setValue(0); - DoScan(); - } - - void VersionExplorer::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) - { - Log("InspectAsset: %s", asset.GetHint().c_str()); - AZ::Entity* scriptCanvasEntity = nullptr; - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - if (!scriptCanvasAsset) + if (!m_tmpFileName.empty()) { - Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); + + if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) + { + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); + } + } + + if (m_upgradeResult == OperationResult::Failure) + { + AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); + } + + m_tmpFileName.clear(); + } + + void View::GraphUpgradeCompleteUIUpdate + (const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) + { + QString text = asset.GetHint().c_str(); + QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); + + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); + QString assetName = asset.GetHint().c_str(); + + if (label->text().compare(assetName) == 0) + { + m_ui->tableWidget->removeCellWidget(row, ColumnAction); + m_ui->tableWidget->removeCellWidget(row, ColumnStatus); + + QToolButton* doneButton = new QToolButton(this); + doneButton->setToolTip("Upgrade complete"); + if (result == OperationResult::Success) + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); + } + else + { + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); + doneButton->setToolTip(message.data()); + } + + m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); + } + } + } + } + + void View::FinalizeUpgrade() + { + Log("FinalizeUpgrade!"); + m_inProgress = false; + m_assetsToUpgrade.clear(); + m_ui->upgradeAllButton->setEnabled(false); + m_ui->onlyShowOutdated->setEnabled(true); + m_keepEditorAlive.reset(); + m_ui->progressBar->setVisible(false); + + // Manual correction + size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); + if (assetsThatNeedManualInspection > 0) + { + m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); + } + else + { + m_ui->spinner->SetText("Upgrade complete."); + } + + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Interface::Get()->SetIsUpgrading(false); + //m_settingsCache.reset(); + } + + // Scanning + + void View::OnScanButtonPress() + { + ViewNotificationsBus::Broadcast(&ViewNotificationsTraits::ScanRequested); + +// m_assetsToUpgrade.clear(); +// m_assetsToInspect.clear(); +// m_ui->tableWidget->setRowCount(0); +// m_inspectedAssets = 0; +// m_currentAssetRowIndex = 0; +// IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); +// m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); +// DoScan(); + } + + void View::DoScan() + { +// m_state = ProcessState::Scan; +// m_settingsCache = AZStd::make_unique(); +// ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; +// ScriptCanvas::Grammar::g_printAbstractCodeModel = false; +// ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; +// +// AZ::SystemTickBus::Handler::BusConnect(); +// +// if (!m_assetsToInspect.empty()) +// { +// m_discoveredAssets = m_assetsToInspect.size(); +// m_failedAssets = 0; +// m_inspectedAssets = 0; +// m_currentAssetRowIndex = 0; +// m_ui->progressFrame->setVisible(true); +// m_ui->progressBar->setVisible(true); +// m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); +// m_ui->progressBar->setValue(0); +// +// m_ui->spinner->SetIsBusy(true); +// m_ui->spinner->SetBusyIconSize(32); +// +// m_ui->scanButton->setEnabled(false); +// m_ui->upgradeAllButton->setEnabled(false); +// m_ui->onlyShowOutdated->setEnabled(false); +// +// m_inspectingAsset = m_assetsToInspect.begin(); +// m_keepEditorAlive = AZStd::make_unique(); +// } + } + + void View::BackupComplete() + { + m_currentAssetRowIndex = 0; + m_ui->progressBar->setValue(0); + DoScan(); + } + + void View::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) + { + Log("InspectAsset: %s", asset.GetHint().c_str()); + AZ::Entity* scriptCanvasEntity = nullptr; + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + if (!scriptCanvasAsset) + { + Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + return; + } + + scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); + } + + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); + bool forceUpgrade = m_ui->forceUpgrade->isChecked(); + ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); + + + if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) + { + ScanComplete(asset); + Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); return; } - scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); - } + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); - bool forceUpgrade = m_ui->forceUpgrade->isChecked(); - ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); - - - if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) - { - ScanComplete(asset); - Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); - return; - } - - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); - - if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) - { - m_assetsToUpgrade.push_back(asset); - - AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); - spinner->SetBusyIconSize(16); - - QPushButton* rowGoToButton = new QPushButton(this); - rowGoToButton->setText("Upgrade"); - rowGoToButton->setEnabled(false); - - connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { - - AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { - // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda - UpgradeSingle(rowGoToButton, spinner, assetInfo); - }); - - AZ::SystemTickBus::ExecuteQueuedEvents(); - - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); - } - - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); - AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); - AZ::StringFunc::Path::Normalize(path); - - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - QByteArray assetNameUtf8 = asset.GetHint().c_str(); - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); - - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); - - QToolButton* browseButton = new QToolButton(this); - browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); - browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); - - QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); - connect(browseButton, &QPushButton::clicked, [absolutePath] { - AzQtComponents::ShowFileOnDesktop(absolutePath); - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); - ScanComplete(asset); - ++m_inspectedAssets; - ++m_currentAssetRowIndex; - } - - void VersionExplorer::UpgradeSingle - ( QPushButton* rowGoToButton - , AzQtComponents::StyledBusyLabel* spinner - , AZ::Data::AssetInfo assetInfo) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset - ( assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - - if (asset) - { - asset.BlockUntilLoadComplete(); - - if (asset.IsReady()) + if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) { - AZ::Interface::Get()->SetIsUpgrading(true); - m_isUpgradingSingleGraph = true; - m_logs.clear(); - m_ui->textEdit->clear(); - spinner->SetIsBusy(true); + m_assetsToUpgrade.push_back(asset); + + AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); + spinner->SetBusyIconSize(16); + + QPushButton* rowGoToButton = new QPushButton(this); + rowGoToButton->setText("Upgrade"); rowGoToButton->setEnabled(false); - m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() - , [asset](const UpgradeAssets::value_type& assetToUpgrade) - { - return assetToUpgrade.GetId() == asset.GetId(); + connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { + + AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { + // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda + UpgradeSingle(rowGoToButton, spinner, assetInfo); + }); + + AZ::SystemTickBus::ExecuteQueuedEvents(); + }); - m_state = ProcessState::Upgrade; - AZ::SystemTickBus::Handler::BusConnect(); - } + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); + } + + char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; + AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); + AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); + AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); + AZ::StringFunc::Path::Normalize(path); + + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; + QByteArray assetNameUtf8 = asset.GetHint().c_str(); + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); + + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + + QToolButton* browseButton = new QToolButton(this); + browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); + browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); + + QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); + connect(browseButton, &QPushButton::clicked, [absolutePath] { + AzQtComponents::ShowFileOnDesktop(absolutePath); + }); + + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); + ScanComplete(asset); + ++m_inspectedAssets; + ++m_currentAssetRowIndex; } - } - void VersionExplorer::ScanComplete(const AZ::Data::Asset& asset) - { - Log("ScanComplete: %s", asset.GetHint().c_str()); - m_inProgress = false; - m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - m_ui->scanButton->setEnabled(true); - - m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); - FlushLogs(); - - if (m_inspectingAsset == m_assetsToInspect.end()) + void View::UpgradeSingle + (QPushButton* rowGoToButton + , AzQtComponents::StyledBusyLabel* spinner + , AZ::Data::AssetInfo assetInfo) { - AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); + AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset + (assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); + + if (asset) + { + asset.BlockUntilLoadComplete(); + + if (asset.IsReady()) + { + AZ::Interface::Get()->SetIsUpgrading(true); + m_isUpgradingSingleGraph = true; + m_logs.clear(); + m_ui->textEdit->clear(); + spinner->SetIsBusy(true); + rowGoToButton->setEnabled(false); + + m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() + , [asset](const UpgradeAssets::value_type& assetToUpgrade) + { + return assetToUpgrade.GetId() == asset.GetId(); + }); + + m_state = ProcessState::Upgrade; + AZ::SystemTickBus::Handler::BusConnect(); + } + } + } + + void View::ScanComplete(const AZ::Data::Asset& asset) + { + Log("ScanComplete: %s", asset.GetHint().c_str()); + m_inProgress = false; + m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); + m_ui->scanButton->setEnabled(true); + + m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); + FlushLogs(); + + if (m_inspectingAsset == m_assetsToInspect.end()) + { + AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); + + if (!m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(true); + } + } + } + + void View::FinalizeScan() + { + Log("FinalizeScan()"); + + m_ui->spinner->SetIsBusy(false); + m_ui->onlyShowOutdated->setEnabled(true); + + // Enable all the Upgrade buttons + for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) + { + QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); + if (button) + { + button->setEnabled(true); + } + } + + QString spinnerText = QStringLiteral("Scan Complete"); + if (m_assetsToUpgrade.empty()) + { + spinnerText.append(" - No graphs require upgrade!"); + } + else + { + spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" + , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); + } + + + m_ui->spinner->SetText(spinnerText); + m_ui->progressBar->setVisible(false); if (!m_assetsToUpgrade.empty()) { m_ui->upgradeAllButton->setEnabled(true); } + + AZ::SystemTickBus::Handler::BusDisconnect(); + + m_keepEditorAlive.reset(); + //m_settingsCache.reset(); + m_state = ProcessState::Inactive; } - } - void VersionExplorer::FinalizeScan() - { - Log("FinalizeScan()"); - - m_ui->spinner->SetIsBusy(false); - m_ui->onlyShowOutdated->setEnabled(true); - - // Enable all the Upgrade buttons - for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) + void View::FlushLogs() { - QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); - if (button) + if (m_logs.empty()) { - button->setEnabled(true); + return; } + + const QTextCursor oldCursor = m_ui->textEdit->textCursor(); + QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); + + m_ui->textEdit->moveCursor(QTextCursor::End); + QTextCursor textCursor = m_ui->textEdit->textCursor(); + + while (!m_logs.empty()) + { + auto line = "\n" + m_logs.front(); + + m_logs.pop_front(); + + textCursor.insertText(line.c_str()); + } + + scrollBar->setValue(scrollBar->maximum()); + m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); + } - QString spinnerText = QStringLiteral("Scan Complete"); - if (m_assetsToUpgrade.empty()) + + void View::closeEvent(QCloseEvent* event) { - spinnerText.append(" - No graphs require upgrade!"); + m_keepEditorAlive.reset(); + + AzQtComponents::StyledDialog::closeEvent(event); } - else - { - spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" - , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); - } - - - m_ui->spinner->SetText(spinnerText); - m_ui->progressBar->setVisible(false); - - if (!m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(true); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); - - m_keepEditorAlive.reset(); - m_settingsCache.reset(); - m_state = ProcessState::Inactive; } - void VersionExplorer::FlushLogs() - { - if (m_logs.empty()) - { - return; - } - - const QTextCursor oldCursor = m_ui->textEdit->textCursor(); - QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); - - m_ui->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = m_ui->textEdit->textCursor(); - - while (!m_logs.empty()) - { - auto line = "\n" + m_logs.front(); - - m_logs.pop_front(); - - textCursor.insertText(line.c_str()); - } - - scrollBar->setValue(scrollBar->maximum()); - m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); - - } - - bool VersionExplorer::CaptureLogFromTraceBus(const char* window, const char* message) - { - if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) - { - return true; - } - - AZStd::string msg = message; - if (msg.ends_with("\n")) - { - msg = msg.substr(0, msg.size() - 1); - } - - m_logs.push_back(msg); - return m_ui->updateReportingOnly->isChecked(); - } - - bool VersionExplorer::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Error): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool VersionExplorer::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) - { - AZStd::string msg = AZStd::string::format("(Warning): %s", message); - return CaptureLogFromTraceBus(window, msg.c_str()); - } - - bool VersionExplorer::OnException(const char* message) - { - AZStd::string msg = AZStd::string::format("(Exception): %s", message); - return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); - } - - bool VersionExplorer::OnPrintf(const char* window, const char* message) - { - return CaptureLogFromTraceBus(window, message); - } - - void VersionExplorer::closeEvent(QCloseEvent* event) - { - m_keepEditorAlive.reset(); - - AzQtComponents::StyledDialog::closeEvent(event); - } - -#include +#include } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h index 7ce1920dbb..905074d17e 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h @@ -15,7 +15,6 @@ AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") AZ_POP_DISABLE_WARNING #include #include -#include #include #include #include @@ -23,11 +22,14 @@ AZ_POP_DISABLE_WARNING #include #endif +#include +#include + class QPushButton; namespace Ui { - class VersionExplorer; + class View; } namespace AzQtComponents @@ -37,140 +39,132 @@ namespace AzQtComponents namespace ScriptCanvasEditor { - //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow - //! the upgrade tool to work even if the editor is not in the foreground - class EditorKeepAlive + namespace VersionExplorer { - public: - EditorKeepAlive(); - ~EditorKeepAlive(); - - private: - int m_keepEditorActive; - ICVar* m_edKeepEditorActive; - }; - - //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog - class VersionExplorer - : public AzQtComponents::StyledDialog - , private AZ::SystemTickBus::Handler - , private UpgradeNotifications::Bus::Handler - , private AZ::Debug::TraceMessageBus::Handler - { - Q_OBJECT - - public: - AZ_CLASS_ALLOCATOR(VersionExplorer, AZ::SystemAllocator, 0); - - explicit VersionExplorer(QWidget* parent = nullptr); - ~VersionExplorer(); - - private: - - static constexpr int ColumnAsset = 0; - static constexpr int ColumnAction = 1; - static constexpr int ColumnBrowse = 2; - static constexpr int ColumnStatus = 3; - - void OnScan(); - void OnClose(); - - enum class ProcessState + //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow + //! the upgrade tool to work even if the editor is not in the foreground + class EditorKeepAlive { - Inactive, - Backup, - Scan, - Upgrade, - }; - ProcessState m_state = ProcessState::Inactive; + public: + EditorKeepAlive(); + ~EditorKeepAlive(); - void DoScan(); - void ScanComplete(const AZ::Data::Asset&); - - void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); - - void OnUpgradeAll(); - - // SystemTickBus::Handler - void OnSystemTick() override; - // - - // AZ::Debug::TranceMessageBus::Handler - bool OnException(const char* /*message*/) override; - bool OnPrintf(const char* /*window*/, const char* /*message*/) override; - bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; - // - - bool CaptureLogFromTraceBus(const char* window, const char* message); - - enum class OperationResult - { - Success, - Failure, + private: + int m_keepEditorActive; + ICVar* m_edKeepEditorActive; }; - void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); + //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog + //! Handles display change notifications, handles state change notifications, sends control requests + class View + : public AzQtComponents::StyledDialog + , private AZ::SystemTickBus::Handler + , private UpgradeNotifications::Bus::Handler + , private ViewRequestsBus::Handler + , private ModelNotificationsBus::Handler + { + Q_OBJECT - bool IsUpgrading() const; + public: + AZ_CLASS_ALLOCATOR(View, AZ::SystemAllocator, 0); - bool m_inProgress = false; - // scan fields - size_t m_currentAssetRowIndex = 0; - size_t m_inspectedAssets = 0; - size_t m_failedAssets = 0; - size_t m_discoveredAssets = 0; + explicit View(QWidget* parent = nullptr); + + private: - IUpgradeRequests::AssetList m_assetsToInspect; - IUpgradeRequests::AssetList::iterator m_inspectingAsset; - using UpgradeAssets = AZStd::vector>; - UpgradeAssets m_assetsToUpgrade; - UpgradeAssets::iterator m_inProgressAsset; + static constexpr int ColumnAsset = 0; + static constexpr int ColumnAction = 1; + static constexpr int ColumnBrowse = 2; + static constexpr int ColumnStatus = 3; - AZ::Data::Asset m_currentAsset; + void OnCloseButtonPress(); + void OnScanButtonPress(); + void OnUpgradeAllButtonPress(); - AZStd::unique_ptr m_ui; + enum class ProcessState + { + Inactive, + Backup, + Scan, + Upgrade, + }; + ProcessState m_state = ProcessState::Inactive; - AZStd::unique_ptr m_settingsCache; + void DoScan(); + void ScanComplete(const AZ::Data::Asset&); - // upgrade fields - AZStd::recursive_mutex m_mutex; - bool m_upgradeComplete = false; - AZ::Data::Asset m_upgradeAsset; - int m_upgradeAssetIndex = 0; - OperationResult m_upgradeResult; - AZStd::string m_upgradeMessage; - AZStd::string m_tmpFileName; + void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); - AZStd::unique_ptr m_keepEditorAlive; + // SystemTickBus::Handler + void OnSystemTick() override; - AZStd::deque m_logs; + enum class OperationResult + { + Success, + Failure, + }; - AZ::Entity* m_scriptCanvasEntity = nullptr; + void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); - bool m_isUpgradingSingleGraph = false; + bool IsUpgrading() const { return false; } - void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); + bool m_inProgress = false; + // scan fields + size_t m_currentAssetRowIndex = 0; + size_t m_inspectedAssets = 0; + size_t m_failedAssets = 0; + size_t m_discoveredAssets = 0; - void FlushLogs(); + IUpgradeRequests::AssetList m_assetsToInspect; + IUpgradeRequests::AssetList::iterator m_inspectingAsset; + using UpgradeAssets = AZStd::vector>; + UpgradeAssets m_assetsToUpgrade; + UpgradeAssets::iterator m_inProgressAsset; - void FinalizeUpgrade(); - void FinalizeScan(); + AZ::Data::Asset m_currentAsset; - void BackupComplete(); - AZStd::string BackupGraph(const AZ::Data::Asset&); - void UpgradeGraph(const AZ::Data::Asset&); + AZStd::unique_ptr m_ui; - void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); - void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; + + // upgrade fields + AZStd::recursive_mutex m_mutex; + bool m_upgradeComplete = false; + AZ::Data::Asset m_upgradeAsset; + int m_upgradeAssetIndex = 0; + OperationResult m_upgradeResult; + AZStd::string m_upgradeMessage; + AZStd::string m_tmpFileName; - void OnSourceFileReleased(AZ::Data::Asset asset); + AZStd::unique_ptr m_keepEditorAlive; - void closeEvent(QCloseEvent* event) override; + AZStd::deque m_logs; - bool m_overwriteAll = false; - void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); + AZ::Entity* m_scriptCanvasEntity = nullptr; - void Log(const char* format, ...); - }; + bool m_isUpgradingSingleGraph = false; + + void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); + + void FlushLogs(); + + void FinalizeUpgrade(); + void FinalizeScan(); + + void BackupComplete(); + AZStd::string BackupGraph(const AZ::Data::Asset&); + void UpgradeGraph(const AZ::Data::Asset&); + + void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); + void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; + + void OnSourceFileReleased(AZ::Data::Asset asset); + + void closeEvent(QCloseEvent* event) override; + + bool m_overwriteAll = false; + void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); + + void Log(const char* format, ...); + }; + } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui index 0cd67bcf22..f549c821d6 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui @@ -1,7 +1,7 @@ - VersionExplorer - + View + Qt::WindowModal diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h new file mode 100644 index 0000000000..7f36e8503d --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h @@ -0,0 +1,26 @@ +/* + * 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 + * + */ +#pragma once + +#include + +namespace ScriptCanvasEditor +{ + namespace VersionExplorer + { + class ViewRequestsTraits : public AZ::EBusTraits + { + public: + // flush logs, or add log text + // set progress update + virtual void ClearProgress() {} + virtual void SetInProgress() {} + }; + using ViewRequestsBus = AZ::EBus; + } +} diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake index dbffe99afd..eb914ae139 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake @@ -259,20 +259,24 @@ set(FILES Editor/View/Windows/ScriptCanvasContextMenus.cpp Editor/View/Windows/ScriptCanvasContextMenus.h Editor/View/Windows/ScriptCanvasEditorResources.qrc - Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h + Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp + Editor/View/Windows/Tools/UpgradeTool/FileSaver.h + Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp + Editor/View/Windows/Tools/UpgradeTool/Modifier.h + Editor/View/Windows/Tools/UpgradeTool/Model.cpp + Editor/View/Windows/Tools/UpgradeTool/Model.h + Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h + Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp + Editor/View/Windows/Tools/UpgradeTool/Scanner.h Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui - Editor/View/Windows/Tools/UpgradeTool/Scanner.h - Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp - Editor/View/Windows/Tools/UpgradeTool/Modifier.h - Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp - Editor/View/Windows/Tools/UpgradeTool/FileSaver.h - Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp - Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h - Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp - Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui - Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h + Editor/View/Windows/Tools/UpgradeTool/View.cpp + Editor/View/Windows/Tools/UpgradeTool/View.h + Editor/View/Windows/Tools/UpgradeTool/View.ui + Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp + Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h + Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h Editor/Framework/ScriptCanvasGraphUtilities.inl Editor/Framework/ScriptCanvasGraphUtilities.h Editor/Framework/ScriptCanvasTraceUtilities.h From fd717048945744f7c1afcea6815336bbeba6ccda Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:27:01 -0700 Subject: [PATCH 06/24] rename view files --> controller Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/{View.cpp => Controller.cpp} | 0 .../View/Windows/Tools/UpgradeTool/{View.h => Controller.h} | 0 Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/{View.cpp => Controller.cpp} (100%) rename Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/{View.h => Controller.h} (100%) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp similarity index 100% rename from Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.cpp rename to Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h similarity index 100% rename from Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.h rename to Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake index eb914ae139..1ce2b0c502 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake @@ -270,8 +270,8 @@ set(FILES Editor/View/Windows/Tools/UpgradeTool/Scanner.h Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui - Editor/View/Windows/Tools/UpgradeTool/View.cpp - Editor/View/Windows/Tools/UpgradeTool/View.h + Editor/View/Windows/Tools/UpgradeTool/Controller.cpp + Editor/View/Windows/Tools/UpgradeTool/Controller.h Editor/View/Windows/Tools/UpgradeTool/View.ui Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp From cbaa2fcff554ca27fb07b9229b6ea06537166f3e Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 10 Sep 2021 21:03:14 -0700 Subject: [PATCH 07/24] rename view --> controller Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../View/Windows/Tools/UpgradeTool/{View.ui => Controller.ui} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/{View.ui => Controller.ui} (100%) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui similarity index 100% rename from Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui rename to Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui From 1badb5a31f7b73b7b83247f6ba90c48949c088a6 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 13 Sep 2021 15:30:31 -0700 Subject: [PATCH 08/24] scan refactor is in a working state Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../ScriptCanvas/Bus/EditorScriptCanvasBus.h | 3 +- .../Code/Editor/SystemComponent.cpp | 107 +---- .../Code/Editor/SystemComponent.h | 69 +-- .../Code/Editor/View/Windows/MainWindow.cpp | 10 +- .../Code/Editor/View/Windows/MainWindow.h | 2 +- .../Windows/Tools/UpgradeTool/Controller.cpp | 409 +++++++++--------- .../Windows/Tools/UpgradeTool/Controller.h | 45 +- .../Windows/Tools/UpgradeTool/Controller.ui | 4 +- .../View/Windows/Tools/UpgradeTool/Model.cpp | 44 ++ .../View/Windows/Tools/UpgradeTool/Model.h | 26 +- .../Windows/Tools/UpgradeTool/ModelTraits.h | 23 +- .../Windows/Tools/UpgradeTool/Scanner.cpp | 94 ++++ .../View/Windows/Tools/UpgradeTool/Scanner.h | 20 + .../Windows/Tools/UpgradeTool/ViewTraits.h | 10 +- 14 files changed, 485 insertions(+), 381 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h index 4497968ffc..09869ba2eb 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h @@ -221,8 +221,7 @@ namespace ScriptCanvasEditor AZ_TYPE_INFO(IUpgradeRequests, "{D25318F2-4DDA-4E76-98CB-6D561BB6234D}"); using AssetList = AZStd::list; - virtual AssetList& GetAssetsToUpgrade() = 0; - + virtual void ClearGraphsThatNeedUpgrade() = 0; virtual void GraphNeedsManualUpgrade(const AZ::Data::AssetId&) = 0; virtual const AZStd::vector& GetGraphsThatNeedManualUpgrade() const = 0; diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp index 4b60fd357c..f901915fdb 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp @@ -6,46 +6,35 @@ * */ - -#include -#include -#include #include +#include +#include +#include +#include #include - #include - +#include #include +#include #include - -#include - +#include +#include #include - -#include #include #include -#include - +#include +#include +#include +#include +#include #include +#include +#include #include #include #include #include -#include -#include - -#include - -#include -#include - #include -#include -#include - -#include -#include namespace ScriptCanvasEditor { @@ -54,6 +43,7 @@ namespace ScriptCanvasEditor SystemComponent::SystemComponent() { AzToolsFramework::AssetSeedManagerRequests::Bus::Handler::BusConnect(); + m_versionExplorer = AZStd::make_unique(); } SystemComponent::~SystemComponent() @@ -61,7 +51,6 @@ namespace ScriptCanvasEditor AzToolsFramework::UnregisterViewPane(LyViewPane::ScriptCanvas); AzToolsFramework::EditorContextMenuBus::Handler::BusDisconnect(); AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AzToolsFramework::AssetSeedManagerRequests::Bus::Handler::BusDisconnect(); } @@ -141,17 +130,12 @@ namespace ScriptCanvasEditor { if (userSettings->m_showUpgradeDialog) { - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); } else { m_upgradeDisabled = true; } } - else - { - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - } } void SystemComponent::NotifyRegisterViews() @@ -172,7 +156,6 @@ namespace ScriptCanvasEditor AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); ScriptCanvasExecutionBus::Handler::BusDisconnect(); SystemRequestBus::Handler::BusDisconnect(); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); m_jobContext.reset(); m_jobManager.reset(); @@ -397,64 +380,6 @@ namespace ScriptCanvasEditor return reporter; } - void SystemComponent::OnCatalogLoaded(const char* /*catalogFile*/) - { - // Enumerate all ScriptCanvas assets - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, - nullptr, - [this](const AZ::Data::AssetId, const AZ::Data::AssetInfo& assetInfo) { - - if (assetInfo.m_assetType == azrtti_typeid()) - { - AddAssetToUpgrade(assetInfo); - } - }, - nullptr - ); - } - - void SystemComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) - { - if (IsUpgrading()) - { - return; - } - - auto assetInfo = ScriptCanvasEditor::AssetHelpers::GetAssetInfo(assetId); - AddAssetToUpgrade(assetInfo); - } - - void SystemComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& /*assetInfo*/) - { - if (IsUpgrading()) - { - return; - } - - AZStd::erase_if(m_assetsToConvert, [assetId](const AZ::Data::AssetInfo& assetToConvert) - { - return assetToConvert.m_assetId == assetId; - } - ); - } - - void SystemComponent::AddAssetToUpgrade(const AZ::Data::AssetInfo& assetInfo) - { - auto query = AZStd::find_if(m_assetsToConvert.begin(), m_assetsToConvert.end(), [assetInfo](const AZ::Data::AssetInfo& assetToConvert) - { - return assetToConvert.m_assetId == assetInfo.m_assetId; - } - ); - - if (query == m_assetsToConvert.end()) - { - if (assetInfo.m_assetType == azrtti_typeid()) - { - m_assetsToConvert.push_back(assetInfo); - } - } - } - AzToolsFramework::AssetSeedManagerRequests::AssetTypePairs SystemComponent::GetAssetTypeMapping() { return { diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h index ba850401d6..37d5962271 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h @@ -9,23 +9,20 @@ #pragma once -#include -#include -#include - #include -#include +#include +#include #include - +#include #include +#include #include #include +#include #include - -#include - -#include -#include +#include +#include +#include namespace ScriptCanvasEditor { @@ -36,9 +33,7 @@ namespace ScriptCanvasEditor , private AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler , private ScriptCanvasExecutionBus::Handler , private AZ::UserSettingsNotificationBus::Handler - , private AzFramework::AssetCatalogEventBus::Handler , private AZ::Data::AssetBus::MultiHandler - , private AZ::Interface::Registrar , private AzToolsFramework::AssetSeedManagerRequests::Bus::Handler , private AzToolsFramework::EditorContextMenuBus::Handler { @@ -96,74 +91,30 @@ namespace ScriptCanvasEditor void OnUserSettingsActivated() override; //////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - // AzFramework::AssetCatalogEventBus::Handler... - void OnCatalogLoaded(const char* /*catalogFile*/) override; - void OnCatalogAssetAdded(const AZ::Data::AssetId& /*assetId*/) override; - void OnCatalogAssetRemoved(const AZ::Data::AssetId& /*assetId*/, const AZ::Data::AssetInfo& /*assetInfo*/) override; - //////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// // AssetSeedManagerRequests::Bus::Handler... AzToolsFramework::AssetSeedManagerRequests::AssetTypePairs GetAssetTypeMapping() override; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - // IUpgradeRequests... - void ClearGraphsThatNeedUpgrade() - { - m_assetsThatNeedManualUpgrade.clear(); - } - - IUpgradeRequests::AssetList& GetAssetsToUpgrade() override - { - return m_assetsToConvert; - } - - void GraphNeedsManualUpgrade(const AZ::Data::AssetId& assetId) override - { - if (AZStd::find(m_assetsThatNeedManualUpgrade.begin(), m_assetsThatNeedManualUpgrade.end(), assetId) == m_assetsThatNeedManualUpgrade.end()) - { - m_assetsThatNeedManualUpgrade.push_back(assetId); - } - } - - const AZStd::vector& GetGraphsThatNeedManualUpgrade() const override - { - return m_assetsThatNeedManualUpgrade; - } - - bool IsUpgrading() override - { - return m_isUpgrading; - } - - void SetIsUpgrading(bool isUpgrading) override - { - m_isUpgrading = isUpgrading; - } - - //////////////////////////////////////////////////////////////////////// private: SystemComponent(const SystemComponent&) = delete; void FilterForScriptCanvasEnabledEntities(AzToolsFramework::EntityIdList& sourceList, AzToolsFramework::EntityIdList& targetList); void PopulateEditorCreatableTypes(); - void AddAssetToUpgrade(const AZ::Data::AssetInfo& assetInfo); - + AZStd::unique_ptr m_jobManager; AZStd::unique_ptr m_jobContext; + AZStd::unique_ptr m_versionExplorer; AZStd::unordered_set m_creatableTypes; AssetTracker m_assetTracker; - IUpgradeRequests::AssetList m_assetsToConvert; AZStd::vector m_assetsThatNeedManualUpgrade; bool m_isUpgrading = false; bool m_upgradeDisabled = false; - }; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 33a58c18a7..6c10726e13 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -134,7 +134,6 @@ #include #include #include -#include #include @@ -3436,9 +3435,14 @@ namespace ScriptCanvasEditor void MainWindow::RunUpgradeTool() { - auto versionExplorer = aznew VersionExplorer::View(this); + // \todo, restore this behavior, post modification step + + /* + auto versionExplorer = aznew VersionExplorer::Controller(this); versionExplorer->exec(); + + // Manual correction size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); @@ -3448,6 +3452,8 @@ namespace ScriptCanvasEditor UpgradeHelper* upgradeHelper = new UpgradeHelper(this); upgradeHelper->show(); } + */ + } void MainWindow::OnShowValidationErrors() diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index 54557c3691..1eeb2dadfb 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -51,7 +51,7 @@ #include -#include +#include #if SCRIPTCANVAS_EDITOR #include diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index bf407765e1..4b2d3d37b9 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -28,12 +28,14 @@ #include #include #include -#include -#include +#include #include #include #include +#include +#include + namespace ScriptCanvasEditor { namespace VersionExplorer @@ -60,33 +62,32 @@ namespace ScriptCanvasEditor } } - View::View(QWidget* parent) + Controller::Controller(QWidget* parent) : AzQtComponents::StyledDialog(parent) - , m_ui(new Ui::View()) + , m_view(new Ui::Controller()) { - m_ui->setupUi(this); - m_ui->tableWidget->horizontalHeader()->setVisible(false); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); - m_ui->tableWidget->setColumnWidth(3, 22); - m_ui->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - m_ui->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); - connect(m_ui->scanButton, &QPushButton::pressed, this, &View::OnScanButtonPress); - connect(m_ui->closeButton, &QPushButton::pressed, this, &View::OnCloseButtonPress); - connect(m_ui->upgradeAllButton, &QPushButton::pressed, this, &View::OnUpgradeAllButtonPress); - m_ui->progressBar->setValue(0); - m_ui->progressBar->setVisible(false); + m_view->setupUi(this); + m_view->tableWidget->horizontalHeader()->setVisible(false); + m_view->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + m_view->tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); + m_view->tableWidget->setColumnWidth(3, 22); + m_view->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + m_view->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); + connect(m_view->scanButton, &QPushButton::pressed, this, &Controller::OnScanButtonPress); + connect(m_view->closeButton, &QPushButton::pressed, this, &Controller::OnCloseButtonPress); + connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnUpgradeAllButtonPress); + m_view->progressBar->setValue(0); + m_view->progressBar->setVisible(false); - ViewRequestsBus::Handler::BusConnect(); ModelNotificationsBus::Handler::BusConnect(); // move to model, maybe m_keepEditorAlive = AZStd::make_unique(); } - void View::Log(const char* /*format*/, ...) + void Controller::Log(const char* /*format*/, ...) { -// if (m_ui->verbose->isChecked()) +// if (m_view->verbose->isChecked()) // { // char sBuffer[2048]; // va_list ArgList; @@ -99,12 +100,12 @@ namespace ScriptCanvasEditor // } } - void View::OnCloseButtonPress() + void Controller::OnCloseButtonPress() { reject(); } - void View::OnSystemTick() + void Controller::OnSystemTick() { // switch (m_state) // { @@ -125,10 +126,10 @@ namespace ScriptCanvasEditor // } // else // { -// m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); +// m_view->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); // QTableWidgetItem* rowName = new QTableWidgetItem // (tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); -// m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); +// m_view->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); // ++m_currentAssetRowIndex; // // Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); @@ -145,8 +146,8 @@ namespace ScriptCanvasEditor // { // ++m_upgradeAssetIndex; // m_inProgress = false; -// m_ui->progressBar->setVisible(true); -// m_ui->progressBar->setValue(m_upgradeAssetIndex); +// m_view->progressBar->setVisible(true); +// m_view->progressBar->setValue(m_upgradeAssetIndex); // // if (m_scriptCanvasEntity) // { @@ -182,7 +183,7 @@ namespace ScriptCanvasEditor // // if (m_assetsToUpgrade.empty()) // { -// m_ui->upgradeAllButton->setEnabled(false); +// m_view->upgradeAllButton->setEnabled(false); // } // // m_upgradeComplete = false; @@ -195,13 +196,13 @@ namespace ScriptCanvasEditor // if (errorMessage.empty()) // { // Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); -// QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); +// QList items = m_view->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); // if (!items.isEmpty()) // { // for (auto* item : items) // { // int row = item->row(); -// AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnStatus)); +// AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnStatus)); // spinner->SetIsBusy(true); // } // } @@ -230,7 +231,7 @@ namespace ScriptCanvasEditor // Backup - void View::OnUpgradeAllButtonPress() + void Controller::OnUpgradeAllButtonPress() { m_state = ProcessState::Upgrade; //m_settingsCache = AZStd::make_unique(); @@ -241,15 +242,15 @@ namespace ScriptCanvasEditor AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); m_inProgressAsset = m_assetsToUpgrade.begin(); AZ::SystemTickBus::Handler::BusConnect(); - m_ui->progressBar->setVisible(true); - m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - m_ui->progressBar->setValue(m_upgradeAssetIndex); + m_view->progressBar->setVisible(true); + m_view->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); + m_view->progressBar->setValue(m_upgradeAssetIndex); m_keepEditorAlive = AZStd::make_unique(); } - AZStd::string View::BackupGraph(const AZ::Data::Asset& asset) + AZStd::string Controller::BackupGraph(const AZ::Data::Asset& asset) { - if (!m_ui->makeBackupCheckbox->isChecked()) + if (!m_view->makeBackupCheckbox->isChecked()) { // considered a success return ""; @@ -303,7 +304,7 @@ namespace ScriptCanvasEditor } else { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "View::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Controller::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); return "Failed to find source file"; } @@ -325,20 +326,20 @@ namespace ScriptCanvasEditor if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "View::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Controller::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); return "Failed to copy source file to backup location"; } - Log("View::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + Log("Controller::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); return ""; } - void View::UpgradeGraph(const AZ::Data::Asset& asset) + void Controller::UpgradeGraph(const AZ::Data::Asset& asset) { m_inProgress = true; m_upgradeComplete = false; Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); - m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); + m_view->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); m_scriptCanvasEntity = nullptr; UpgradeNotifications::Bus::Handler::BusConnect(); @@ -355,7 +356,7 @@ namespace ScriptCanvasEditor } AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "View::UpgradeGraph The Script Canvas asset must have a valid entity"); + AZ_Assert(scriptCanvasEntity, "Controller::UpgradeGraph The Script Canvas asset must have a valid entity"); if (!scriptCanvasEntity) { return; @@ -393,15 +394,15 @@ namespace ScriptCanvasEditor graphComponent->UpgradeGraph (asset - , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_ui->verbose->isChecked()); + , m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_view->verbose->isChecked()); } } AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); } - void View::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) + void Controller::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) { AZStd::string relativePath, fullPath; AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); @@ -421,7 +422,7 @@ namespace ScriptCanvasEditor streamer->QueueRequest(flushRequest); } - void View::OnSourceFileReleased(AZ::Data::Asset asset) + void Controller::OnSourceFileReleased(AZ::Data::Asset asset) { AZStd::string relativePath, fullPath; AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); @@ -502,7 +503,7 @@ namespace ScriptCanvasEditor }); } - void View::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target + void Controller::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target , size_t remainingAttempts) { // ViewCpp::FileEventHandler fileEventHandler; @@ -559,7 +560,7 @@ namespace ScriptCanvasEditor } } - void View::GraphUpgradeComplete + void Controller::GraphUpgradeComplete (const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) { AZStd::lock_guard lock(m_mutex); @@ -587,24 +588,24 @@ namespace ScriptCanvasEditor m_tmpFileName.clear(); } - void View::GraphUpgradeCompleteUIUpdate + void Controller::GraphUpgradeCompleteUIUpdate (const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) { QString text = asset.GetHint().c_str(); - QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); + QList items = m_view->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); if (!items.isEmpty()) { for (auto* item : items) { int row = item->row(); - QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); + QTableWidgetItem* label = m_view->tableWidget->item(row, ColumnAsset); QString assetName = asset.GetHint().c_str(); if (label->text().compare(assetName) == 0) { - m_ui->tableWidget->removeCellWidget(row, ColumnAction); - m_ui->tableWidget->removeCellWidget(row, ColumnStatus); + m_view->tableWidget->removeCellWidget(row, ColumnAction); + m_view->tableWidget->removeCellWidget(row, ColumnStatus); QToolButton* doneButton = new QToolButton(this); doneButton->setToolTip("Upgrade complete"); @@ -618,31 +619,31 @@ namespace ScriptCanvasEditor doneButton->setToolTip(message.data()); } - m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); + m_view->tableWidget->setCellWidget(row, ColumnStatus, doneButton); } } } } - void View::FinalizeUpgrade() + void Controller::FinalizeUpgrade() { Log("FinalizeUpgrade!"); m_inProgress = false; m_assetsToUpgrade.clear(); - m_ui->upgradeAllButton->setEnabled(false); - m_ui->onlyShowOutdated->setEnabled(true); + m_view->upgradeAllButton->setEnabled(false); + m_view->onlyShowOutdated->setEnabled(true); m_keepEditorAlive.reset(); - m_ui->progressBar->setVisible(false); + m_view->progressBar->setVisible(false); // Manual correction size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); if (assetsThatNeedManualInspection > 0) { - m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); + m_view->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); } else { - m_ui->spinner->SetText("Upgrade complete."); + m_view->spinner->SetText("Upgrade complete."); } AZ::SystemTickBus::Handler::BusDisconnect(); @@ -650,126 +651,120 @@ namespace ScriptCanvasEditor //m_settingsCache.reset(); } - // Scanning - - void View::OnScanButtonPress() + void Controller::OnScanButtonPress() { - ViewNotificationsBus::Broadcast(&ViewNotificationsTraits::ScanRequested); - -// m_assetsToUpgrade.clear(); -// m_assetsToInspect.clear(); -// m_ui->tableWidget->setRowCount(0); -// m_inspectedAssets = 0; -// m_currentAssetRowIndex = 0; -// IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); -// m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); -// DoScan(); - } - - void View::DoScan() - { -// m_state = ProcessState::Scan; -// m_settingsCache = AZStd::make_unique(); -// ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; -// ScriptCanvas::Grammar::g_printAbstractCodeModel = false; -// ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; -// -// AZ::SystemTickBus::Handler::BusConnect(); -// -// if (!m_assetsToInspect.empty()) -// { -// m_discoveredAssets = m_assetsToInspect.size(); -// m_failedAssets = 0; -// m_inspectedAssets = 0; -// m_currentAssetRowIndex = 0; -// m_ui->progressFrame->setVisible(true); -// m_ui->progressBar->setVisible(true); -// m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); -// m_ui->progressBar->setValue(0); -// -// m_ui->spinner->SetIsBusy(true); -// m_ui->spinner->SetBusyIconSize(32); -// -// m_ui->scanButton->setEnabled(false); -// m_ui->upgradeAllButton->setEnabled(false); -// m_ui->onlyShowOutdated->setEnabled(false); -// -// m_inspectingAsset = m_assetsToInspect.begin(); -// m_keepEditorAlive = AZStd::make_unique(); -// } - } - - void View::BackupComplete() - { - m_currentAssetRowIndex = 0; - m_ui->progressBar->setValue(0); - DoScan(); - } - - void View::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) - { - Log("InspectAsset: %s", asset.GetHint().c_str()); - AZ::Entity* scriptCanvasEntity = nullptr; - if (asset.GetType() == azrtti_typeid()) + auto isUpToDate = [this](AZ::Data::Asset asset) { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - if (!scriptCanvasAsset) + Log("InspectAsset: %s", asset.GetHint().c_str()); + AZ::Entity* scriptCanvasEntity = nullptr; + + if (asset.GetType() == azrtti_typeid()) { - Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); - return; + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + if (!scriptCanvasAsset) + { + Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + return true; + } + + scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); } - scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + return !m_view->forceUpgrade->isChecked() && graphComponent->GetVersion().IsLatest(); + }; + + ScanConfiguration config; + config.reportFilteredGraphs = !m_view->onlyShowOutdated->isChecked(); + config.filter = isUpToDate; + + ModelRequestsBus::Broadcast(&ModelRequestsTraits::Scan, config); + } + + void Controller::OnScanBegin(size_t assetCount) + { + m_currentAssetRowIndex = 0; + m_view->tableWidget->setRowCount(0); + m_view->progressBar->setVisible(true); + m_view->progressBar->setRange(0, aznumeric_cast(assetCount)); + m_view->progressBar->setValue(0); + m_view->scanButton->setEnabled(false); + m_view->upgradeAllButton->setEnabled(false); + m_view->onlyShowOutdated->setEnabled(false); + } + + void Controller::OnScanComplete(const ScanResult& result) + { + Log("Full Scan Complete."); + + m_view->onlyShowOutdated->setEnabled(true); + + // Enable all the Upgrade buttons + for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) + { + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(true); + } } - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + QString spinnerText = QStringLiteral("Scan Complete"); + spinnerText.append(QString::asprintf(" - Discovered: %zu, Failed: %zu, Upgradeable: %zu, Up-to-date: %zu" + , result.m_catalogAssets.size() + , result.m_loadErrors.size() + , result.m_unfiltered.size() + , result.m_filteredAssets.size())); - bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); - bool forceUpgrade = m_ui->forceUpgrade->isChecked(); - ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); + m_view->spinner->SetText(spinnerText); + m_view->progressBar->setVisible(false); - - if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) + if (!result.m_unfiltered.empty()) { - ScanComplete(asset); - Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); - return; + m_view->upgradeAllButton->setEnabled(true); } - m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); - QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); - m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + m_keepEditorAlive.reset(); + } - if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) + void Controller::OnScanFilteredGraph(const AZ::Data::AssetInfo& info) + { + OnScannedGraph(info, Filtered::Yes); + } + + void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, Filtered filtered) + { + m_view->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str())); + m_view->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + + if (filtered == Filtered::No) { - m_assetsToUpgrade.push_back(asset); - - AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); - spinner->SetBusyIconSize(16); - QPushButton* rowGoToButton = new QPushButton(this); rowGoToButton->setText("Upgrade"); rowGoToButton->setEnabled(false); + AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); + spinner->SetBusyIconSize(16); +// +// connect(rowGoToButton, &QPushButton::clicked, [this, rowGoToButton, assetInfo] { +// +// // request upgrade of a single graph +// // AZ::SystemTickBus::QueueFunction([this, rowGoToButton, assetInfo]() { +// // // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda +// // UpgradeSingle(rowGoToButton, spinner, assetInfo); +// // }); +// // +// // AZ::SystemTickBus::ExecuteQueuedEvents(); +// +// }); - connect(rowGoToButton, &QPushButton::clicked, [this, spinner, rowGoToButton, assetInfo] { - - AZ::SystemTickBus::QueueFunction([this, rowGoToButton, spinner, assetInfo]() { - // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda - UpgradeSingle(rowGoToButton, spinner, assetInfo); - }); - - AZ::SystemTickBus::ExecuteQueuedEvents(); - - }); - - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); + m_view->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); + m_view->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); } char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); + AZStd::string path = AZStd::string::format("@devroot@/%s", assetInfo.m_relativePath.c_str()); AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); AZ::StringFunc::Path::Normalize(path); @@ -777,10 +772,17 @@ namespace ScriptCanvasEditor bool result = false; AZ::Data::AssetInfo info; AZStd::string watchFolder; - QByteArray assetNameUtf8 = asset.GetHint().c_str(); - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); - - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + QByteArray assetNameUtf8 = assetInfo.m_relativePath.c_str(); + AzToolsFramework::AssetSystemRequestBus::BroadcastResult + ( result + , &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath + , assetNameUtf8 + , info + , watchFolder); + AZ_Error + ( ScriptCanvas::k_VersionExplorerWindow.data() + , result + , "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); QToolButton* browseButton = new QToolButton(this); browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); @@ -791,14 +793,40 @@ namespace ScriptCanvasEditor AzQtComponents::ShowFileOnDesktop(absolutePath); }); - m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); - ScanComplete(asset); - ++m_inspectedAssets; - ++m_currentAssetRowIndex; + m_view->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); + OnScannedGraphResult(assetInfo); } - void View::UpgradeSingle - (QPushButton* rowGoToButton + void Controller::OnScannedGraphResult(const AZ::Data::AssetInfo& info) + { + m_view->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); + ++m_currentAssetRowIndex; + Log("ScanComplete: %s", info.m_relativePath.c_str()); + FlushLogs(); + } + + void Controller::OnScanLoadFailure(const AZ::Data::AssetInfo& info) + { + m_view->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + QTableWidgetItem* rowName = new QTableWidgetItem + (tr(AZStd::string::format("Load Error: %s", info.m_relativePath.c_str()).c_str())); + m_view->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + OnScannedGraphResult(info); + } + + void Controller::OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) + { + OnScannedGraph(info, Filtered::No); + } + + void Controller::BackupComplete() + { + m_currentAssetRowIndex = 0; + m_view->progressBar->setValue(0); + } + + void Controller::UpgradeSingle + ( QPushButton* rowGoToButton , AzQtComponents::StyledBusyLabel* spinner , AZ::Data::AssetInfo assetInfo) { @@ -814,7 +842,7 @@ namespace ScriptCanvasEditor AZ::Interface::Get()->SetIsUpgrading(true); m_isUpgradingSingleGraph = true; m_logs.clear(); - m_ui->textEdit->clear(); + m_view->textEdit->clear(); spinner->SetIsBusy(true); rowGoToButton->setEnabled(false); @@ -830,38 +858,37 @@ namespace ScriptCanvasEditor } } - void View::ScanComplete(const AZ::Data::Asset& asset) + void Controller::ScanComplete(const AZ::Data::Asset& asset) { Log("ScanComplete: %s", asset.GetHint().c_str()); m_inProgress = false; - m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - m_ui->scanButton->setEnabled(true); + m_view->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); + m_view->scanButton->setEnabled(true); m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); - FlushLogs(); - + if (m_inspectingAsset == m_assetsToInspect.end()) { AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); if (!m_assetsToUpgrade.empty()) { - m_ui->upgradeAllButton->setEnabled(true); + m_view->upgradeAllButton->setEnabled(true); } } } - void View::FinalizeScan() + void Controller::FinalizeScan() { Log("FinalizeScan()"); - m_ui->spinner->SetIsBusy(false); - m_ui->onlyShowOutdated->setEnabled(true); + m_view->spinner->SetIsBusy(false); + m_view->onlyShowOutdated->setEnabled(true); // Enable all the Upgrade buttons - for (int row = 0; row < m_ui->tableWidget->rowCount(); ++row) + for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) { - QPushButton* button = qobject_cast(m_ui->tableWidget->cellWidget(row, ColumnAction)); + QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction)); if (button) { button->setEnabled(true); @@ -880,12 +907,12 @@ namespace ScriptCanvasEditor } - m_ui->spinner->SetText(spinnerText); - m_ui->progressBar->setVisible(false); + m_view->spinner->SetText(spinnerText); + m_view->progressBar->setVisible(false); if (!m_assetsToUpgrade.empty()) { - m_ui->upgradeAllButton->setEnabled(true); + m_view->upgradeAllButton->setEnabled(true); } AZ::SystemTickBus::Handler::BusDisconnect(); @@ -895,18 +922,18 @@ namespace ScriptCanvasEditor m_state = ProcessState::Inactive; } - void View::FlushLogs() + void Controller::FlushLogs() { if (m_logs.empty()) { return; } - const QTextCursor oldCursor = m_ui->textEdit->textCursor(); - QScrollBar* scrollBar = m_ui->textEdit->verticalScrollBar(); + const QTextCursor oldCursor = m_view->textEdit->textCursor(); + QScrollBar* scrollBar = m_view->textEdit->verticalScrollBar(); - m_ui->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = m_ui->textEdit->textCursor(); + m_view->textEdit->moveCursor(QTextCursor::End); + QTextCursor textCursor = m_view->textEdit->textCursor(); while (!m_logs.empty()) { @@ -918,19 +945,15 @@ namespace ScriptCanvasEditor } scrollBar->setValue(scrollBar->maximum()); - m_ui->textEdit->moveCursor(QTextCursor::StartOfLine); + m_view->textEdit->moveCursor(QTextCursor::StartOfLine); } - - void View::closeEvent(QCloseEvent* event) + void Controller::closeEvent(QCloseEvent* event) { m_keepEditorAlive.reset(); AzQtComponents::StyledDialog::closeEvent(event); } } - -#include - } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index 905074d17e..85459b4d46 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -9,27 +9,26 @@ #pragma once #if !defined(Q_MOC_RUN) -#include -AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") -#include -AZ_POP_DISABLE_WARNING #include #include +#include #include +#include +#include #include #include #include #include +AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") +#include +AZ_POP_DISABLE_WARNING #endif -#include -#include - class QPushButton; namespace Ui { - class View; + class Controller; } namespace AzQtComponents @@ -56,29 +55,41 @@ namespace ScriptCanvasEditor //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog //! Handles display change notifications, handles state change notifications, sends control requests - class View + class Controller : public AzQtComponents::StyledDialog , private AZ::SystemTickBus::Handler , private UpgradeNotifications::Bus::Handler - , private ViewRequestsBus::Handler , private ModelNotificationsBus::Handler { Q_OBJECT public: - AZ_CLASS_ALLOCATOR(View, AZ::SystemAllocator, 0); + AZ_CLASS_ALLOCATOR(Controller, AZ::SystemAllocator, 0); - explicit View(QWidget* parent = nullptr); + explicit Controller(QWidget* parent = nullptr); private: - static constexpr int ColumnAsset = 0; static constexpr int ColumnAction = 1; static constexpr int ColumnBrowse = 2; static constexpr int ColumnStatus = 3; void OnCloseButtonPress(); + void OnScanBegin(size_t assetCount) override; void OnScanButtonPress(); + void OnScanComplete(const ScanResult& result) override; + void OnScanFilteredGraph(const AZ::Data::AssetInfo& info) override; + void OnScanLoadFailure(const AZ::Data::AssetInfo& info) override; + void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) override; + enum Filtered + { + No, + Yes + }; + void OnScannedGraph(const AZ::Data::AssetInfo& info, Filtered filtered); + void OnScannedGraphResult(const AZ::Data::AssetInfo& info); + + void OnUpgradeAllButtonPress(); enum class ProcessState @@ -90,11 +101,8 @@ namespace ScriptCanvasEditor }; ProcessState m_state = ProcessState::Inactive; - void DoScan(); void ScanComplete(const AZ::Data::Asset&); - void InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo); - // SystemTickBus::Handler void OnSystemTick() override; @@ -123,9 +131,8 @@ namespace ScriptCanvasEditor AZ::Data::Asset m_currentAsset; - AZStd::unique_ptr m_ui; - - + AZStd::unique_ptr m_view; + // upgrade fields AZStd::recursive_mutex m_mutex; bool m_upgradeComplete = false; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui index f549c821d6..fdeb701f33 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui @@ -1,7 +1,7 @@ - View - + Controller + Qt::WindowModal diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp index 710d6863f5..8d5aa62674 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp @@ -6,7 +6,10 @@ * */ +#include #include +#include +#include namespace ModifierCpp { @@ -17,9 +20,50 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + Model::Model() + { + ModelRequestsBus::Handler::BusConnect(); + } + + void Model::CacheSettings() + { + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + } + const AZStd::vector* Model::GetLogs() { return &m_log.GetEntries(); } + + bool Model::IsWorking() const + { + return m_state != State::Idle; + } + + void Model::OnScanComplete() + { + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanComplete, m_scanner->GetResult()); + m_state = State::Idle; + } + + void Model::Scan(const ScanConfiguration& config) + { + if (IsWorking()) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Explorer is already working"); + return; + } + + m_state = State::Scanning; + m_scanner = AZStd::make_unique(config, [this](){ OnScanComplete(); }); + } + + void Model::RestoreSettings() + { + m_settingsCache.reset(); + } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h index 44da70e85c..407074fa94 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h @@ -7,9 +7,13 @@ */ #pragma once -#include + +#include #include +#include +#include #include +#include namespace ScriptCanvasEditor { @@ -22,12 +26,30 @@ namespace ScriptCanvasEditor public: AZ_CLASS_ALLOCATOR(Model, AZ::SystemAllocator, 0); + Model(); + const AZStd::vector* GetLogs(); + void Scan(const ScanConfiguration& config) override; private: - Log m_log; + enum class State + { + Idle, + Scanning, + Modifying, + }; + State m_state = State::Idle; + Log m_log; + + AZStd::unique_ptr m_modifier; + AZStd::unique_ptr m_scanner; AZStd::unique_ptr m_settingsCache; + + void CacheSettings(); + bool IsWorking() const; + void OnScanComplete(); + void RestoreSettings(); }; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index e66cdac13e..11a956c555 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -8,23 +8,44 @@ #pragma once #include +#include namespace ScriptCanvasEditor { namespace VersionExplorer { + struct ScanConfiguration + { + AZStd::function)> filter; + bool reportFilteredGraphs = false; + }; + class ModelRequestsTraits : public AZ::EBusTraits { public: - virtual const AZStd::vector* GetLogs(); + virtual const AZStd::vector* GetLogs() = 0; + virtual void Scan(const ScanConfiguration& filter) = 0; }; using ModelRequestsBus = AZ::EBus; + struct ScanResult + { + AZStd::vector m_catalogAssets; + AZStd::vector m_unfiltered; + AZStd::vector m_filteredAssets; + AZStd::vector m_loadErrors; + }; + class ModelNotificationsTraits : public AZ::EBusTraits { public: + virtual void OnScanBegin(size_t assetCount) = 0; + virtual void OnScanComplete(const ScanResult& result) = 0; + virtual void OnScanFilteredGraph(const AZ::Data::AssetInfo& info) = 0; + virtual void OnScanLoadFailure(const AZ::Data::AssetInfo& info) = 0; + virtual void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) = 0; }; using ModelNotificationsBus = AZ::EBus; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp index f74c27004b..09574883b6 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace ScannerCpp { @@ -17,6 +18,99 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + Scanner::Scanner(const ScanConfiguration& config, AZStd::function onComplete) + : m_config(config) + , m_onComplete(onComplete) + { + AZ::Data::AssetCatalogRequestBus::Broadcast + ( &AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets + , nullptr + , [this](const AZ::Data::AssetId, const AZ::Data::AssetInfo& assetInfo) + { + if (assetInfo.m_assetType == azrtti_typeid()) + { + m_result.m_catalogAssets.push_back(assetInfo); + } + } + , nullptr); + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanBegin, m_result.m_catalogAssets.size()); + AZ::SystemTickBus::Handler::BusConnect(); + } + + void Scanner::FilterAsset(AZ::Data::Asset asset) + { + if (m_config.filter && m_config.filter(asset)) + { + m_result.m_filteredAssets.push_back(GetCurrentAsset()); + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanFilteredGraph, GetCurrentAsset()); + } + else + { + m_result.m_unfiltered.push_back(GetCurrentAsset()); + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanUnFilteredGraph, GetCurrentAsset()); + } + } + + const AZ::Data::AssetInfo& Scanner::GetCurrentAsset() const + { + return m_result.m_catalogAssets[m_catalogAssetIndex]; + } + + const ScanResult& Scanner::GetResult() const + { + return m_result; + } + + AZ::Data::Asset Scanner::LoadAsset() + { + AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset + ( GetCurrentAsset().m_assetId + , azrtti_typeid() + , AZ::Data::AssetLoadBehavior::PreLoad); + + // Log("Scan: Loading: %s ", m_catalogAssets[m_catalogAssetIndex].GetHint().c_str()); + asset.BlockUntilLoadComplete(); + + if (asset.IsReady()) + { + return asset; + } + else + { + return {}; + } + } + + void Scanner::OnSystemTick() + { + if (m_catalogAssetIndex == m_result.m_catalogAssets.size()) + { + AZ::SystemTickBus::Handler::BusConnect(); + if (m_onComplete) + { + m_onComplete(); + } + } + else + { + if (auto asset = LoadAsset()) + { + FilterAsset(asset); + } + else + { + m_result.m_loadErrors.push_back(GetCurrentAsset()); + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanLoadFailure, GetCurrentAsset()); + } + + ++m_catalogAssetIndex; + } + } + + ScanResult&& Scanner::TakeResult() + { + return AZStd::move(m_result); + } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h index 19642a07f1..8b4dd69c82 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h @@ -9,15 +9,35 @@ #pragma once #include +#include +#include namespace ScriptCanvasEditor { namespace VersionExplorer { class Scanner + : private AZ::SystemTickBus::Handler { public: AZ_CLASS_ALLOCATOR(Scanner, AZ::SystemAllocator, 0); + + Scanner(const ScanConfiguration& config, AZStd::function onComplete); + + const ScanResult& GetResult() const; + + ScanResult&& TakeResult(); + + private: + size_t m_catalogAssetIndex = 0; + AZStd::function m_onComplete; + ScanConfiguration m_config; + ScanResult m_result; + + void FilterAsset(AZ::Data::Asset); + const AZ::Data::AssetInfo& GetCurrentAsset() const; + AZ::Data::Asset LoadAsset(); + void OnSystemTick() override; }; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h index 7f36e8503d..cf49072230 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h @@ -13,14 +13,6 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { - class ViewRequestsTraits : public AZ::EBusTraits - { - public: - // flush logs, or add log text - // set progress update - virtual void ClearProgress() {} - virtual void SetInProgress() {} - }; - using ViewRequestsBus = AZ::EBus; + } } From cb12d318217e2616dc97d3e66f62af6221b75ac8 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:01:49 -0700 Subject: [PATCH 09/24] Modifier step WIP Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/Controller.cpp | 826 +++--------------- .../Windows/Tools/UpgradeTool/Controller.h | 119 +-- .../Windows/Tools/UpgradeTool/LogTraits.h | 32 + .../View/Windows/Tools/UpgradeTool/Model.cpp | 77 +- .../View/Windows/Tools/UpgradeTool/Model.h | 22 +- .../Windows/Tools/UpgradeTool/ModelTraits.h | 18 +- .../Windows/Tools/UpgradeTool/Modifier.cpp | 13 + .../View/Windows/Tools/UpgradeTool/Modifier.h | 16 + .../Windows/Tools/UpgradeTool/Scanner.cpp | 16 +- .../Tools/UpgradeTool/VersionExplorerLog.cpp | 32 +- .../Tools/UpgradeTool/VersionExplorerLog.h | 13 +- .../Windows/Tools/UpgradeTool/ViewTraits.h | 18 - .../Code/scriptcanvasgem_editor_files.cmake | 14 +- 13 files changed, 335 insertions(+), 881 deletions(-) create mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h delete mode 100644 Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 4b2d3d37b9..44d6f2e738 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -40,28 +41,6 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { - EditorKeepAlive::EditorKeepAlive() - { - ISystem* system = nullptr; - CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - - m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - - if (m_edKeepEditorActive) - { - m_keepEditorActive = m_edKeepEditorActive->GetIVal(); - m_edKeepEditorActive->Set(1); - } - } - - EditorKeepAlive::~EditorKeepAlive() - { - if (m_edKeepEditorActive) - { - m_edKeepEditorActive->Set(m_keepEditorActive); - } - } - Controller::Controller(QWidget* parent) : AzQtComponents::StyledDialog(parent) , m_view(new Ui::Controller()) @@ -80,24 +59,32 @@ namespace ScriptCanvasEditor m_view->progressBar->setVisible(false); ModelNotificationsBus::Handler::BusConnect(); - - // move to model, maybe - m_keepEditorAlive = AZStd::make_unique(); } - void Controller::Log(const char* /*format*/, ...) + void Controller::AddLogEntries() { -// if (m_view->verbose->isChecked()) -// { -// char sBuffer[2048]; -// va_list ArgList; -// va_start(ArgList, format); -// azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); -// sBuffer[sizeof(sBuffer) - 1] = '\0'; -// va_end(ArgList); -// -// AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); -// } + const AZStd::vector* logs = nullptr; + LogBus::BroadcastResult(logs, &LogTraits::GetEntries); + if (!logs || logs->empty()) + { + return; + } + + const QTextCursor oldCursor = m_view->textEdit->textCursor(); + QScrollBar* scrollBar = m_view->textEdit->verticalScrollBar(); + + m_view->textEdit->moveCursor(QTextCursor::End); + QTextCursor textCursor = m_view->textEdit->textCursor(); + + for (auto& entry : *logs) + { + auto line = "\n" + entry; + textCursor.insertText(line.c_str()); + } + + scrollBar->setValue(scrollBar->maximum()); + m_view->textEdit->moveCursor(QTextCursor::StartOfLine); + LogBus::Broadcast(&LogTraits::Clear); } void Controller::OnCloseButtonPress() @@ -105,557 +92,10 @@ namespace ScriptCanvasEditor reject(); } - void Controller::OnSystemTick() - { -// switch (m_state) -// { -// case ProcessState::Scan: -// -// if (!m_inProgress && m_inspectingAsset != m_assetsToInspect.end()) -// { -// m_inProgress = true; -// AZ::Data::AssetInfo& assetToUpgrade = *m_inspectingAsset; -// m_currentAsset = AZ::Data::AssetManager::Instance().GetAsset(assetToUpgrade.m_assetId, assetToUpgrade.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); -// Log("SystemTick::ProcessState::Scan: %s pre-blocking load hint", m_currentAsset.GetHint().c_str()); -// m_currentAsset.BlockUntilLoadComplete(); -// if (m_currentAsset.IsReady()) -// { -// // The asset is ready, grab its info -// m_inProgress = true; -// InspectAsset(m_currentAsset, assetToUpgrade); -// } -// else -// { -// m_view->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); -// QTableWidgetItem* rowName = new QTableWidgetItem -// (tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); -// m_view->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); -// ++m_currentAssetRowIndex; -// -// Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); -// ++m_failedAssets; -// ScanComplete(m_currentAsset); -// } -// } -// break; -// -// case ProcessState::Upgrade: -// { -// AZStd::lock_guard lock(m_mutex); -// if (m_upgradeComplete) -// { -// ++m_upgradeAssetIndex; -// m_inProgress = false; -// m_view->progressBar->setVisible(true); -// m_view->progressBar->setValue(m_upgradeAssetIndex); -// -// if (m_scriptCanvasEntity) -// { -// m_scriptCanvasEntity->Deactivate(); -// m_scriptCanvasEntity = nullptr; -// } -// -// GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); -// -// if (!m_isUpgradingSingleGraph) -// { -// if (m_inProgressAsset != m_assetsToUpgrade.end()) -// { -// m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); -// } -// -// if (m_inProgressAsset == m_assetsToUpgrade.end()) -// { -// FinalizeUpgrade(); -// } -// } -// else -// { -// m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); -// m_inProgress = false; -// m_state = ProcessState::Inactive; -// // m_settingsCache.reset(); -// AZ::SystemTickBus::Handler::BusDisconnect(); -// -// } -// -// m_isUpgradingSingleGraph = false; -// -// if (m_assetsToUpgrade.empty()) -// { -// m_view->upgradeAllButton->setEnabled(false); -// } -// -// m_upgradeComplete = false; -// } -// -// if (!IsUpgrading() && m_state == ProcessState::Upgrade) -// { -// AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); -// // Make the backup -// if (errorMessage.empty()) -// { -// Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); -// QList items = m_view->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); -// if (!items.isEmpty()) -// { -// for (auto* item : items) -// { -// int row = item->row(); -// AzQtComponents::StyledBusyLabel* spinner = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnStatus)); -// spinner->SetIsBusy(true); -// } -// } -// -// // Upgrade the graph -// UpgradeGraph(*m_inProgressAsset); -// } -// else -// { -// Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); -// GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); -// } -// -// } -// break; -// } -// default: -// break; -// } -// -// FlushLogs(); -// -// AZ::Data::AssetManager::Instance().DispatchEvents(); -// AZ::SystemTickBus::ExecuteQueuedEvents(); - } - - // Backup - - void Controller::OnUpgradeAllButtonPress() - { - m_state = ProcessState::Upgrade; - //m_settingsCache = AZStd::make_unique(); - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - ScriptCanvas::Grammar::g_printAbstractCodeModel = false; - ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; - AZ::Interface::Get()->SetIsUpgrading(true); - AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); - m_inProgressAsset = m_assetsToUpgrade.begin(); - AZ::SystemTickBus::Handler::BusConnect(); - m_view->progressBar->setVisible(true); - m_view->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); - m_view->progressBar->setValue(m_upgradeAssetIndex); - m_keepEditorAlive = AZStd::make_unique(); - } - - AZStd::string Controller::BackupGraph(const AZ::Data::Asset& asset) - { - if (!m_view->makeBackupCheckbox->isChecked()) - { - // considered a success - return ""; - } - - QDateTime theTime = QDateTime::currentDateTime(); - QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); - - AZStd::string backupPath = AZStd::string::format("@devroot@/ScriptCanvas_BACKUP/%s", subFolder.toUtf8().data()); - char backupPathCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(backupPath.c_str(), backupPathCStr, AZ_MAX_PATH_LEN); - backupPath = backupPathCStr; - - if (!AZ::IO::FileIOBase::GetInstance()->Exists(backupPath.c_str())) - { - if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); - return "Failed to create backup folder"; - } - } - - AZStd::string devRoot = "@devroot@"; - AZStd::string devAssets = "@devassets@"; - - char devRootCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devRoot.c_str(), devRootCStr, AZ_MAX_PATH_LEN); - - char devAssetsCStr[AZ_MAX_PATH_LEN] = { 0 }; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(devAssets.c_str(), devAssetsCStr, AZ_MAX_PATH_LEN); - - AZStd::string relativePath = devAssetsCStr; - AzFramework::StringFunc::Replace(relativePath, devRootCStr, ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AZStd::string sourceFilePath; - - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo; - bool sourceInfoFound{}; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, asset.GetHint().c_str(), assetInfo, watchFolder); - if (sourceInfoFound) - { - AZStd::string assetPath; - AzFramework::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), assetPath); - - sourceFilePath = assetPath; - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Controller::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); - return "Failed to find source file"; - } - - devRoot = devRootCStr; - AzFramework::StringFunc::Path::Normalize(devRoot); - - relativePath = sourceFilePath; - AzFramework::StringFunc::Replace(relativePath, devRoot.c_str(), ""); - if (relativePath.starts_with("/")) - { - relativePath = relativePath.substr(1, relativePath.size() - 1); - } - - AzFramework::StringFunc::Path::Normalize(relativePath); - AzFramework::StringFunc::Path::Normalize(backupPath); - - AZStd::string targetFilePath = backupPath; - targetFilePath += relativePath; - - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Controller::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return "Failed to copy source file to backup location"; - } - - Log("Controller::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return ""; - } - - void Controller::UpgradeGraph(const AZ::Data::Asset& asset) - { - m_inProgress = true; - m_upgradeComplete = false; - Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); - m_view->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); - m_scriptCanvasEntity = nullptr; - - UpgradeNotifications::Bus::Handler::BusConnect(); - - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" - , azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) - { - return; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "Controller::UpgradeGraph The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return; - } - - AZ::Entity* queryEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); - if (queryEntity) - { - if (queryEntity->GetState() == AZ::Entity::State::Active) - { - queryEntity->Deactivate(); - } - - scriptCanvasEntity = queryEntity; - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) - { - scriptCanvasEntity->Init(); - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) - { - scriptCanvasEntity->Activate(); - } - - AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - if (graphComponent) - { - m_scriptCanvasEntity = scriptCanvasEntity; - - graphComponent->UpgradeGraph - (asset - , m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_view->verbose->isChecked()); - } - } - - AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); - } - - void Controller::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - if (!fullPathFound) - { - AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); - } - - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - this->OnSourceFileReleased(asset); - }); - streamer->QueueRequest(flushRequest); - } - - void Controller::OnSourceFileReleased(AZ::Data::Asset asset) - { - AZStd::string relativePath, fullPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); - bool fullPathFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); - m_tmpFileName.clear(); - AZStd::string tmpFileName; - // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. - // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. - if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); - return; - } - - bool tempSavedSucceeded = false; - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); - if (fileStream.IsOpen()) - { - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasEditor::ScriptCanvasAssetHandler handler; - tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); - } - - fileStream.Close(); - } - - // attempt to remove temporary file no matter what - m_tmpFileName = tmpFileName; - if (!tempSavedSucceeded) - { - GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); - return; - } - - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) - { - constexpr const size_t k_maxAttemps = 10; - - if (!info.IsReadOnly()) - { - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - if (m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - else - { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); - } - } - } - }); - } - - void Controller::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target - , size_t remainingAttempts) - { - // ViewCpp::FileEventHandler fileEventHandler; - - if (remainingAttempts == 0) - { - // all attempts failed, give up - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); - GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); - } - else if (remainingAttempts == 2) - { - // before the final attempt, flush all caches - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); - streamer->SetRequestCompleteCallback(flushRequest - , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction( - [this, asset, remainingAttempts, source, target]() { PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - else - { - // the actual move attempt - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - m_tmpFileName.clear(); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - AZ::SystemTickBus::QueueFunction([this, asset]() - { - GraphUpgradeComplete(asset, OperationResult::Success, ""); - }); - } - else - { - AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); - }); - streamer->QueueRequest(flushRequest); - } - } - } - - void Controller::GraphUpgradeComplete - (const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - AZStd::lock_guard lock(m_mutex); - m_upgradeComplete = true; - m_upgradeResult = result; - m_upgradeMessage = message; - m_upgradeAsset = asset; - - if (!m_tmpFileName.empty()) - { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); - - if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) - { - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); - } - } - - if (m_upgradeResult == OperationResult::Failure) - { - AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); - } - - m_tmpFileName.clear(); - } - - void Controller::GraphUpgradeCompleteUIUpdate - (const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) - { - QString text = asset.GetHint().c_str(); - QList items = m_view->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); - - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - QTableWidgetItem* label = m_view->tableWidget->item(row, ColumnAsset); - QString assetName = asset.GetHint().c_str(); - - if (label->text().compare(assetName) == 0) - { - m_view->tableWidget->removeCellWidget(row, ColumnAction); - m_view->tableWidget->removeCellWidget(row, ColumnStatus); - - QToolButton* doneButton = new QToolButton(this); - doneButton->setToolTip("Upgrade complete"); - if (result == OperationResult::Success) - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); - } - else - { - doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); - doneButton->setToolTip(message.data()); - } - - m_view->tableWidget->setCellWidget(row, ColumnStatus, doneButton); - } - } - } - } - - void Controller::FinalizeUpgrade() - { - Log("FinalizeUpgrade!"); - m_inProgress = false; - m_assetsToUpgrade.clear(); - m_view->upgradeAllButton->setEnabled(false); - m_view->onlyShowOutdated->setEnabled(true); - m_keepEditorAlive.reset(); - m_view->progressBar->setVisible(false); - - // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - if (assetsThatNeedManualInspection > 0) - { - m_view->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); - } - else - { - m_view->spinner->SetText("Upgrade complete."); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - AZ::Interface::Get()->SetIsUpgrading(false); - //m_settingsCache.reset(); - } - void Controller::OnScanButtonPress() { auto isUpToDate = [this](AZ::Data::Asset asset) { - Log("InspectAsset: %s", asset.GetHint().c_str()); AZ::Entity* scriptCanvasEntity = nullptr; if (asset.GetType() == azrtti_typeid()) @@ -663,7 +103,11 @@ namespace ScriptCanvasEditor ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); if (!scriptCanvasAsset) { - Log("InspectAsset: %s, AsestData failed to return ScriptCanvasAsset", asset.GetHint().c_str()); + AZ_Warning + ( ScriptCanvas::k_VersionExplorerWindow.data() + , false + , "InspectAsset: %s, AsestData failed to return ScriptCanvasAsset" + , asset.GetHint().c_str()); return true; } @@ -697,8 +141,6 @@ namespace ScriptCanvasEditor void Controller::OnScanComplete(const ScanResult& result) { - Log("Full Scan Complete."); - m_view->onlyShowOutdated->setEnabled(true); // Enable all the Upgrade buttons @@ -724,8 +166,6 @@ namespace ScriptCanvasEditor { m_view->upgradeAllButton->setEnabled(true); } - - m_keepEditorAlive.reset(); } void Controller::OnScanFilteredGraph(const AZ::Data::AssetInfo& info) @@ -746,7 +186,7 @@ namespace ScriptCanvasEditor rowGoToButton->setEnabled(false); AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); spinner->SetBusyIconSize(16); -// +// \\ todo restore this // connect(rowGoToButton, &QPushButton::clicked, [this, rowGoToButton, assetInfo] { // // // request upgrade of a single graph @@ -797,19 +237,18 @@ namespace ScriptCanvasEditor OnScannedGraphResult(assetInfo); } - void Controller::OnScannedGraphResult(const AZ::Data::AssetInfo& info) + void Controller::OnScannedGraphResult([[maybe_unused]] const AZ::Data::AssetInfo& info) { m_view->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); ++m_currentAssetRowIndex; - Log("ScanComplete: %s", info.m_relativePath.c_str()); - FlushLogs(); + AddLogEntries(); } void Controller::OnScanLoadFailure(const AZ::Data::AssetInfo& info) { m_view->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); QTableWidgetItem* rowName = new QTableWidgetItem - (tr(AZStd::string::format("Load Error: %s", info.m_relativePath.c_str()).c_str())); + ( tr(AZStd::string::format("Load Error: %s", info.m_relativePath.c_str()).c_str())); m_view->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); OnScannedGraphResult(info); } @@ -819,141 +258,92 @@ namespace ScriptCanvasEditor OnScannedGraph(info, Filtered::No); } - void Controller::BackupComplete() + void Controller::OnUpgradeAllButtonPress() + { + auto simpleUpdate = [this](AZ::Data::Asset asset) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "View::UpgradeGraph The Script Canvas asset must have a valid entity"); + if (!scriptCanvasEntity) + { + return; + } + + AZ::Entity* queryEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); + if (queryEntity) + { + if (queryEntity->GetState() == AZ::Entity::State::Active) + { + queryEntity->Deactivate(); + } + + scriptCanvasEntity = queryEntity; + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) + { + scriptCanvasEntity->Init(); + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) + { + scriptCanvasEntity->Activate(); + } + + AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + if (graphComponent) + { + graphComponent->UpgradeGraph + ( asset + , m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_view->verbose->isChecked()); + } + } + }; + + ModifyConfiguration config; + config.modification = simpleUpdate; + config.backupGraphBeforeModification = m_view->makeBackupCheckbox->isChecked(); + ModelRequestsBus::Broadcast(&ModelRequestsTraits::Modify, config); + } + + void Controller::OnUpgradeAllBegin() { m_currentAssetRowIndex = 0; + m_view->tableWidget->setRowCount(0); + m_view->progressBar->setVisible(true); m_view->progressBar->setValue(0); + m_view->scanButton->setEnabled(false); + m_view->upgradeAllButton->setEnabled(false); + m_view->onlyShowOutdated->setEnabled(false); } - void Controller::UpgradeSingle - ( QPushButton* rowGoToButton - , AzQtComponents::StyledBusyLabel* spinner - , AZ::Data::AssetInfo assetInfo) + void Controller::OnUpgradeAllComplete() { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset - (assetInfo.m_assetId, assetInfo.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - - if (asset) - { - asset.BlockUntilLoadComplete(); - - if (asset.IsReady()) - { - AZ::Interface::Get()->SetIsUpgrading(true); - m_isUpgradingSingleGraph = true; - m_logs.clear(); - m_view->textEdit->clear(); - spinner->SetIsBusy(true); - rowGoToButton->setEnabled(false); - - m_inProgressAsset = AZStd::find_if(m_assetsToUpgrade.begin(), m_assetsToUpgrade.end() - , [asset](const UpgradeAssets::value_type& assetToUpgrade) - { - return assetToUpgrade.GetId() == asset.GetId(); - }); - - m_state = ProcessState::Upgrade; - AZ::SystemTickBus::Handler::BusConnect(); - } - } - } - - void Controller::ScanComplete(const AZ::Data::Asset& asset) - { - Log("ScanComplete: %s", asset.GetHint().c_str()); - m_inProgress = false; - m_view->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - m_view->scanButton->setEnabled(true); - - m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); - - if (m_inspectingAsset == m_assetsToInspect.end()) - { - AZ::SystemTickBus::QueueFunction([this]() { FinalizeScan(); }); - - if (!m_assetsToUpgrade.empty()) - { - m_view->upgradeAllButton->setEnabled(true); - } - } - } - - void Controller::FinalizeScan() - { - Log("FinalizeScan()"); - - m_view->spinner->SetIsBusy(false); - m_view->onlyShowOutdated->setEnabled(true); - - // Enable all the Upgrade buttons - for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) - { - QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction)); - if (button) - { - button->setEnabled(true); - } - } - - QString spinnerText = QStringLiteral("Scan Complete"); - if (m_assetsToUpgrade.empty()) - { - spinnerText.append(" - No graphs require upgrade!"); - } - else - { - spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" - , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); - } - - - m_view->spinner->SetText(spinnerText); - m_view->progressBar->setVisible(false); - - if (!m_assetsToUpgrade.empty()) - { - m_view->upgradeAllButton->setEnabled(true); - } - - AZ::SystemTickBus::Handler::BusDisconnect(); - - m_keepEditorAlive.reset(); - //m_settingsCache.reset(); - m_state = ProcessState::Inactive; - } - - void Controller::FlushLogs() - { - if (m_logs.empty()) - { - return; - } - - const QTextCursor oldCursor = m_view->textEdit->textCursor(); - QScrollBar* scrollBar = m_view->textEdit->verticalScrollBar(); - - m_view->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = m_view->textEdit->textCursor(); - - while (!m_logs.empty()) - { - auto line = "\n" + m_logs.front(); - - m_logs.pop_front(); - - textCursor.insertText(line.c_str()); - } - - scrollBar->setValue(scrollBar->maximum()); - m_view->textEdit->moveCursor(QTextCursor::StartOfLine); } - void Controller::closeEvent(QCloseEvent* event) + void Controller::OnUpgradeAllDependencySortBegin() { - m_keepEditorAlive.reset(); - AzQtComponents::StyledDialog::closeEvent(event); + } + + void Controller::OnUpgradeAllDependencySortEnd(const AZStd::vector& sortedAssets) + { + m_view->progressBar->setRange(0, aznumeric_cast(sortedAssets.size())); } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index 85459b4d46..f7a0315730 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -10,12 +10,9 @@ #if !defined(Q_MOC_RUN) #include -#include #include #include #include -#include -#include #include #include #include @@ -40,24 +37,10 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { - //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow - //! the upgrade tool to work even if the editor is not in the foreground - class EditorKeepAlive - { - public: - EditorKeepAlive(); - ~EditorKeepAlive(); - - private: - int m_keepEditorActive; - ICVar* m_edKeepEditorActive; - }; - //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog //! Handles display change notifications, handles state change notifications, sends control requests class Controller : public AzQtComponents::StyledDialog - , private AZ::SystemTickBus::Handler , private UpgradeNotifications::Bus::Handler , private ModelNotificationsBus::Handler { @@ -74,104 +57,28 @@ namespace ScriptCanvasEditor static constexpr int ColumnBrowse = 2; static constexpr int ColumnStatus = 3; + AZStd::unique_ptr m_view; + size_t m_currentAssetRowIndex = 0; + + void AddLogEntries(); + void OnCloseButtonPress(); - void OnScanBegin(size_t assetCount) override; void OnScanButtonPress(); + void OnUpgradeAllButtonPress(); + + void OnScanBegin(size_t assetCount) override; void OnScanComplete(const ScanResult& result) override; void OnScanFilteredGraph(const AZ::Data::AssetInfo& info) override; void OnScanLoadFailure(const AZ::Data::AssetInfo& info) override; void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) override; - enum Filtered - { - No, - Yes - }; + enum class Filtered { No, Yes }; void OnScannedGraph(const AZ::Data::AssetInfo& info, Filtered filtered); void OnScannedGraphResult(const AZ::Data::AssetInfo& info); - - - void OnUpgradeAllButtonPress(); - - enum class ProcessState - { - Inactive, - Backup, - Scan, - Upgrade, - }; - ProcessState m_state = ProcessState::Inactive; - - void ScanComplete(const AZ::Data::Asset&); - - // SystemTickBus::Handler - void OnSystemTick() override; - - enum class OperationResult - { - Success, - Failure, - }; - - void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); - - bool IsUpgrading() const { return false; } - - bool m_inProgress = false; - // scan fields - size_t m_currentAssetRowIndex = 0; - size_t m_inspectedAssets = 0; - size_t m_failedAssets = 0; - size_t m_discoveredAssets = 0; - - IUpgradeRequests::AssetList m_assetsToInspect; - IUpgradeRequests::AssetList::iterator m_inspectingAsset; - using UpgradeAssets = AZStd::vector>; - UpgradeAssets m_assetsToUpgrade; - UpgradeAssets::iterator m_inProgressAsset; - - AZ::Data::Asset m_currentAsset; - - AZStd::unique_ptr m_view; - // upgrade fields - AZStd::recursive_mutex m_mutex; - bool m_upgradeComplete = false; - AZ::Data::Asset m_upgradeAsset; - int m_upgradeAssetIndex = 0; - OperationResult m_upgradeResult; - AZStd::string m_upgradeMessage; - AZStd::string m_tmpFileName; - - AZStd::unique_ptr m_keepEditorAlive; - - AZStd::deque m_logs; - - AZ::Entity* m_scriptCanvasEntity = nullptr; - - bool m_isUpgradingSingleGraph = false; - - void UpgradeSingle(QPushButton* item, AzQtComponents::StyledBusyLabel* spinner, AZ::Data::AssetInfo assetInfo); - - void FlushLogs(); - - void FinalizeUpgrade(); - void FinalizeScan(); - - void BackupComplete(); - AZStd::string BackupGraph(const AZ::Data::Asset&); - void UpgradeGraph(const AZ::Data::Asset&); - - void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); - void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; - - void OnSourceFileReleased(AZ::Data::Asset asset); - - void closeEvent(QCloseEvent* event) override; - - bool m_overwriteAll = false; - void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); - - void Log(const char* format, ...); + void OnUpgradeAllBegin() override; + void OnUpgradeAllComplete() override; + void OnUpgradeAllDependencySortBegin() override; + void OnUpgradeAllDependencySortEnd(const AZStd::vector& sortedAssets) override; }; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h new file mode 100644 index 0000000000..c75133f09e --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h @@ -0,0 +1,32 @@ +/* + * 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 + * + */ +#pragma once + +#include + +#define VE_LOG(...) LogBus::Broadcast(&LogTraits::Entry, __VA_ARGS__); + +namespace ScriptCanvasEditor +{ + namespace VersionExplorer + { + class LogTraits + : public AZ::EBusTraits + { + public: + virtual void Activate() = 0; + virtual void Clear() = 0; + virtual void Deactivate() = 0; + virtual void Entry(const char* format, ...) = 0; + virtual const AZStd::vector* GetEntries() const = 0; + virtual void SetVersionExporerExclusivity(bool enabled) = 0; + virtual void SetVerbose(bool verbosity) = 0; + }; + using LogBus = AZ::EBus; + } +} diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp index 8d5aa62674..ad9d39cb98 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp @@ -7,8 +7,11 @@ */ #include -#include +#include #include +#include +#include +#include #include namespace ModifierCpp @@ -20,6 +23,31 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + EditorKeepAlive::EditorKeepAlive() + { + ISystem* system = nullptr; + CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); + + if (system) + { + m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); + + if (m_edKeepEditorActive) + { + m_keepEditorActive = m_edKeepEditorActive->GetIVal(); + m_edKeepEditorActive->Set(1); + } + } + } + + EditorKeepAlive::~EditorKeepAlive() + { + if (m_edKeepEditorActive) + { + m_edKeepEditorActive->Set(m_keepEditorActive); + } + } + Model::Model() { ModelRequestsBus::Handler::BusConnect(); @@ -33,20 +61,58 @@ namespace ScriptCanvasEditor ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; } - const AZStd::vector* Model::GetLogs() + void Model::Idle() { - return &m_log.GetEntries(); + m_state = State::Idle; + m_keepEditorAlive.reset(); } - + + bool Model::IsReadyToModify() const + { + if (IsWorking()) + { + return false; + } + + if (!m_scanner) + { + return false; + } + + return !m_scanner->GetResult().m_unfiltered.empty(); + } + bool Model::IsWorking() const { return m_state != State::Idle; } + void Model::Modify(const ModifyConfiguration& modification) + { + if (!IsReadyToModify()) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Explorer is not ready to modify graphs."); + return; + } + + m_state = State::Modifying; + m_keepEditorAlive = AZStd::make_unique(); + auto results = m_scanner->TakeResult(); + m_modifier = AZStd::make_unique(modification, AZStd::move(results.m_unfiltered), [this](){ OnModificationComplete(); }); + } + + void Model::OnModificationComplete() + { + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanComplete, m_scanner->GetResult()); + m_modifier.reset(); + m_scanner.reset(); + Idle(); + } + void Model::OnScanComplete() { ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanComplete, m_scanner->GetResult()); - m_state = State::Idle; + Idle(); } void Model::Scan(const ScanConfiguration& config) @@ -58,6 +124,7 @@ namespace ScriptCanvasEditor } m_state = State::Scanning; + m_keepEditorAlive = AZStd::make_unique(); m_scanner = AZStd::make_unique(config, [this](){ OnScanComplete(); }); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h index 407074fa94..72ab210e37 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h @@ -15,10 +15,25 @@ #include #include +struct ICVar; + namespace ScriptCanvasEditor { namespace VersionExplorer { + //!Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow + //! the upgrade tool to work even if the editor is not in the foreground + class EditorKeepAlive + { + public: + EditorKeepAlive(); + ~EditorKeepAlive(); + + private: + int m_keepEditorActive; + ICVar* m_edKeepEditorActive; + }; + //! Handles model change requests, state queries; sends state change notifications class Model : public ModelRequestsBus::Handler @@ -28,7 +43,8 @@ namespace ScriptCanvasEditor Model(); - const AZStd::vector* GetLogs(); + void Modify(const ModifyConfiguration& modification) override; + void Scan(const ScanConfiguration& config) override; private: @@ -45,9 +61,13 @@ namespace ScriptCanvasEditor AZStd::unique_ptr m_modifier; AZStd::unique_ptr m_scanner; AZStd::unique_ptr m_settingsCache; + AZStd::unique_ptr m_keepEditorAlive; void CacheSettings(); + void Idle(); + bool IsReadyToModify() const; bool IsWorking() const; + void OnModificationComplete(); void OnScanComplete(); void RestoreSettings(); }; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index 11a956c555..d48c15949a 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -14,6 +14,12 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + struct ModifyConfiguration + { + AZStd::function)> modification; + bool backupGraphBeforeModification = false; + }; + struct ScanConfiguration { AZStd::function)> filter; @@ -24,11 +30,16 @@ namespace ScriptCanvasEditor : public AZ::EBusTraits { public: - virtual const AZStd::vector* GetLogs() = 0; + virtual void Modify(const ModifyConfiguration& modification) = 0; virtual void Scan(const ScanConfiguration& filter) = 0; }; using ModelRequestsBus = AZ::EBus; + struct ModificationResult + { + + }; + struct ScanResult { AZStd::vector m_catalogAssets; @@ -46,6 +57,11 @@ namespace ScriptCanvasEditor virtual void OnScanFilteredGraph(const AZ::Data::AssetInfo& info) = 0; virtual void OnScanLoadFailure(const AZ::Data::AssetInfo& info) = 0; virtual void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) = 0; + + virtual void OnUpgradeAllBegin() = 0; + virtual void OnUpgradeAllComplete() = 0; + virtual void OnUpgradeAllDependencySortBegin() = 0; + virtual void OnUpgradeAllDependencySortEnd(const AZStd::vector& sortedAssets) = 0; }; using ModelNotificationsBus = AZ::EBus; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index a0067e1a5f..d782ebd572 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -17,6 +17,19 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + Modifier::Modifier + ( const ModifyConfiguration& modification + , AZStd::vector&& assets + , AZStd::function onComplete) + { + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeAllBegin); + AZ::SystemTickBus::Handler::BusConnect(); + } + + void Modifier::OnSystemTick() + { + + } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h index e5a40ff096..d391f51bf7 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -9,15 +9,31 @@ #pragma once #include +#include +#include namespace ScriptCanvasEditor { namespace VersionExplorer { class Modifier + : private AZ::SystemTickBus::Handler { public: AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0); + + Modifier + ( const ModifyConfiguration& modification + , AZStd::vector&& assets + , AZStd::function onComplete); + + private: + size_t m_assetIndex = 0; + AZStd::function m_onComplete; + ModifyConfiguration m_config; + ModifyConfiguration m_result; + + void OnSystemTick() override; }; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp index 09574883b6..26765a9f97 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp @@ -8,11 +8,7 @@ #include #include - -namespace ScannerCpp -{ - -} +#include namespace ScriptCanvasEditor { @@ -42,11 +38,13 @@ namespace ScriptCanvasEditor { if (m_config.filter && m_config.filter(asset)) { + VE_LOG("Scanner: Excluded: %s ", GetCurrentAsset().m_relativePath.c_str()); m_result.m_filteredAssets.push_back(GetCurrentAsset()); ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanFilteredGraph, GetCurrentAsset()); } else { + VE_LOG("Scanner: Included: %s ", GetCurrentAsset().m_relativePath.c_str()); m_result.m_unfiltered.push_back(GetCurrentAsset()); ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanUnFilteredGraph, GetCurrentAsset()); } @@ -69,7 +67,6 @@ namespace ScriptCanvasEditor , azrtti_typeid() , AZ::Data::AssetLoadBehavior::PreLoad); - // Log("Scan: Loading: %s ", m_catalogAssets[m_catalogAssetIndex].GetHint().c_str()); asset.BlockUntilLoadComplete(); if (asset.IsReady()) @@ -86,7 +83,9 @@ namespace ScriptCanvasEditor { if (m_catalogAssetIndex == m_result.m_catalogAssets.size()) { - AZ::SystemTickBus::Handler::BusConnect(); + VE_LOG("Scanner: Complete."); + AZ::SystemTickBus::Handler::BusDisconnect(); + if (m_onComplete) { m_onComplete(); @@ -96,14 +95,17 @@ namespace ScriptCanvasEditor { if (auto asset = LoadAsset()) { + VE_LOG("Scanner: Loaded: %s ", GetCurrentAsset().m_relativePath.c_str()); FilterAsset(asset); } else { + VE_LOG("Scanner: Failed to load: %s ", GetCurrentAsset().m_relativePath.c_str()); m_result.m_loadErrors.push_back(GetCurrentAsset()); ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanLoadFailure, GetCurrentAsset()); } + VE_LOG("Scanner: scan of %s complete", GetCurrentAsset().m_relativePath.c_str()); ++m_catalogAssetIndex; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp index be4b619bfd..6f856b9d4c 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp @@ -20,20 +20,12 @@ namespace ScriptCanvasEditor void Log::Activate() { AZ::Debug::TraceMessageBus::Handler::BusConnect(); + LogBus::Handler::BusConnect(); } - void Log::AddEntry(const char* format, ...) + void Log::Clear() { - if (m_isVerbose) - { - char sBuffer[2048]; - va_list ArgList; - va_start(ArgList, format); - azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); - sBuffer[sizeof(sBuffer) - 1] = '\0'; - va_end(ArgList); - AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); - } + m_logs.clear(); } bool Log::CaptureFromTraceBus(const char* window, const char* message) @@ -58,9 +50,23 @@ namespace ScriptCanvasEditor AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); } - const AZStd::vector& Log::GetEntries() const + void Log::Entry(const char* format, ...) { - return m_logs; + if (m_isVerbose) + { + char sBuffer[2048]; + va_list ArgList; + va_start(ArgList, format); + azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); + sBuffer[sizeof(sBuffer) - 1] = '\0'; + va_end(ArgList); + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); + } + } + + const AZStd::vector* Log::GetEntries() const + { + return &m_logs; } void Log::SetVersionExporerExclusivity(bool enabled) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h index 1ba8e8c9b1..7399b085da 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h @@ -10,6 +10,7 @@ #include #include +#include namespace ScriptCanvasEditor { @@ -17,16 +18,18 @@ namespace ScriptCanvasEditor { class Log : private AZ::Debug::TraceMessageBus::Handler + , private LogBus::Handler { public: AZ_CLASS_ALLOCATOR(Log, AZ::SystemAllocator, 0); - void Activate(); - void AddEntry(const char* format, ...); + void Activate() override; + void Clear() override; void Deactivate(); - const AZStd::vector& GetEntries() const; - void SetVersionExporerExclusivity(bool enabled); - void SetVerbose(bool verbosity); + void Entry(const char* format, ...) override; + const AZStd::vector* GetEntries() const override; + void SetVersionExporerExclusivity(bool enabled) override; + void SetVerbose(bool verbosity) override; private: bool m_isExclusiveReportingEnabled = false; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h deleted file mode 100644 index cf49072230..0000000000 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 - * - */ -#pragma once - -#include - -namespace ScriptCanvasEditor -{ - namespace VersionExplorer - { - - } -} diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake index 1ce2b0c502..b12c608fe5 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake @@ -259,24 +259,24 @@ set(FILES Editor/View/Windows/ScriptCanvasContextMenus.cpp Editor/View/Windows/ScriptCanvasContextMenus.h Editor/View/Windows/ScriptCanvasEditorResources.qrc + Editor/View/Windows/Tools/UpgradeTool/Controller.cpp + Editor/View/Windows/Tools/UpgradeTool/Controller.h + Editor/View/Windows/Tools/UpgradeTool/Controller.ui Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp Editor/View/Windows/Tools/UpgradeTool/FileSaver.h - Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp - Editor/View/Windows/Tools/UpgradeTool/Modifier.h + Editor/View/Windows/Tools/UpgradeTool/LogTraits.h Editor/View/Windows/Tools/UpgradeTool/Model.cpp Editor/View/Windows/Tools/UpgradeTool/Model.h + Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp + Editor/View/Windows/Tools/UpgradeTool/Modifier.h Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp Editor/View/Windows/Tools/UpgradeTool/Scanner.h Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp + Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui - Editor/View/Windows/Tools/UpgradeTool/Controller.cpp - Editor/View/Windows/Tools/UpgradeTool/Controller.h - Editor/View/Windows/Tools/UpgradeTool/View.ui - Editor/View/Windows/Tools/UpgradeTool/ViewTraits.h Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h - Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h Editor/Framework/ScriptCanvasGraphUtilities.inl Editor/Framework/ScriptCanvasGraphUtilities.h Editor/Framework/ScriptCanvasTraceUtilities.h From f55737af11081c6f6cc588b61df696774dfb9d23 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 14 Sep 2021 08:41:11 -0700 Subject: [PATCH 10/24] dependency sort WIP Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/Controller.cpp | 1 + .../Windows/Tools/UpgradeTool/ModelTraits.h | 2 + .../Windows/Tools/UpgradeTool/Modifier.cpp | 87 ++++++++++++++++++- .../View/Windows/Tools/UpgradeTool/Modifier.h | 19 +++- 4 files changed, 107 insertions(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 44d6f2e738..09f0428901 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -94,6 +94,7 @@ namespace ScriptCanvasEditor void Controller::OnScanButtonPress() { + // \todo move to another file auto isUpToDate = [this](AZ::Data::Asset asset) { AZ::Entity* scriptCanvasEntity = nullptr; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index d48c15949a..d01d311ebc 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -18,6 +18,8 @@ namespace ScriptCanvasEditor { AZStd::function)> modification; bool backupGraphBeforeModification = false; + // disabling this can be acceptable, but be careful + bool successfulDependencyUpgradeRequired = true; }; struct ScanConfiguration diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index d782ebd572..9841a9f60e 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include namespace ModifierCpp { @@ -21,15 +23,98 @@ namespace ScriptCanvasEditor ( const ModifyConfiguration& modification , AZStd::vector&& assets , AZStd::function onComplete) + : m_config(modification) + , m_assets(assets) + , m_onComplete(onComplete) { - ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeAllBegin); AZ::SystemTickBus::Handler::BusConnect(); } + + const AZ::Data::AssetInfo& Modifier::GetCurrentAsset() const + { + return m_state == State::GatheringDependencies + ? m_assets[m_assetIndex] + : m_assets[m_dependencyOrderedIndicies[m_assetIndex]]; + } + + void Modifier::GatherDependencies() + { + AZ::SerializeContext* serializeContext{}; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + AZ_Assert(serializeContext, "SerializeContext is required to enumerate dependent assets in the ScriptCanvas file"); + + /* + + // AZStd::unordered_multimap jobDependenciesByKey; + auto assetFilter = [this, &jobDependenciesByKey] + ( void* instancePointer + , const AZ::SerializeContext::ClassData* classData + , [[maybe_unused]] const AZ::SerializeContext::ClassElement* classElement) + { + auto azTypeId = classData->m_azRtti->GetTypeId(); + if (azTypeId == azrtti_typeid>()) + { + const auto* subgraphAsset = reinterpret_cast*>(instancePointer); + if (subgraphAsset->GetId().IsValid()) + { + // AssetBuilderSDK::SourceFileDependency dependency; + // dependency.m_sourceFileDependencyUUID = subgraphAsset->GetId().m_guid; + // jobDependenciesByKey.insert({ s_scriptCanvasProcessJobKey, dependency }); + // this->m_processEditorAssetDependencies.push_back + // ({ subgraphAsset->GetId(), azTypeId, AZ::Data::AssetLoadBehavior::PreLoad }); + } + } + // always continue, make note of the script canvas dependencies + return true; + }; + + AZ_Verify(serializeContext->EnumerateInstanceConst + ( sourceGraph->GetGraphData() + , azrtti_typeid() + , assetFilter + , {} + , AZ::SerializeContext::ENUM_ACCESS_FOR_READ + , nullptr + , nullptr), "Failed to gather dependencies from graph data"); + + // Flush asset database events to ensure no asset references are held by closures queued on Ebuses. + AZ::Data::AssetManager::Instance().DispatchEvents(); + */ + } + + AZ::Data::Asset Modifier::LoadAsset() + { + AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset + (GetCurrentAsset().m_assetId + , azrtti_typeid() + , AZ::Data::AssetLoadBehavior::PreLoad); + + asset.BlockUntilLoadComplete(); + + if (asset.IsReady()) + { + return asset; + } + else + { + return {}; + } + } + void Modifier::OnSystemTick() { + switch (m_state) + { + case State::GatheringDependencies: + TickGatherDependencies(); + break; + case State::ModifyingGraphs: + TickUpdateGraph(); + break; + } } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h index d391f51bf7..b862de82f0 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -28,12 +28,29 @@ namespace ScriptCanvasEditor , AZStd::function onComplete); private: + enum class State + { + GatheringDependencies, + ModifyingGraphs + }; + + State m_state = State::GatheringDependencies; size_t m_assetIndex = 0; AZStd::function m_onComplete; + AZStd::vector m_assets; + AZStd::vector m_dependencyOrderedIndicies; + AZStd::unordered_map> m_dependencies; + AZStd::vector m_failures; ModifyConfiguration m_config; - ModifyConfiguration m_result; + ModificationResult m_result; + void GatherDependencies(); + const AZ::Data::AssetInfo& GetCurrentAsset() const; + AZ::Data::Asset LoadAsset(); + void SortGraphsByDependencies(); void OnSystemTick() override; + void TickGatherDependencies(); + void TickUpdateGraph(); }; } } From 0e2f75492c4ac67fdd475c62729912fb5365d50e Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 14 Sep 2021 14:05:15 -0700 Subject: [PATCH 11/24] dependency sort finished, but not tested Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/Controller.cpp | 4 +- .../Windows/Tools/UpgradeTool/Controller.h | 4 +- .../Windows/Tools/UpgradeTool/LogTraits.h | 1 + .../Windows/Tools/UpgradeTool/ModelTraits.h | 4 +- .../Windows/Tools/UpgradeTool/Modifier.cpp | 159 ++++++++++++++++-- .../View/Windows/Tools/UpgradeTool/Modifier.h | 21 ++- 6 files changed, 174 insertions(+), 19 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 09f0428901..8eae0e1bd0 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -342,7 +342,9 @@ namespace ScriptCanvasEditor } - void Controller::OnUpgradeAllDependencySortEnd(const AZStd::vector& sortedAssets) + void Controller::OnUpgradeAllDependencySortEnd + ( const AZStd::vector& sortedAssets + , [[maybe_unused]] const AZStd::vector& sortedOrder) { m_view->progressBar->setRange(0, aznumeric_cast(sortedAssets.size())); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index f7a0315730..e2f00fe6f3 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -78,7 +78,9 @@ namespace ScriptCanvasEditor void OnUpgradeAllBegin() override; void OnUpgradeAllComplete() override; void OnUpgradeAllDependencySortBegin() override; - void OnUpgradeAllDependencySortEnd(const AZStd::vector& sortedAssets) override; + void OnUpgradeAllDependencySortEnd + ( const AZStd::vector& sortedAssets + , const AZStd::vector& sortedOrder) override; }; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h index c75133f09e..47cebe7324 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/LogTraits.h @@ -8,6 +8,7 @@ #pragma once #include +#include #define VE_LOG(...) LogBus::Broadcast(&LogTraits::Entry, __VA_ARGS__); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index d01d311ebc..09ad2b01c1 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -63,7 +63,9 @@ namespace ScriptCanvasEditor virtual void OnUpgradeAllBegin() = 0; virtual void OnUpgradeAllComplete() = 0; virtual void OnUpgradeAllDependencySortBegin() = 0; - virtual void OnUpgradeAllDependencySortEnd(const AZStd::vector& sortedAssets) = 0; + virtual void OnUpgradeAllDependencySortEnd + ( const AZStd::vector& assets + , const AZStd::vector& sortedOrder) = 0; }; using ModelNotificationsBus = AZ::EBus; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index 9841a9f60e..1723b0f8ff 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -6,9 +6,11 @@ * */ +#include #include #include #include +#include namespace ModifierCpp { @@ -23,7 +25,8 @@ namespace ScriptCanvasEditor ( const ModifyConfiguration& modification , AZStd::vector&& assets , AZStd::function onComplete) - : m_config(modification) + : m_state(State::GatheringDependencies) + , m_config(modification) , m_assets(assets) , m_onComplete(onComplete) { @@ -31,12 +34,22 @@ namespace ScriptCanvasEditor AZ::SystemTickBus::Handler::BusConnect(); } - const AZ::Data::AssetInfo& Modifier::GetCurrentAsset() const { return m_state == State::GatheringDependencies ? m_assets[m_assetIndex] - : m_assets[m_dependencyOrderedIndicies[m_assetIndex]]; + : m_assets[m_dependencyOrderedAssetIndicies[m_assetIndex]]; + } + + AZStd::unordered_set& Modifier::GetOrCreateDependencyIndexSet() + { + auto iter = m_dependencies.find(m_assetIndex); + if (iter == m_dependencies.end()) + { + iter = m_dependencies.insert_or_assign(m_assetIndex, AZStd::unordered_set()).first; + } + + return iter->second; } void Modifier::GatherDependencies() @@ -45,10 +58,19 @@ namespace ScriptCanvasEditor AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); AZ_Assert(serializeContext, "SerializeContext is required to enumerate dependent assets in the ScriptCanvas file"); - /* + auto asset = LoadAsset(); + if (!asset + || !asset.GetAs() + || !asset.GetAs()->GetScriptCanvasGraph() + || !asset.GetAs()->GetScriptCanvasGraph()->GetGraphData()) + { + VE_LOG("Modifier: Failed to load asset %s for modification, even though it scanned properly"); + return; + } - // AZStd::unordered_multimap jobDependenciesByKey; - auto assetFilter = [this, &jobDependenciesByKey] + auto graphData = asset.GetAs()->GetScriptCanvasGraph()->GetGraphData(); + + auto dependencyGrabber = [this] ( void* instancePointer , const AZ::SerializeContext::ClassData* classData , [[maybe_unused]] const AZ::SerializeContext::ClassElement* classElement) @@ -59,11 +81,15 @@ namespace ScriptCanvasEditor const auto* subgraphAsset = reinterpret_cast*>(instancePointer); if (subgraphAsset->GetId().IsValid()) { - // AssetBuilderSDK::SourceFileDependency dependency; - // dependency.m_sourceFileDependencyUUID = subgraphAsset->GetId().m_guid; - // jobDependenciesByKey.insert({ s_scriptCanvasProcessJobKey, dependency }); - // this->m_processEditorAssetDependencies.push_back - // ({ subgraphAsset->GetId(), azTypeId, AZ::Data::AssetLoadBehavior::PreLoad }); + if (auto iter = m_assetInfoIndexById.find(subgraphAsset->GetId().m_guid); iter != m_assetInfoIndexById.end()) + { + GetOrCreateDependencyIndexSet().insert(iter->second); + } + else + { + VE_LOG("Modifier: Dependency found that was not picked up by the scanner: %s" + , subgraphAsset->GetId().ToString().c_str()); + } } } // always continue, make note of the script canvas dependencies @@ -71,9 +97,9 @@ namespace ScriptCanvasEditor }; AZ_Verify(serializeContext->EnumerateInstanceConst - ( sourceGraph->GetGraphData() + ( graphData , azrtti_typeid() - , assetFilter + , dependencyGrabber , {} , AZ::SerializeContext::ENUM_ACCESS_FOR_READ , nullptr @@ -81,13 +107,12 @@ namespace ScriptCanvasEditor // Flush asset database events to ensure no asset references are held by closures queued on Ebuses. AZ::Data::AssetManager::Instance().DispatchEvents(); - */ } AZ::Data::Asset Modifier::LoadAsset() { AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().GetAsset - (GetCurrentAsset().m_assetId + ( GetCurrentAsset().m_assetId , azrtti_typeid() , AZ::Data::AssetLoadBehavior::PreLoad); @@ -116,5 +141,109 @@ namespace ScriptCanvasEditor break; } } + + const AZStd::unordered_set* Modifier::Sorter::GetDependencies(size_t index) const + { + auto iter = modifier->m_dependencies.find(index); + return iter != modifier->m_dependencies.end() ? &iter->second : nullptr; + } + + void Modifier::Sorter::Sort() + { + for (size_t index = 0; index != modifier->m_assets.size(); ++index) + { + Visit(index); + } + /* + L ← Empty list that will contain the sorted nodes + (m_dependencyOrderedAssetIndicies) + + while exists nodes without a permanent mark do + select an unmarked node n + visit(n) + */ + } + + void Modifier::Sorter::Visit(size_t index) + { + if (markedPermanent.contains(index)) + { + return; + } + + if (markedTemporary.contains(index)) + { + AZ_Error + ( ScriptCanvas::k_VersionExplorerWindow.data() + , false + , "Modifier: Dependency sort has failed during, circular dependency detected for Asset: %s" + , modifier->GetCurrentAsset().m_relativePath.c_str()); + return; + } + + markedTemporary.insert(index); + + if (auto dependencies = GetDependencies(index)) + { + for (auto& dependency : *dependencies) + { + Visit(dependency); + } + } + + markedTemporary.erase(index); + markedPermanent.insert(index); + modifier->m_dependencyOrderedAssetIndicies.push_back(index); + } + + void Modifier::SortGraphsByDependencies() + { + m_dependencyOrderedAssetIndicies.reserve(m_assets.size()); + Sorter sorter; + sorter.modifier = this; + sorter.Sort(); + } + + void Modifier::TickGatherDependencies() + { + if (m_assetIndex == 0) + { + if (m_config.successfulDependencyUpgradeRequired) + { + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeAllDependencySortBegin); + m_assetInfoIndexById.reserve(m_assets.size()); + + for (size_t index = 0; index != m_assets.size(); ++index) + { + m_assetInfoIndexById.insert({ m_assets[index].m_assetId.m_guid, index }); + } + } + else + { + m_dependencyOrderedAssetIndicies.reserve(m_assets.size()); + + for (size_t index = 0; index != m_assets.size(); ++index) + { + m_dependencyOrderedAssetIndicies.push_back(index); + } + } + } + + if (m_assetIndex == m_assets.size()) + { + SortGraphsByDependencies(); + ModelNotificationsBus::Broadcast + ( &ModelNotificationsTraits::OnUpgradeAllDependencySortEnd + , m_assets + , m_dependencyOrderedAssetIndicies); + m_assetIndex = 0; + m_state = State::ModifyingGraphs; + } + else + { + GatherDependencies(); + ++m_assetIndex; + } + } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h index b862de82f0..e0b1f1a289 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -28,6 +28,20 @@ namespace ScriptCanvasEditor , AZStd::function onComplete); private: + friend class Sorter; + + struct Sorter + { + Modifier* modifier; + AZStd::unordered_set markedPermanent; + AZStd::unordered_set markedTemporary; + void Sort(); + + private: + void Visit(size_t index); + const AZStd::unordered_set* GetDependencies(size_t index) const; + }; + enum class State { GatheringDependencies, @@ -37,15 +51,20 @@ namespace ScriptCanvasEditor State m_state = State::GatheringDependencies; size_t m_assetIndex = 0; AZStd::function m_onComplete; + // asset infos in scanned order AZStd::vector m_assets; - AZStd::vector m_dependencyOrderedIndicies; + // dependency sorted order indices into the asset vector + AZStd::vector m_dependencyOrderedAssetIndicies; + // dependency indices by asset info index (only exist if graphs have them) AZStd::unordered_map> m_dependencies; + AZStd::unordered_map m_assetInfoIndexById; AZStd::vector m_failures; ModifyConfiguration m_config; ModificationResult m_result; void GatherDependencies(); const AZ::Data::AssetInfo& GetCurrentAsset() const; + AZStd::unordered_set& GetOrCreateDependencyIndexSet(); AZ::Data::Asset LoadAsset(); void SortGraphsByDependencies(); void OnSystemTick() override; From 0dfcc1ea42708d12c4d68103908f83ae3fad523d Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 15 Sep 2021 12:25:06 -0700 Subject: [PATCH 12/24] dependency sort finished, UI updated Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/View/Windows/MainWindow.cpp | 23 +- .../Windows/Tools/UpgradeTool/Controller.cpp | 200 +++++++++++++++--- .../Windows/Tools/UpgradeTool/Controller.h | 28 ++- .../Windows/Tools/UpgradeTool/ModelTraits.h | 24 ++- .../Windows/Tools/UpgradeTool/Modifier.cpp | 122 ++++++----- 5 files changed, 287 insertions(+), 110 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 6c10726e13..ee539aa5fa 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -3435,25 +3435,20 @@ namespace ScriptCanvasEditor void MainWindow::RunUpgradeTool() { - // \todo, restore this behavior, post modification step - - /* auto versionExplorer = aznew VersionExplorer::Controller(this); versionExplorer->exec(); - - + // update and fix this // Manual correction - size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); - - // If there are graphs that need manual correction, show the helper - if (assetsThatNeedManualInspection > 0) - { - UpgradeHelper* upgradeHelper = new UpgradeHelper(this); - upgradeHelper->show(); - } - */ +// size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); +// // If there are graphs that need manual correction, show the helper +// if (assetsThatNeedManualInspection > 0) +// { +// UpgradeHelper* upgradeHelper = new UpgradeHelper(this); +// upgradeHelper->show(); +// } + delete versionExplorer; } void MainWindow::OnShowValidationErrors() diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 8eae0e1bd0..c8353b1d25 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -54,7 +54,7 @@ namespace ScriptCanvasEditor m_view->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); connect(m_view->scanButton, &QPushButton::pressed, this, &Controller::OnScanButtonPress); connect(m_view->closeButton, &QPushButton::pressed, this, &Controller::OnCloseButtonPress); - connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnUpgradeAllButtonPress); + connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnUpgradeButtonPress); m_view->progressBar->setValue(0); m_view->progressBar->setVisible(false); @@ -130,7 +130,7 @@ namespace ScriptCanvasEditor void Controller::OnScanBegin(size_t assetCount) { - m_currentAssetRowIndex = 0; + m_handledAssetCount = 0; m_view->tableWidget->setRowCount(0); m_view->progressBar->setVisible(true); m_view->progressBar->setRange(0, aznumeric_cast(assetCount)); @@ -138,6 +138,10 @@ namespace ScriptCanvasEditor m_view->scanButton->setEnabled(false); m_view->upgradeAllButton->setEnabled(false); m_view->onlyShowOutdated->setEnabled(false); + + QString spinnerText = QStringLiteral("Scan in progress - gathering graphs that can be updated"); + m_view->spinner->SetText(spinnerText); + SetSpinnerIsBusy(true); } void Controller::OnScanComplete(const ScanResult& result) @@ -161,6 +165,7 @@ namespace ScriptCanvasEditor , result.m_filteredAssets.size())); m_view->spinner->SetText(spinnerText); + SetSpinnerIsBusy(false); m_view->progressBar->setVisible(false); if (!result.m_unfiltered.empty()) @@ -176,17 +181,17 @@ namespace ScriptCanvasEditor void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, Filtered filtered) { - m_view->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + m_view->tableWidget->insertRow(m_handledAssetCount); QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str())); - m_view->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + m_view->tableWidget->setItem(m_handledAssetCount, static_cast(ColumnAsset), rowName); + SetRowSucceeded(m_handledAssetCount); if (filtered == Filtered::No) { QPushButton* rowGoToButton = new QPushButton(this); rowGoToButton->setText("Upgrade"); rowGoToButton->setEnabled(false); - AzQtComponents::StyledBusyLabel* spinner = new AzQtComponents::StyledBusyLabel(this); - spinner->SetBusyIconSize(16); + SetRowBusy(m_handledAssetCount); // \\ todo restore this // connect(rowGoToButton, &QPushButton::clicked, [this, rowGoToButton, assetInfo] { // @@ -200,8 +205,7 @@ namespace ScriptCanvasEditor // // }); - m_view->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); - m_view->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); + m_view->tableWidget->setCellWidget(m_handledAssetCount, static_cast(ColumnAction), rowGoToButton); } char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; @@ -234,23 +238,24 @@ namespace ScriptCanvasEditor AzQtComponents::ShowFileOnDesktop(absolutePath); }); - m_view->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); + m_view->tableWidget->setCellWidget(m_handledAssetCount, static_cast(ColumnBrowse), browseButton); OnScannedGraphResult(assetInfo); } void Controller::OnScannedGraphResult([[maybe_unused]] const AZ::Data::AssetInfo& info) { - m_view->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); - ++m_currentAssetRowIndex; + m_view->progressBar->setValue(aznumeric_cast(m_handledAssetCount)); + ++m_handledAssetCount; AddLogEntries(); } void Controller::OnScanLoadFailure(const AZ::Data::AssetInfo& info) { - m_view->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); + m_view->tableWidget->insertRow(m_handledAssetCount); QTableWidgetItem* rowName = new QTableWidgetItem ( tr(AZStd::string::format("Load Error: %s", info.m_relativePath.c_str()).c_str())); - m_view->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + m_view->tableWidget->setItem(m_handledAssetCount, static_cast(ColumnAsset), rowName); + SetRowFailed(m_handledAssetCount, "Load failed"); OnScannedGraphResult(info); } @@ -259,7 +264,7 @@ namespace ScriptCanvasEditor OnScannedGraph(info, Filtered::No); } - void Controller::OnUpgradeAllButtonPress() + void Controller::OnUpgradeButtonPress() { auto simpleUpdate = [this](AZ::Data::Asset asset) { @@ -321,32 +326,167 @@ namespace ScriptCanvasEditor ModelRequestsBus::Broadcast(&ModelRequestsTraits::Modify, config); } - void Controller::OnUpgradeAllBegin() + void Controller::OnUpgradeBegin + ( const ModifyConfiguration& config + , [[maybe_unused]] const AZStd::vector& assets) { - m_currentAssetRowIndex = 0; - m_view->tableWidget->setRowCount(0); + for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) + { + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(false); + SetRowBusy(row); + } + } + + QString spinnerText = QStringLiteral("Upgrade in progress - "); + if (config.modifySingleAsset) + { + spinnerText.append(" single graph"); + } + else + { + spinnerText.append(" all scanned graphs"); + } + + m_view->spinner->SetText(spinnerText); + SetSpinnerIsBusy(true); + } + + void Controller::SetSpinnerIsBusy(bool isBusy) + { + m_view->spinner->SetIsBusy(isBusy); + m_view->spinner->SetBusyIconSize(16); + } + + void Controller::OnUpgradeComplete() + { + SetSpinnerIsBusy(false); + } + + void Controller::OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) + { + QList items = m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + + if (result == Result::Success) + { + SetRowSucceeded(row); + } + else + { + SetRowFailed(row, ""); + } + } + } + m_view->progressBar->setVisible(true); + ++m_handledAssetCount; + m_view->progressBar->setValue(m_handledAssetCount); + } + + void Controller::OnUpgradeDependencySortBegin + ( [[maybe_unused]] const ModifyConfiguration& config + , const AZStd::vector& assets) + { + m_handledAssetCount = 0; + m_view->progressBar->setVisible(true); + m_view->progressBar->setRange(0, aznumeric_caster(assets.size())); m_view->progressBar->setValue(0); m_view->scanButton->setEnabled(false); m_view->upgradeAllButton->setEnabled(false); m_view->onlyShowOutdated->setEnabled(false); + + for (int row = 0; row != m_view->tableWidget->rowCount(); ++row) + { + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(false); + SetRowBusy(row); + } + } + + QString spinnerText = QStringLiteral("Upgrade in progress - gathering dependencies for the scanned graphs"); + m_view->spinner->SetText(spinnerText); + SetSpinnerIsBusy(true); } - void Controller::OnUpgradeAllComplete() - { - - } - - void Controller::OnUpgradeAllDependencySortBegin() - { - - } - - void Controller::OnUpgradeAllDependencySortEnd - ( const AZStd::vector& sortedAssets + void Controller::OnUpgradeDependencySortEnd + ( [[maybe_unused]] const ModifyConfiguration& config + , const AZStd::vector& assets , [[maybe_unused]] const AZStd::vector& sortedOrder) { - m_view->progressBar->setRange(0, aznumeric_cast(sortedAssets.size())); + m_handledAssetCount = 0; + m_view->progressBar->setRange(0, aznumeric_caster(assets.size())); + m_view->progressBar->setValue(0); + m_view->progressBar->setVisible(true); + + for (int row = 0; row != m_view->tableWidget->rowCount(); ++row) + { + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(false); + SetRowPending(row); + } + } + + QString spinnerText = QStringLiteral("Upgrade in progress - gathering dependencies is complete"); + m_view->spinner->SetText(spinnerText); + SetSpinnerIsBusy(false); + } + + void Controller::SetRowBusy(int index) + { + if (index >= m_view->tableWidget->rowCount()) + { + return; + } + + AzQtComponents::StyledBusyLabel* busy = new AzQtComponents::StyledBusyLabel(this); + busy->SetBusyIconSize(16); + m_view->tableWidget->setCellWidget(index, ColumnStatus, busy); + } + + void Controller::SetRowFailed(int index, AZStd::string_view message) + { + if (index >= m_view->tableWidget->rowCount()) + { + return; + } + + QToolButton* doneButton = new QToolButton(this); + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); + doneButton->setToolTip(message.data()); + m_view->tableWidget->setCellWidget(index, ColumnStatus, doneButton); + } + + void Controller::SetRowPending(int index) + { + m_view->tableWidget->removeCellWidget(index, ColumnStatus); + } + + void Controller::SetRowsBusy() + { + for (int i = 0; i != m_view->tableWidget->rowCount(); ++i) + { + SetRowBusy(i); + } + } + + void Controller::SetRowSucceeded(int index) + { + if (index >= m_view->tableWidget->rowCount()) + { + return; + } + + QToolButton* doneButton = new QToolButton(this); + doneButton->setIcon(QIcon(":/stylesheet/img/UI20/checkmark-menu.svg")); + m_view->tableWidget->setCellWidget(index, ColumnStatus, doneButton); } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index e2f00fe6f3..f99aaf5466 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -58,13 +58,13 @@ namespace ScriptCanvasEditor static constexpr int ColumnStatus = 3; AZStd::unique_ptr m_view; - size_t m_currentAssetRowIndex = 0; + int m_handledAssetCount = 0; void AddLogEntries(); void OnCloseButtonPress(); void OnScanButtonPress(); - void OnUpgradeAllButtonPress(); + void OnUpgradeButtonPress(); void OnScanBegin(size_t assetCount) override; void OnScanComplete(const ScanResult& result) override; @@ -74,13 +74,25 @@ namespace ScriptCanvasEditor enum class Filtered { No, Yes }; void OnScannedGraph(const AZ::Data::AssetInfo& info, Filtered filtered); void OnScannedGraphResult(const AZ::Data::AssetInfo& info); - - void OnUpgradeAllBegin() override; - void OnUpgradeAllComplete() override; - void OnUpgradeAllDependencySortBegin() override; - void OnUpgradeAllDependencySortEnd - ( const AZStd::vector& sortedAssets + + // for single operation UI updates, just check the assets size, or note it on the request + void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector& assets) override; + void OnUpgradeComplete() override; + void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) override; + void OnUpgradeDependencySortBegin + ( const ModifyConfiguration& config + , const AZStd::vector& assets) override; + void OnUpgradeDependencySortEnd + ( const ModifyConfiguration& config + , const AZStd::vector& assets , const AZStd::vector& sortedOrder) override; + + void SetSpinnerIsBusy(bool isBusy); + void SetRowBusy(int index); + void SetRowFailed(int index, AZStd::string_view message); + void SetRowPending(int index); + void SetRowsBusy(); + void SetRowSucceeded(int index); }; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index 09ad2b01c1..86e1b47b18 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -17,8 +17,8 @@ namespace ScriptCanvasEditor struct ModifyConfiguration { AZStd::function)> modification; + bool modifySingleAsset = false; bool backupGraphBeforeModification = false; - // disabling this can be acceptable, but be careful bool successfulDependencyUpgradeRequired = true; }; @@ -50,6 +50,12 @@ namespace ScriptCanvasEditor AZStd::vector m_loadErrors; }; + enum Result + { + Failure, + Success + }; + class ModelNotificationsTraits : public AZ::EBusTraits { @@ -60,11 +66,17 @@ namespace ScriptCanvasEditor virtual void OnScanLoadFailure(const AZ::Data::AssetInfo& info) = 0; virtual void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) = 0; - virtual void OnUpgradeAllBegin() = 0; - virtual void OnUpgradeAllComplete() = 0; - virtual void OnUpgradeAllDependencySortBegin() = 0; - virtual void OnUpgradeAllDependencySortEnd - ( const AZStd::vector& assets + virtual void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector& assets) = 0; + virtual void OnUpgradeComplete() = 0; + // virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config) = 0; + // virtual void OnUpgradeModification(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, Result result) = 0; + virtual void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) = 0; + virtual void OnUpgradeDependencySortBegin + ( const ModifyConfiguration& config + , const AZStd::vector& assets) = 0; + virtual void OnUpgradeDependencySortEnd + ( const ModifyConfiguration& config + , const AZStd::vector& assets , const AZStd::vector& sortedOrder) = 0; }; using ModelNotificationsBus = AZ::EBus; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index 1723b0f8ff..5656d6cf6d 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -30,7 +30,7 @@ namespace ScriptCanvasEditor , m_assets(assets) , m_onComplete(onComplete) { - ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeAllBegin); + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeBegin, modification, m_assets); AZ::SystemTickBus::Handler::BusConnect(); } @@ -58,52 +58,64 @@ namespace ScriptCanvasEditor AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); AZ_Assert(serializeContext, "SerializeContext is required to enumerate dependent assets in the ScriptCanvas file"); + bool anyFailures = false; auto asset = LoadAsset(); - if (!asset - || !asset.GetAs() - || !asset.GetAs()->GetScriptCanvasGraph() - || !asset.GetAs()->GetScriptCanvasGraph()->GetGraphData()) - { - VE_LOG("Modifier: Failed to load asset %s for modification, even though it scanned properly"); - return; - } - auto graphData = asset.GetAs()->GetScriptCanvasGraph()->GetGraphData(); - - auto dependencyGrabber = [this] - ( void* instancePointer - , const AZ::SerializeContext::ClassData* classData - , [[maybe_unused]] const AZ::SerializeContext::ClassElement* classElement) + if (asset + && asset.GetAs() + && asset.GetAs()->GetScriptCanvasGraph() + && asset.GetAs()->GetScriptCanvasGraph()->GetGraphData()) { - auto azTypeId = classData->m_azRtti->GetTypeId(); - if (azTypeId == azrtti_typeid>()) + auto graphData = asset.GetAs()->GetScriptCanvasGraph()->GetGraphData(); + + auto dependencyGrabber = [this] + ( void* instancePointer + , const AZ::SerializeContext::ClassData* classData + , [[maybe_unused]] const AZ::SerializeContext::ClassElement* classElement) { - const auto* subgraphAsset = reinterpret_cast*>(instancePointer); - if (subgraphAsset->GetId().IsValid()) + if (auto azTypeId = classData->m_azRtti->GetTypeId(); + azTypeId == azrtti_typeid>()) { - if (auto iter = m_assetInfoIndexById.find(subgraphAsset->GetId().m_guid); iter != m_assetInfoIndexById.end()) + const auto* subgraphAsset = + reinterpret_cast*>(instancePointer); + if (subgraphAsset->GetId().IsValid()) { - GetOrCreateDependencyIndexSet().insert(iter->second); - } - else - { - VE_LOG("Modifier: Dependency found that was not picked up by the scanner: %s" - , subgraphAsset->GetId().ToString().c_str()); + if (auto iter = m_assetInfoIndexById.find(subgraphAsset->GetId().m_guid); iter != m_assetInfoIndexById.end()) + { + // insert the index of the dependency into the set that belongs to this asset + GetOrCreateDependencyIndexSet().insert(iter->second); + } } } - } - // always continue, make note of the script canvas dependencies - return true; - }; + // always continue, make note of the script canvas dependencies + return true; + }; - AZ_Verify(serializeContext->EnumerateInstanceConst - ( graphData - , azrtti_typeid() - , dependencyGrabber - , {} - , AZ::SerializeContext::ENUM_ACCESS_FOR_READ - , nullptr - , nullptr), "Failed to gather dependencies from graph data"); + if (!serializeContext->EnumerateInstanceConst + ( graphData + , azrtti_typeid() + , dependencyGrabber + , {} + , AZ::SerializeContext::ENUM_ACCESS_FOR_READ + , nullptr + , nullptr)) + { + anyFailures = true; + VE_LOG("Modifier: ERROR - Failed to gather dependencies from graph data: %s" + , GetCurrentAsset().m_relativePath.c_str()) + } + } + else + { + anyFailures = true; + VE_LOG("Modifier: ERROR - Failed to load asset %s for modification, even though it scanned properly" + , GetCurrentAsset().m_relativePath.c_str()); + } + + ModelNotificationsBus::Broadcast + ( &ModelNotificationsTraits::OnUpgradeDependenciesGathered + , GetCurrentAsset() + , anyFailures ? Result::Failure : Result::Success); // Flush asset database events to ensure no asset references are held by closures queued on Ebuses. AZ::Data::AssetManager::Instance().DispatchEvents(); @@ -154,14 +166,6 @@ namespace ScriptCanvasEditor { Visit(index); } - /* - L ← Empty list that will contain the sorted nodes - (m_dependencyOrderedAssetIndicies) - - while exists nodes without a permanent mark do - select an unmarked node n - visit(n) - */ } void Modifier::Sorter::Visit(size_t index) @@ -210,7 +214,7 @@ namespace ScriptCanvasEditor { if (m_config.successfulDependencyUpgradeRequired) { - ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeAllDependencySortBegin); + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeDependencySortBegin, m_config, m_assets); m_assetInfoIndexById.reserve(m_assets.size()); for (size_t index = 0; index != m_assets.size(); ++index) @@ -226,16 +230,24 @@ namespace ScriptCanvasEditor { m_dependencyOrderedAssetIndicies.push_back(index); } + + // go straight into ModifyinGraphs + m_assetIndex = m_assets.size(); } } if (m_assetIndex == m_assets.size()) { - SortGraphsByDependencies(); - ModelNotificationsBus::Broadcast - ( &ModelNotificationsTraits::OnUpgradeAllDependencySortEnd - , m_assets - , m_dependencyOrderedAssetIndicies); + if (m_config.successfulDependencyUpgradeRequired) + { + SortGraphsByDependencies(); + ModelNotificationsBus::Broadcast + ( &ModelNotificationsTraits::OnUpgradeDependencySortEnd + , m_config + , m_assets + , m_dependencyOrderedAssetIndicies); + } + m_assetIndex = 0; m_state = State::ModifyingGraphs; } @@ -245,5 +257,11 @@ namespace ScriptCanvasEditor ++m_assetIndex; } } + + void Modifier::TickUpdateGraph() + { + + } + } } From 296fca722e36aab372ee8f43d545c9ef027d5023 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 15 Sep 2021 15:42:54 -0700 Subject: [PATCH 13/24] file save finished, not tested Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/Components/GraphUpgrade.cpp | 2 +- .../ScriptCanvas/Bus/EditorScriptCanvasBus.h | 5 +- .../Widgets/NodePalette/NodePaletteModel.cpp | 4 +- .../Widgets/NodePalette/NodePaletteModel.h | 2 +- .../ScriptCanvasNodePaletteDockWidget.cpp | 4 +- .../ScriptCanvasNodePaletteDockWidget.h | 2 +- .../Code/Editor/View/Windows/MainWindow.h | 6 +- .../Windows/Tools/UpgradeTool/Controller.cpp | 221 ++++++++++++------ .../Windows/Tools/UpgradeTool/Controller.h | 14 +- .../Windows/Tools/UpgradeTool/FileSaver.cpp | 184 +++++++++++++++ .../Windows/Tools/UpgradeTool/FileSaver.h | 25 ++ .../View/Windows/Tools/UpgradeTool/Model.cpp | 2 +- .../View/Windows/Tools/UpgradeTool/Model.h | 3 +- .../Windows/Tools/UpgradeTool/ModelTraits.h | 27 ++- .../Windows/Tools/UpgradeTool/Modifier.cpp | 199 ++++++++++++---- .../View/Windows/Tools/UpgradeTool/Modifier.h | 27 ++- .../View/Windows/Tools/UpgradeTool/Scanner.h | 1 - 17 files changed, 588 insertions(+), 140 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp index e87c82e186..2754cc9777 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp @@ -686,7 +686,7 @@ namespace ScriptCanvasEditor void EditorGraphUpgradeMachine::OnComplete(IState::ExitStatus exitStatus) { - UpgradeNotifications::Bus::Broadcast(&UpgradeNotifications::OnGraphUpgradeComplete, m_asset, exitStatus == IState::ExitStatus::Skipped); + UpgradeNotificationsBus::Broadcast(&UpgradeNotifications::OnGraphUpgradeComplete, m_asset, exitStatus == IState::ExitStatus::Skipped); m_asset = {}; } diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h index 09869ba2eb..7c47c77b3e 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h @@ -236,8 +236,6 @@ namespace ScriptCanvasEditor static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - using Bus = AZ::EBus; - virtual void OnUpgradeStart() {} virtual void OnUpgradeComplete() {} virtual void OnUpgradeCancelled() {} @@ -245,6 +243,5 @@ namespace ScriptCanvasEditor virtual void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) { (void)skipped; } }; - - + using UpgradeNotificationsBus = AZ::EBus; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp index 390dbaf0fb..4602fe5a87 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp @@ -829,12 +829,12 @@ namespace ScriptCanvasEditor NodePaletteModel::NodePaletteModel() : m_paletteId(AZ::Entity::MakeId()) { - UpgradeNotifications::Bus::Handler::BusConnect(); + UpgradeNotificationsBus::Handler::BusConnect(); } NodePaletteModel::~NodePaletteModel() { - UpgradeNotifications::Bus::Handler::BusDisconnect(); + UpgradeNotificationsBus::Handler::BusDisconnect(); DisconnectLambdas(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h index b27bfd97f1..f92ab5142e 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h @@ -61,7 +61,7 @@ namespace ScriptCanvasEditor class NodePaletteModel : public GraphCanvas::CategorizerInterface - , UpgradeNotifications::Bus::Handler + , UpgradeNotificationsBus::Handler { public: typedef AZStd::unordered_map< ScriptCanvas::NodeTypeIdentifier, NodePaletteModelInformation* > NodePaletteRegistry; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp index 96b0ac353f..b60b4f2924 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp @@ -148,7 +148,7 @@ namespace ScriptCanvasEditor , m_assetModel(assetModel) , m_categorizer(nodePaletteModel) { - UpgradeNotifications::Bus::Handler::BusConnect(); + UpgradeNotificationsBus::Handler::BusConnect(); if (m_assetModel) { @@ -166,7 +166,7 @@ namespace ScriptCanvasEditor AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AZ::Data::AssetBus::MultiHandler::BusDisconnect(); - UpgradeNotifications::Bus::Handler::BusDisconnect(); + UpgradeNotificationsBus::Handler::BusDisconnect(); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h index 7b2e9293bd..16beb5b79e 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h @@ -57,7 +57,7 @@ namespace ScriptCanvasEditor : public GraphCanvas::NodePaletteTreeItem , AzFramework::AssetCatalogEventBus::Handler , AZ::Data::AssetBus::MultiHandler - , UpgradeNotifications::Bus::Handler + , UpgradeNotificationsBus::Handler , AZ::SystemTickBus::Handler { public: diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index 1eeb2dadfb..afc413a425 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -98,19 +98,19 @@ namespace ScriptCanvasEditor class ScriptCanvasAssetBrowserModel : public AzToolsFramework::AssetBrowser::AssetBrowserFilterModel - , private UpgradeNotifications::Bus::Handler + , private UpgradeNotificationsBus::Handler { public: explicit ScriptCanvasAssetBrowserModel(QObject* parent = nullptr) : AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent) { - UpgradeNotifications::Bus::Handler::BusConnect(); + UpgradeNotificationsBus::Handler::BusConnect(); } ~ScriptCanvasAssetBrowserModel() override { - UpgradeNotifications::Bus::Handler::BusDisconnect(); + UpgradeNotificationsBus::Handler::BusDisconnect(); } void OnUpgradeStart() override diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index c8353b1d25..f3ea605451 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -52,9 +52,9 @@ namespace ScriptCanvasEditor m_view->tableWidget->setColumnWidth(3, 22); m_view->textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); m_view->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); - connect(m_view->scanButton, &QPushButton::pressed, this, &Controller::OnScanButtonPress); - connect(m_view->closeButton, &QPushButton::pressed, this, &Controller::OnCloseButtonPress); - connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnUpgradeButtonPress); + connect(m_view->scanButton, &QPushButton::pressed, this, &Controller::OnButtonPressScan); + connect(m_view->closeButton, &QPushButton::pressed, this, &Controller::OnButtonPressClose); + connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnButtonPressUpgrade); m_view->progressBar->setValue(0); m_view->progressBar->setVisible(false); @@ -87,12 +87,12 @@ namespace ScriptCanvasEditor LogBus::Broadcast(&LogTraits::Clear); } - void Controller::OnCloseButtonPress() + void Controller::OnButtonPressClose() { reject(); } - void Controller::OnScanButtonPress() + void Controller::OnButtonPressScan() { // \todo move to another file auto isUpToDate = [this](AZ::Data::Asset asset) @@ -128,6 +128,148 @@ namespace ScriptCanvasEditor ModelRequestsBus::Broadcast(&ModelRequestsTraits::Scan, config); } + void Controller::OnButtonPressUpgrade() + { + auto simpleUpdate = [this](AZ::Data::Asset asset) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "View::UpgradeGraph The Script Canvas asset must have a valid entity"); + if (!scriptCanvasEntity) + { + return; + } + + AZ::Entity* queryEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); + if (queryEntity) + { + if (queryEntity->GetState() == AZ::Entity::State::Active) + { + queryEntity->Deactivate(); + } + + scriptCanvasEntity = queryEntity; + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) + { + scriptCanvasEntity->Init(); + } + + if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) + { + scriptCanvasEntity->Activate(); + } + + AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); + auto graphComponent = scriptCanvasEntity->FindComponent(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + if (graphComponent) + { + graphComponent->UpgradeGraph + ( asset + , m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_view->verbose->isChecked()); + } + } + }; + + auto onReadyOnlyFile = [this]()->bool + { + int result = QMessageBox::No; + QMessageBox mb + ( QMessageBox::Warning + , QObject::tr("Failed to Save Upgraded File") + , QObject::tr("The upgraded file could not be saved because the file is read only.\n" + "Do you want to make it writeable and overwrite it?") + , QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No + , this); + result = mb.exec(); + return result == QMessageBox::YesToAll; + }; + + ModifyConfiguration config; + config.modification = simpleUpdate; + config.onReadOnlyFile = onReadyOnlyFile; + config.backupGraphBeforeModification = m_view->makeBackupCheckbox->isChecked(); + ModelRequestsBus::Broadcast(&ModelRequestsTraits::Modify, config); + } + + void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) + { + QList items = m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + SetRowBusy(row); + } + } + } + + void Controller::OnUpgradeModificationEnd + ( [[maybe_unused]] const ModifyConfiguration& config + , const AZ::Data::AssetInfo& info + , ModificationResult result) + { + if (result.errorMessage.empty()) + { + VE_LOG("Successfully modified %s", result.assetInfo.m_relativePath.c_str()); + } + else + { + VE_LOG("Failed to modify %s: %s", result.assetInfo.m_relativePath.c_str(), result.errorMessage.data()); + } + + QList items = m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) + { + for (auto* item : items) + { + int row = item->row(); + + if (result.errorMessage.empty()) + { + SetRowSucceeded(row); + } + else + { + SetRowFailed(row, ""); + } + } + } + + m_view->progressBar->setVisible(true); + ++m_handledAssetCount; + m_view->progressBar->setValue(m_handledAssetCount); + } + + void Controller::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool skipped) + { + ModificationResult result; + result.asset = asset; + AZ::Data::AssetCatalogRequestBus::BroadcastResult + ( result.assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, asset.GetId()); + + if (skipped) + { + result.errorMessage = "Failed in editor upgrade state machine - check logs"; + } + + ModificationNotificationsBus::Broadcast(&ModificationNotificationsTraits::ModificationComplete, result); + } + void Controller::OnScanBegin(size_t assetCount) { m_handledAssetCount = 0; @@ -264,68 +406,6 @@ namespace ScriptCanvasEditor OnScannedGraph(info, Filtered::No); } - void Controller::OnUpgradeButtonPress() - { - auto simpleUpdate = [this](AZ::Data::Asset asset) - { - if (asset.GetType() == azrtti_typeid()) - { - ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" - , azrtti_typeid().template ToString().c_str()); - if (!scriptCanvasAsset) - { - return; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "View::UpgradeGraph The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return; - } - - AZ::Entity* queryEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId()); - if (queryEntity) - { - if (queryEntity->GetState() == AZ::Entity::State::Active) - { - queryEntity->Deactivate(); - } - - scriptCanvasEntity = queryEntity; - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed) - { - scriptCanvasEntity->Init(); - } - - if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init) - { - scriptCanvasEntity->Activate(); - } - - AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active"); - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - if (graphComponent) - { - graphComponent->UpgradeGraph - ( asset - , m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate - , m_view->verbose->isChecked()); - } - } - }; - - ModifyConfiguration config; - config.modification = simpleUpdate; - config.backupGraphBeforeModification = m_view->makeBackupCheckbox->isChecked(); - ModelRequestsBus::Broadcast(&ModelRequestsTraits::Modify, config); - } - void Controller::OnUpgradeBegin ( const ModifyConfiguration& config , [[maybe_unused]] const AZStd::vector& assets) @@ -359,8 +439,13 @@ namespace ScriptCanvasEditor m_view->spinner->SetBusyIconSize(16); } - void Controller::OnUpgradeComplete() + void Controller::OnUpgradeComplete(const ModificationResults& result) { + QString spinnerText = QStringLiteral("Upgrade Complete - "); + spinnerText.append(QString::asprintf(" - Upgraded: %zu, Failed: %zu" + , result.m_successes.size() + , result.m_failures.size())); + m_view->spinner->SetText(spinnerText); SetSpinnerIsBusy(false); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index f99aaf5466..1b8b109759 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -41,7 +41,7 @@ namespace ScriptCanvasEditor //! Handles display change notifications, handles state change notifications, sends control requests class Controller : public AzQtComponents::StyledDialog - , private UpgradeNotifications::Bus::Handler + , private UpgradeNotificationsBus::Handler , private ModelNotificationsBus::Handler { Q_OBJECT @@ -62,10 +62,12 @@ namespace ScriptCanvasEditor void AddLogEntries(); - void OnCloseButtonPress(); - void OnScanButtonPress(); - void OnUpgradeButtonPress(); + void OnButtonPressClose(); + void OnButtonPressScan(); + void OnButtonPressUpgrade(); + void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped) override; + void OnScanBegin(size_t assetCount) override; void OnScanComplete(const ScanResult& result) override; void OnScanFilteredGraph(const AZ::Data::AssetInfo& info) override; @@ -77,7 +79,7 @@ namespace ScriptCanvasEditor // for single operation UI updates, just check the assets size, or note it on the request void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector& assets) override; - void OnUpgradeComplete() override; + void OnUpgradeComplete(const ModificationResults& results) override; void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) override; void OnUpgradeDependencySortBegin ( const ModifyConfiguration& config @@ -86,6 +88,8 @@ namespace ScriptCanvasEditor ( const ModifyConfiguration& config , const AZStd::vector& assets , const AZStd::vector& sortedOrder) override; + void OnUpgradeModificationBegin(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) override; + void OnUpgradeModificationEnd(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, ModificationResult result) override; void SetSpinnerIsBusy(bool isBusy); void SetRowBusy(int index); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp index 7a7c4fe5a3..f067feeca4 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp @@ -6,8 +6,15 @@ * */ +#include +#include #include +#include +#include +#include +#include #include +#include namespace FileSaverCpp { @@ -44,6 +51,183 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + FileSaver::FileSaver + ( AZStd::function onReadOnlyFile + , AZStd::function onComplete) + : m_onReadOnlyFile(onReadOnlyFile) + , m_onComplete(onComplete) + {} + void FileSaver::PerformMove + ( AZStd::string tmpFileName + , AZStd::string target + , size_t remainingAttempts) + { + FileSaverCpp::FileEventHandler fileEventHandler; + + if (remainingAttempts == 0) + { + AZ::SystemTickBus::QueueFunction([this, tmpFileName]() + { + FileSaveResult result; + result.fileSaveError = "Failed to move updated file from temporary location to tmpFileName destination"; + result.tempFileRemovalError = RemoveTempFile(tmpFileName); + m_onComplete(result); + }); + } + else if (remainingAttempts == 2) + { + auto streamer = AZ::Interface::Get(); + // before the last attempt, flush all the caches + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); + streamer->SetRequestCompleteCallback(flushRequest + , [this, remainingAttempts, tmpFileName, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // One last try + AZ::SystemTickBus::QueueFunction( + [this, remainingAttempts, tmpFileName, target]() { PerformMove(tmpFileName, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + else + { + // the actual move attempt + auto moveResult = AZ::IO::SmartMove(tmpFileName.c_str(), target.c_str()); + if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) + { + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + // Bump the slice asset up in the asset processor's queue. + AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); + AZ::SystemTickBus::QueueFunction([this, tmpFileName]() + { + FileSaveResult result; + result.tempFileRemovalError = RemoveTempFile(tmpFileName); + m_onComplete(result); + }); + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to tmpFileName destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + streamer->SetRequestCompleteCallback(flushRequest, [this, tmpFileName, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction([this, tmpFileName, target, remainingAttempts]() { PerformMove(tmpFileName, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); + } + } + } + + void FileSaver::OnSourceFileReleased(AZ::Data::Asset asset) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath); + AZStd::string tmpFileName; + // here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file. + // This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP. + if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) + { + FileSaveResult result; + result.fileSaveError = "Failure to create temporary file name"; + m_onComplete(result); + return; + } + + bool tempSavedSucceeded = false; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + if (fileStream.IsOpen()) + { + if (asset.GetType() == azrtti_typeid()) + { + ScriptCanvasEditor::ScriptCanvasAssetHandler handler; + tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); + } + + fileStream.Close(); + } + + if (!tempSavedSucceeded) + { + FileSaveResult result; + result.fileSaveError = "Save asset data to temporary file failed"; + m_onComplete(result); + return; + } + + AzToolsFramework::SourceControlCommandBus::Broadcast + ( &AzToolsFramework::SourceControlCommandBus::Events::RequestEdit + , fullPath.c_str() + , true + , [this, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + { + constexpr const size_t k_maxAttemps = 10; + + if (!info.IsReadOnly()) + { + PerformMove(tmpFileName, fullPath, k_maxAttemps); + } + else if (m_onReadOnlyFile && m_onReadOnlyFile()) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(tmpFileName, fullPath, k_maxAttemps); + } + else + { + FileSaveResult result; + result.fileSaveError = "Source file was and remained read-only"; + result.tempFileRemovalError = RemoveTempFile(tmpFileName); + m_onComplete(result); + } + }); + } + + AZStd::string FileSaver::RemoveTempFile(AZStd::string_view tempFile) + { + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + if (!fileIO) + { + return "GraphUpgradeComplete: No FileIO instance"; + } + + if (fileIO->Exists(tempFile.data()) && !fileIO->Remove(tempFile.data())) + { + return AZStd::string::format("Failed to remove temporary file: %s", tempFile.data()); + } + + return ""; + } + + void FileSaver::Save(AZ::Data::Asset asset) + { + AZStd::string relativePath, fullPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); + bool fullPathFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult + (fullPathFound + , &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath + , relativePath, fullPath); + + if (!fullPathFound) + { + FileSaveResult result; + result.fileSaveError = "Full source path not found"; + m_onComplete(result); + } + else + { + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + this->OnSourceFileReleased(asset); + }); + streamer->QueueRequest(flushRequest); + } + } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h index e1ab92acbc..dd333927ed 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h @@ -14,10 +14,35 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + struct FileSaveResult + { + AZStd::string fileSaveError; + AZStd::string tempFileRemovalError; + }; + class FileSaver { public: AZ_CLASS_ALLOCATOR(FileSaver, AZ::SystemAllocator, 0); + + FileSaver + ( AZStd::function onReadOnlyFile + , AZStd::function onComplete); + + void Save(AZ::Data::Asset asset); + + private: + AZStd::function m_onComplete; + AZStd::function m_onReadOnlyFile; + + void OnSourceFileReleased(AZ::Data::Asset asset); + + void PerformMove + ( AZStd::string source + , AZStd::string target + , size_t remainingAttempts); + + AZStd::string RemoveTempFile(AZStd::string_view tempFile); }; } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp index ad9d39cb98..b88d147d6d 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp @@ -103,7 +103,7 @@ namespace ScriptCanvasEditor void Model::OnModificationComplete() { - ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanComplete, m_scanner->GetResult()); + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeComplete, m_modifier->GetResult()); m_modifier.reset(); m_scanner.reset(); Idle(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h index 72ab210e37..637c77648a 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h @@ -57,7 +57,8 @@ namespace ScriptCanvasEditor State m_state = State::Idle; Log m_log; - + + // these two are managed by the same class because the modifer will only operate on the results of the scanner AZStd::unique_ptr m_modifier; AZStd::unique_ptr m_scanner; AZStd::unique_ptr m_settingsCache; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index 86e1b47b18..6eedba647f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -17,11 +17,27 @@ namespace ScriptCanvasEditor struct ModifyConfiguration { AZStd::function)> modification; + AZStd::function onReadOnlyFile; bool modifySingleAsset = false; bool backupGraphBeforeModification = false; bool successfulDependencyUpgradeRequired = true; }; + struct ModificationResult + { + AZ::Data::Asset asset; + AZ::Data::AssetInfo assetInfo; + AZStd::string errorMessage; + }; + + class ModificationNotificationsTraits + : public AZ::EBusTraits + { + public: + virtual void ModificationComplete(const ModificationResult& result) = 0; + }; + using ModificationNotificationsBus = AZ::EBus; + struct ScanConfiguration { AZStd::function)> filter; @@ -37,9 +53,10 @@ namespace ScriptCanvasEditor }; using ModelRequestsBus = AZ::EBus; - struct ModificationResult + struct ModificationResults { - + AZStd::vector m_successes; + AZStd::vector m_failures; }; struct ScanResult @@ -67,9 +84,7 @@ namespace ScriptCanvasEditor virtual void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) = 0; virtual void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector& assets) = 0; - virtual void OnUpgradeComplete() = 0; - // virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config) = 0; - // virtual void OnUpgradeModification(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, Result result) = 0; + virtual void OnUpgradeComplete(const ModificationResults& results) = 0; virtual void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) = 0; virtual void OnUpgradeDependencySortBegin ( const ModifyConfiguration& config @@ -78,6 +93,8 @@ namespace ScriptCanvasEditor ( const ModifyConfiguration& config , const AZStd::vector& assets , const AZStd::vector& sortedOrder) = 0; + virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) = 0; + virtual void OnUpgradeModificationEnd(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, ModificationResult result) = 0; }; using ModelNotificationsBus = AZ::EBus; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index 5656d6cf6d..4096508b8b 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -30,6 +30,7 @@ namespace ScriptCanvasEditor , m_assets(assets) , m_onComplete(onComplete) { + AZ_Assert(m_config.modification, "No modification function provided"); ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeBegin, modification, m_assets); AZ::SystemTickBus::Handler::BusConnect(); } @@ -52,6 +53,11 @@ namespace ScriptCanvasEditor return iter->second; } + const ModificationResults& Modifier::GetResult() const + { + return m_results; + } + void Modifier::GatherDependencies() { AZ::SerializeContext* serializeContext{}; @@ -140,6 +146,84 @@ namespace ScriptCanvasEditor } } + void Modifier::ModificationComplete(const ModificationResult& result) + { + m_result = result; + + if (result.errorMessage.empty()) + { + SaveModifiedGraph(result); + } + else + { + ReportModificationError(result.errorMessage); + } + } + + void Modifier::ModifyCurrentAsset() + { + m_result = {}; + m_result.assetInfo = GetCurrentAsset(); + + ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeModificationBegin, m_config, GetCurrentAsset()); + + if (auto asset = LoadAsset()) + { + ModificationNotificationsBus::Handler::BusConnect(); + m_modifyState = ModifyState::InProgress; + m_config.modification(asset); + } + else + { + ReportModificationError("Failed to load during modification"); + } + } + + void Modifier::ModifyNextAsset() + { + ModelNotificationsBus::Broadcast + ( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, GetCurrentAsset(), m_result); + m_modifyState = ModifyState::Idle; + ++m_assetIndex; + m_result = {}; + } + + void Modifier::ReportModificationError(AZStd::string_view report) + { + m_result.asset = {}; + m_result.errorMessage = report; + m_results.m_failures.push_back(m_result); + ModifyNextAsset(); + } + + void Modifier::ReportModificationSuccess() + { + m_results.m_successes.push_back(m_result.assetInfo); + ModifyNextAsset(); + } + + void Modifier::OnFileSaveComplete(const FileSaveResult& result) + { + if (!result.tempFileRemovalError.empty()) + { + VE_LOG + ( "Temporary file not removed for %s: %s" + , m_result.assetInfo.m_relativePath.c_str() + , result.tempFileRemovalError.c_str()); + } + + m_fileSaver.reset(); + + if (result.fileSaveError.empty()) + { + ReportModificationSuccess(); + } + else + { + ReportModificationError(result.fileSaveError); + } + } + void Modifier::OnSystemTick() { switch (m_state) @@ -154,50 +238,13 @@ namespace ScriptCanvasEditor } } - const AZStd::unordered_set* Modifier::Sorter::GetDependencies(size_t index) const + void Modifier::SaveModifiedGraph(const ModificationResult& result) { - auto iter = modifier->m_dependencies.find(index); - return iter != modifier->m_dependencies.end() ? &iter->second : nullptr; - } - - void Modifier::Sorter::Sort() - { - for (size_t index = 0; index != modifier->m_assets.size(); ++index) - { - Visit(index); - } - } - - void Modifier::Sorter::Visit(size_t index) - { - if (markedPermanent.contains(index)) - { - return; - } - - if (markedTemporary.contains(index)) - { - AZ_Error - ( ScriptCanvas::k_VersionExplorerWindow.data() - , false - , "Modifier: Dependency sort has failed during, circular dependency detected for Asset: %s" - , modifier->GetCurrentAsset().m_relativePath.c_str()); - return; - } - - markedTemporary.insert(index); - - if (auto dependencies = GetDependencies(index)) - { - for (auto& dependency : *dependencies) - { - Visit(dependency); - } - } - - markedTemporary.erase(index); - markedPermanent.insert(index); - modifier->m_dependencyOrderedAssetIndicies.push_back(index); + m_modifyState = ModifyState::Saving; + m_fileSaver = AZStd::make_unique + ( m_config.onReadOnlyFile + , [this](const FileSaveResult& result) { OnFileSaveComplete(result); }); + m_fileSaver->Save(result.asset); } void Modifier::SortGraphsByDependencies() @@ -208,6 +255,11 @@ namespace ScriptCanvasEditor sorter.Sort(); } + ModificationResults&& Modifier::TakeResult() + { + return AZStd::move(m_results); + } + void Modifier::TickGatherDependencies() { if (m_assetIndex == 0) @@ -260,8 +312,69 @@ namespace ScriptCanvasEditor void Modifier::TickUpdateGraph() { + if (m_assetIndex == m_assets.size()) + { + VE_LOG("Modifier: Complete."); + AZ::SystemTickBus::Handler::BusDisconnect(); + if (m_onComplete) + { + m_onComplete(); + } + } + else + { + if (m_modifyState == ModifyState::Idle) + { + ModifyCurrentAsset(); + } + } } + const AZStd::unordered_set* Modifier::Sorter::GetDependencies(size_t index) const + { + auto iter = modifier->m_dependencies.find(index); + return iter != modifier->m_dependencies.end() ? &iter->second : nullptr; + } + + void Modifier::Sorter::Sort() + { + for (size_t index = 0; index != modifier->m_assets.size(); ++index) + { + Visit(index); + } + } + + void Modifier::Sorter::Visit(size_t index) + { + if (markedPermanent.contains(index)) + { + return; + } + + if (markedTemporary.contains(index)) + { + AZ_Error + (ScriptCanvas::k_VersionExplorerWindow.data() + , false + , "Modifier: Dependency sort has failed during, circular dependency detected for Asset: %s" + , modifier->GetCurrentAsset().m_relativePath.c_str()); + return; + } + + markedTemporary.insert(index); + + if (auto dependencies = GetDependencies(index)) + { + for (auto& dependency : *dependencies) + { + Visit(dependency); + } + } + + markedTemporary.erase(index); + markedPermanent.insert(index); + modifier->m_dependencyOrderedAssetIndicies.push_back(index); + } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h index e0b1f1a289..f318627cbe 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -8,9 +8,10 @@ #pragma once -#include -#include #include +#include +#include +#include namespace ScriptCanvasEditor { @@ -18,6 +19,7 @@ namespace ScriptCanvasEditor { class Modifier : private AZ::SystemTickBus::Handler + , private ModificationNotificationsBus::Handler { public: AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0); @@ -27,6 +29,9 @@ namespace ScriptCanvasEditor , AZStd::vector&& assets , AZStd::function onComplete); + const ModificationResults& GetResult() const; + ModificationResults&& TakeResult(); + private: friend class Sorter; @@ -48,7 +53,16 @@ namespace ScriptCanvasEditor ModifyingGraphs }; + enum class ModifyState + { + Idle, + InProgress, + Saving, + }; + + // the two states reside in this class because the modification is only complete if the new source file saves out State m_state = State::GatheringDependencies; + ModifyState m_modifyState = ModifyState::Idle; size_t m_assetIndex = 0; AZStd::function m_onComplete; // asset infos in scanned order @@ -61,12 +75,21 @@ namespace ScriptCanvasEditor AZStd::vector m_failures; ModifyConfiguration m_config; ModificationResult m_result; + ModificationResults m_results; + AZStd::unique_ptr m_fileSaver; void GatherDependencies(); const AZ::Data::AssetInfo& GetCurrentAsset() const; AZStd::unordered_set& GetOrCreateDependencyIndexSet(); AZ::Data::Asset LoadAsset(); + void ModifyCurrentAsset(); + void ModifyNextAsset(); + void ModificationComplete(const ModificationResult& result) override; + void ReportModificationError(AZStd::string_view report); + void ReportModificationSuccess(); + void SaveModifiedGraph(const ModificationResult& result); void SortGraphsByDependencies(); + void OnFileSaveComplete(const FileSaveResult& result); void OnSystemTick() override; void TickGatherDependencies(); void TickUpdateGraph(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h index 8b4dd69c82..fb030845c7 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.h @@ -25,7 +25,6 @@ namespace ScriptCanvasEditor Scanner(const ScanConfiguration& config, AZStd::function onComplete); const ScanResult& GetResult() const; - ScanResult&& TakeResult(); private: From 9196e98ee6e2057f3543525fad2a33e7d81cfb30 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 15 Sep 2021 17:03:16 -0700 Subject: [PATCH 14/24] update reporting and logging and make bug fixes Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/Components/GraphUpgrade.cpp | 4 +- .../ScriptCanvas/Bus/EditorScriptCanvasBus.h | 14 ---- .../ScriptCanvas/Components/GraphUpgrade.h | 5 ++ .../Code/Editor/View/Windows/MainWindow.cpp | 18 ++--- .../Windows/Tools/UpgradeTool/Controller.cpp | 15 ++-- .../Windows/Tools/UpgradeTool/Controller.h | 11 +-- .../View/Windows/Tools/UpgradeTool/Model.cpp | 9 +++ .../View/Windows/Tools/UpgradeTool/Model.h | 4 + .../Windows/Tools/UpgradeTool/ModelTraits.h | 59 ++++++++------- .../Windows/Tools/UpgradeTool/Modifier.cpp | 9 ++- .../View/Windows/Tools/UpgradeTool/Modifier.h | 4 +- .../Windows/Tools/UpgradeTool/Scanner.cpp | 2 +- .../Tools/UpgradeTool/UpgradeHelper.cpp | 74 ++++++++++--------- 13 files changed, 122 insertions(+), 106 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp index 2754cc9777..0e5f11fa40 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp @@ -519,7 +519,7 @@ namespace ScriptCanvasEditor if (validationResults.HasErrors()) { - AZ::Interface::Get()->GraphNeedsManualUpgrade(sm->m_asset.GetId()); + sm->MarkError("Failed to Parse"); for (auto& err : validationResults.GetEvents()) { @@ -735,7 +735,7 @@ namespace ScriptCanvasEditor { AZ::SystemTickBus::Handler::BusDisconnect(); - OnComplete(exitStatus); + OnComplete(m_error.empty() ? exitStatus : IState::ExitStatus::Skipped); } } diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h index 7c47c77b3e..02edce4974 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h @@ -215,20 +215,6 @@ namespace ScriptCanvasEditor using EditorLoggingComponentNotificationBus = AZ::EBus; - class IUpgradeRequests - { - public: - AZ_TYPE_INFO(IUpgradeRequests, "{D25318F2-4DDA-4E76-98CB-6D561BB6234D}"); - - using AssetList = AZStd::list; - - virtual void ClearGraphsThatNeedUpgrade() = 0; - virtual void GraphNeedsManualUpgrade(const AZ::Data::AssetId&) = 0; - virtual const AZStd::vector& GetGraphsThatNeedManualUpgrade() const = 0; - virtual bool IsUpgrading() = 0; - virtual void SetIsUpgrading(bool isUpgrading) = 0; - }; - class UpgradeNotifications : public AZ::EBusTraits { diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h index 89ee0f3b55..f67bc11244 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h @@ -133,18 +133,23 @@ namespace ScriptCanvasEditor bool GetVerbose() const; + const AZStd::string GetError() const { return m_error; } + void SetVerbose(bool isVerbose); const AZStd::string& GetDebugPrefix() const; void SetDebugPrefix(AZStd::string_view); + void MarkError(AZStd::string_view error) { m_error = error; } + AZStd::shared_ptr m_currentState = nullptr; AZStd::vector> m_states; private: bool m_isVerbose = true; AZStd::string m_debugPrefix; + AZStd::string m_error; }; //! This state machine will collect and share a variety of data from the EditorGraph diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index ee539aa5fa..4da806f2e8 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -3435,18 +3435,18 @@ namespace ScriptCanvasEditor void MainWindow::RunUpgradeTool() { + using namespace VersionExplorer; auto versionExplorer = aznew VersionExplorer::Controller(this); versionExplorer->exec(); - // update and fix this - // Manual correction -// size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); -// // If there are graphs that need manual correction, show the helper -// if (assetsThatNeedManualInspection > 0) -// { -// UpgradeHelper* upgradeHelper = new UpgradeHelper(this); -// upgradeHelper->show(); -// } + const ModificationResults* result = nullptr; + ModelRequestsBus::BroadcastResult(result, &ModelRequestsTraits::GetResults); + if (result && !result->m_failures.empty()) + { + // If there are graphs that need manual correction, show the helper + UpgradeHelper* upgradeHelper = new UpgradeHelper(this); + upgradeHelper->show(); + } delete versionExplorer; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index f3ea605451..9d7224373f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -58,6 +58,7 @@ namespace ScriptCanvasEditor m_view->progressBar->setValue(0); m_view->progressBar->setVisible(false); + UpgradeNotificationsBus::Handler::BusConnect(); ModelNotificationsBus::Handler::BusConnect(); } @@ -78,8 +79,8 @@ namespace ScriptCanvasEditor for (auto& entry : *logs) { - auto line = "\n" + entry; - textCursor.insertText(line.c_str()); + textCursor.insertText("\n"); + textCursor.insertText(entry.c_str()); } scrollBar->setValue(scrollBar->maximum()); @@ -253,6 +254,7 @@ namespace ScriptCanvasEditor m_view->progressBar->setVisible(true); ++m_handledAssetCount; m_view->progressBar->setValue(m_handledAssetCount); + AddLogEntries(); } void Controller::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool skipped) @@ -408,7 +410,7 @@ namespace ScriptCanvasEditor void Controller::OnUpgradeBegin ( const ModifyConfiguration& config - , [[maybe_unused]] const AZStd::vector& assets) + , [[maybe_unused]] const WorkingAssets& assets) { for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) { @@ -447,6 +449,7 @@ namespace ScriptCanvasEditor , result.m_failures.size())); m_view->spinner->SetText(spinnerText); SetSpinnerIsBusy(false); + AddLogEntries(); } void Controller::OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) @@ -472,11 +475,12 @@ namespace ScriptCanvasEditor m_view->progressBar->setVisible(true); ++m_handledAssetCount; m_view->progressBar->setValue(m_handledAssetCount); + AddLogEntries(); } void Controller::OnUpgradeDependencySortBegin ( [[maybe_unused]] const ModifyConfiguration& config - , const AZStd::vector& assets) + , const WorkingAssets& assets) { m_handledAssetCount = 0; m_view->progressBar->setVisible(true); @@ -502,7 +506,7 @@ namespace ScriptCanvasEditor void Controller::OnUpgradeDependencySortEnd ( [[maybe_unused]] const ModifyConfiguration& config - , const AZStd::vector& assets + , const WorkingAssets& assets , [[maybe_unused]] const AZStd::vector& sortedOrder) { m_handledAssetCount = 0; @@ -522,6 +526,7 @@ namespace ScriptCanvasEditor QString spinnerText = QStringLiteral("Upgrade in progress - gathering dependencies is complete"); m_view->spinner->SetText(spinnerText); SetSpinnerIsBusy(false); + AddLogEntries(); } void Controller::SetRowBusy(int index) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index 1b8b109759..0fb3ce1bf4 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -50,7 +50,7 @@ namespace ScriptCanvasEditor AZ_CLASS_ALLOCATOR(Controller, AZ::SystemAllocator, 0); explicit Controller(QWidget* parent = nullptr); - + private: static constexpr int ColumnAsset = 0; static constexpr int ColumnAction = 1; @@ -61,7 +61,6 @@ namespace ScriptCanvasEditor int m_handledAssetCount = 0; void AddLogEntries(); - void OnButtonPressClose(); void OnButtonPressScan(); void OnButtonPressUpgrade(); @@ -78,15 +77,13 @@ namespace ScriptCanvasEditor void OnScannedGraphResult(const AZ::Data::AssetInfo& info); // for single operation UI updates, just check the assets size, or note it on the request - void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector& assets) override; + void OnUpgradeBegin(const ModifyConfiguration& config, const WorkingAssets& assets) override; void OnUpgradeComplete(const ModificationResults& results) override; void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) override; - void OnUpgradeDependencySortBegin - ( const ModifyConfiguration& config - , const AZStd::vector& assets) override; + void OnUpgradeDependencySortBegin(const ModifyConfiguration& config, const WorkingAssets& assets) override; void OnUpgradeDependencySortEnd ( const ModifyConfiguration& config - , const AZStd::vector& assets + , const WorkingAssets& assets , const AZStd::vector& sortedOrder) override; void OnUpgradeModificationBegin(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) override; void OnUpgradeModificationEnd(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, ModificationResult result) override; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp index b88d147d6d..ed17293ab7 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp @@ -61,10 +61,16 @@ namespace ScriptCanvasEditor ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; } + const ModificationResults* Model::GetResults() + { + return !IsWorking() ? &m_modResults : nullptr; + } + void Model::Idle() { m_state = State::Idle; m_keepEditorAlive.reset(); + m_log.Deactivate(); } bool Model::IsReadyToModify() const @@ -95,7 +101,9 @@ namespace ScriptCanvasEditor return; } + m_modResults = {}; m_state = State::Modifying; + m_log.Activate(); m_keepEditorAlive = AZStd::make_unique(); auto results = m_scanner->TakeResult(); m_modifier = AZStd::make_unique(modification, AZStd::move(results.m_unfiltered), [this](){ OnModificationComplete(); }); @@ -124,6 +132,7 @@ namespace ScriptCanvasEditor } m_state = State::Scanning; + m_log.Activate(); m_keepEditorAlive = AZStd::make_unique(); m_scanner = AZStd::make_unique(config, [this](){ OnScanComplete(); }); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h index 637c77648a..e11f8857e7 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h @@ -43,6 +43,8 @@ namespace ScriptCanvasEditor Model(); + const ModificationResults* GetResults() override; + void Modify(const ModifyConfiguration& modification) override; void Scan(const ScanConfiguration& config) override; @@ -64,6 +66,8 @@ namespace ScriptCanvasEditor AZStd::unique_ptr m_settingsCache; AZStd::unique_ptr m_keepEditorAlive; + ModificationResults m_modResults; + void CacheSettings(); void Idle(); bool IsReadyToModify() const; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index 6eedba647f..026748c344 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -14,6 +14,14 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { + struct WorkingAsset + { + AZ::Data::Asset asset; + AZ::Data::AssetInfo info; + }; + + using WorkingAssets = AZStd::vector; + struct ModifyConfiguration { AZStd::function)> modification; @@ -30,13 +38,11 @@ namespace ScriptCanvasEditor AZStd::string errorMessage; }; - class ModificationNotificationsTraits - : public AZ::EBusTraits + struct ModificationResults { - public: - virtual void ModificationComplete(const ModificationResult& result) = 0; + AZStd::vector m_successes; + AZStd::vector m_failures; }; - using ModificationNotificationsBus = AZ::EBus; struct ScanConfiguration { @@ -44,25 +50,10 @@ namespace ScriptCanvasEditor bool reportFilteredGraphs = false; }; - class ModelRequestsTraits - : public AZ::EBusTraits - { - public: - virtual void Modify(const ModifyConfiguration& modification) = 0; - virtual void Scan(const ScanConfiguration& filter) = 0; - }; - using ModelRequestsBus = AZ::EBus; - - struct ModificationResults - { - AZStd::vector m_successes; - AZStd::vector m_failures; - }; - struct ScanResult { AZStd::vector m_catalogAssets; - AZStd::vector m_unfiltered; + WorkingAssets m_unfiltered; AZStd::vector m_filteredAssets; AZStd::vector m_loadErrors; }; @@ -73,6 +64,24 @@ namespace ScriptCanvasEditor Success }; + class ModificationNotificationsTraits + : public AZ::EBusTraits + { + public: + virtual void ModificationComplete(const ModificationResult& result) = 0; + }; + using ModificationNotificationsBus = AZ::EBus; + + class ModelRequestsTraits + : public AZ::EBusTraits + { + public: + virtual const ModificationResults* GetResults() = 0; + virtual void Modify(const ModifyConfiguration& modification) = 0; + virtual void Scan(const ScanConfiguration& filter) = 0; + }; + using ModelRequestsBus = AZ::EBus; + class ModelNotificationsTraits : public AZ::EBusTraits { @@ -83,15 +92,13 @@ namespace ScriptCanvasEditor virtual void OnScanLoadFailure(const AZ::Data::AssetInfo& info) = 0; virtual void OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info) = 0; - virtual void OnUpgradeBegin(const ModifyConfiguration& config, const AZStd::vector& assets) = 0; + virtual void OnUpgradeBegin(const ModifyConfiguration& config, const WorkingAssets& assets) = 0; virtual void OnUpgradeComplete(const ModificationResults& results) = 0; virtual void OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) = 0; - virtual void OnUpgradeDependencySortBegin - ( const ModifyConfiguration& config - , const AZStd::vector& assets) = 0; + virtual void OnUpgradeDependencySortBegin(const ModifyConfiguration& config, const WorkingAssets& assets) = 0; virtual void OnUpgradeDependencySortEnd ( const ModifyConfiguration& config - , const AZStd::vector& assets + , const WorkingAssets& assets , const AZStd::vector& sortedOrder) = 0; virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) = 0; virtual void OnUpgradeModificationEnd(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, ModificationResult result) = 0; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index 4096508b8b..1bd33bbe49 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -23,7 +23,7 @@ namespace ScriptCanvasEditor { Modifier::Modifier ( const ModifyConfiguration& modification - , AZStd::vector&& assets + , WorkingAssets&& assets , AZStd::function onComplete) : m_state(State::GatheringDependencies) , m_config(modification) @@ -38,8 +38,8 @@ namespace ScriptCanvasEditor const AZ::Data::AssetInfo& Modifier::GetCurrentAsset() const { return m_state == State::GatheringDependencies - ? m_assets[m_assetIndex] - : m_assets[m_dependencyOrderedAssetIndicies[m_assetIndex]]; + ? m_assets[m_assetIndex].info + : m_assets[m_dependencyOrderedAssetIndicies[m_assetIndex]].info; } AZStd::unordered_set& Modifier::GetOrCreateDependencyIndexSet() @@ -183,6 +183,7 @@ namespace ScriptCanvasEditor { ModelNotificationsBus::Broadcast ( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, GetCurrentAsset(), m_result); + ModificationNotificationsBus::Handler::BusDisconnect(); m_modifyState = ModifyState::Idle; ++m_assetIndex; m_result = {}; @@ -271,7 +272,7 @@ namespace ScriptCanvasEditor for (size_t index = 0; index != m_assets.size(); ++index) { - m_assetInfoIndexById.insert({ m_assets[index].m_assetId.m_guid, index }); + m_assetInfoIndexById.insert({ m_assets[index].info.m_assetId.m_guid, index }); } } else diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h index f318627cbe..2a8a12e3cf 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -26,7 +26,7 @@ namespace ScriptCanvasEditor Modifier ( const ModifyConfiguration& modification - , AZStd::vector&& assets + , WorkingAssets&& assets , AZStd::function onComplete); const ModificationResults& GetResult() const; @@ -66,7 +66,7 @@ namespace ScriptCanvasEditor size_t m_assetIndex = 0; AZStd::function m_onComplete; // asset infos in scanned order - AZStd::vector m_assets; + WorkingAssets m_assets; // dependency sorted order indices into the asset vector AZStd::vector m_dependencyOrderedAssetIndicies; // dependency indices by asset info index (only exist if graphs have them) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp index 26765a9f97..bc69f6e634 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Scanner.cpp @@ -45,7 +45,7 @@ namespace ScriptCanvasEditor else { VE_LOG("Scanner: Included: %s ", GetCurrentAsset().m_relativePath.c_str()); - m_result.m_unfiltered.push_back(GetCurrentAsset()); + m_result.m_unfiltered.push_back({ asset, GetCurrentAsset() }); ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanUnFilteredGraph, GetCurrentAsset()); } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp index 9670bb2f1f..14bc1c4dc8 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.cpp @@ -6,37 +6,32 @@ * */ +#include +#include #include #include -#include #include -#include #include -#include "UpgradeHelper.h" - #include #include #include #include - #include #include - +#include +#include #include #include #include - -#include - +#include #include +#include +#include #include #include - #include #include -#include -#include namespace ScriptCanvasEditor { @@ -52,40 +47,47 @@ namespace ScriptCanvasEditor m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); int rows = 0; - auto& graphsToUpgrade = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade(); - for (auto& assetId : graphsToUpgrade) + const VersionExplorer::ModificationResults* result = nullptr; + VersionExplorer::ModelRequestsBus::BroadcastResult(result, &VersionExplorer::ModelRequestsTraits::GetResults); + + if (result && !result->m_failures.empty()) { - auto assetInfo = ScriptCanvasEditor::AssetHelpers::GetAssetInfo(assetId); - m_ui->tableWidget->insertRow(rows); + for (auto& failedUpdate : result->m_failures) + { + auto& assetInfo = failedUpdate.assetInfo; + auto assetId = assetInfo.m_assetId; - connect(m_ui->closeButton, &QPushButton::pressed, this, &QDialog::accept); - connect(m_ui->tableWidget, &QTableWidget::itemDoubleClicked, this, [this, rows, assetId](QTableWidgetItem* item) - { - if (item && item->data(Qt::UserRole).toInt() == rows) + m_ui->tableWidget->insertRow(rows); + + connect(m_ui->closeButton, &QPushButton::pressed, this, &QDialog::accept); + connect(m_ui->tableWidget, &QTableWidget::itemDoubleClicked, this, [this, rows, assetId](QTableWidgetItem* item) { - OpenGraph(assetId); + if (item && item->data(Qt::UserRole).toInt() == rows) + { + OpenGraph(assetId); + } } - } - ); + ); - auto openGraph = [this, assetId] { - OpenGraph(assetId); - }; + auto openGraph = [this, assetId] { + OpenGraph(assetId); + }; - QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str())); - rowName->setData(Qt::UserRole, rows); - m_ui->tableWidget->setItem(rows, 0, rowName); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str())); + rowName->setData(Qt::UserRole, rows); + m_ui->tableWidget->setItem(rows, 0, rowName); - QToolButton* rowGoToButton = new QToolButton(this); - rowGoToButton->setIcon(QIcon(":/stylesheet/img/UI20/open-in-internal-app.svg")); - rowGoToButton->setToolTip("Open Graph"); - - connect(rowGoToButton, &QToolButton::clicked, openGraph); + QToolButton* rowGoToButton = new QToolButton(this); + rowGoToButton->setIcon(QIcon(":/stylesheet/img/UI20/open-in-internal-app.svg")); + rowGoToButton->setToolTip("Open Graph"); - m_ui->tableWidget->setCellWidget(rows, 1, rowGoToButton); + connect(rowGoToButton, &QToolButton::clicked, openGraph); - ++rows; + m_ui->tableWidget->setCellWidget(rows, 1, rowGoToButton); + + ++rows; + } } } From e125462eaaaadbd9c0762784100b52bfef8935c2 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 24 Sep 2021 11:56:42 -0700 Subject: [PATCH 15/24] Set logging preference before running tools Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Editor/View/Windows/Tools/UpgradeTool/Controller.cpp | 8 ++++++++ .../Editor/View/Windows/Tools/UpgradeTool/Controller.h | 1 + .../Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp | 3 +++ 3 files changed, 12 insertions(+) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 9d7224373f..4e4e842cb8 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -126,6 +126,7 @@ namespace ScriptCanvasEditor config.reportFilteredGraphs = !m_view->onlyShowOutdated->isChecked(); config.filter = isUpToDate; + SetLoggingPreferences(); ModelRequestsBus::Broadcast(&ModelRequestsTraits::Scan, config); } @@ -199,6 +200,7 @@ namespace ScriptCanvasEditor return result == QMessageBox::YesToAll; }; + SetLoggingPreferences(); ModifyConfiguration config; config.modification = simpleUpdate; config.onReadOnlyFile = onReadyOnlyFile; @@ -435,6 +437,12 @@ namespace ScriptCanvasEditor SetSpinnerIsBusy(true); } + void Controller::SetLoggingPreferences() + { + LogBus::Broadcast(&LogTraits::SetVerbose, m_view->verbose->isChecked()); + LogBus::Broadcast(&LogTraits::SetVersionExporerExclusivity, m_view->updateReportingOnly->isChecked()); + } + void Controller::SetSpinnerIsBusy(bool isBusy) { m_view->spinner->SetIsBusy(isBusy); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index 0fb3ce1bf4..fd297832bb 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -88,6 +88,7 @@ namespace ScriptCanvasEditor void OnUpgradeModificationBegin(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) override; void OnUpgradeModificationEnd(const ModifyConfiguration& config, const AZ::Data::AssetInfo& info, ModificationResult result) override; + void SetLoggingPreferences(); void SetSpinnerIsBusy(bool isBusy); void SetRowBusy(int index); void SetRowFailed(int index, AZStd::string_view message); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index 1bd33bbe49..3c62670ef0 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -237,6 +237,9 @@ namespace ScriptCanvasEditor TickUpdateGraph(); break; } + + AZ::Data::AssetManager::Instance().DispatchEvents(); + AZ::SystemTickBus::ExecuteQueuedEvents(); } void Modifier::SaveModifiedGraph(const ModificationResult& result) From 619948231a9f67f7b687a89bdce80fc4154f9dbb Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Thu, 30 Sep 2021 14:26:27 -0700 Subject: [PATCH 16/24] fix compile error from bad automatic merge Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Editor/SystemComponent.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h index 0b085a7e8d..6f85b3c5a6 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h @@ -97,8 +97,7 @@ namespace ScriptCanvasEditor //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - void ClearGraphsThatNeedUpgrade() - + private: SystemComponent(const SystemComponent&) = delete; From 2185505302e7a80dbb0c441a44d7df487711b98e Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Thu, 30 Sep 2021 14:59:11 -0700 Subject: [PATCH 17/24] Repair upgrade notification after bad automatic merge Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h | 1 - .../Editor/View/Widgets/NodePalette/NodePaletteModel.h | 4 ---- .../View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp | 9 --------- .../View/Widgets/ScriptCanvasNodePaletteDockWidget.h | 1 - Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h | 5 ----- 5 files changed, 20 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h index 02edce4974..7e7b600081 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h @@ -223,7 +223,6 @@ namespace ScriptCanvasEditor static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; virtual void OnUpgradeStart() {} - virtual void OnUpgradeComplete() {} virtual void OnUpgradeCancelled() {} virtual void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) { (void)skipped; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h index f92ab5142e..28d627af01 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.h @@ -104,10 +104,6 @@ namespace ScriptCanvasEditor { DisconnectLambdas(); } - void OnUpgradeComplete() override - { - ConnectLambdas(); - } // Asset Node Support void OnRowsInserted(const QModelIndex& parentIndex, int first, int last); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp index b60b4f2924..9e51c1896f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp @@ -386,15 +386,6 @@ namespace ScriptCanvasEditor AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } - void ScriptCanvasRootPaletteTreeItem::OnUpgradeComplete() - { - ConnectLambdas(); - - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - - TraverseTree(); - } - void ScriptCanvasRootPaletteTreeItem::OnUpgradeCancelled() { if (!AzFramework::AssetCatalogEventBus::Handler::BusIsConnected()) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h index 16beb5b79e..45645ceb33 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h @@ -92,7 +92,6 @@ namespace ScriptCanvasEditor // UpgradeNotifications::Bus void OnUpgradeStart() override; - void OnUpgradeComplete() override; void OnUpgradeCancelled() override; //// diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index f8703cc5c5..244d9dcd72 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -117,11 +117,6 @@ namespace ScriptCanvasEditor { AzToolsFramework::AssetBrowser::AssetBrowserComponentNotificationBus::Handler::BusDisconnect(); } - - void OnUpgradeComplete() override - { - AzToolsFramework::AssetBrowser::AssetBrowserComponentNotificationBus::Handler::BusConnect(); - } }; class OnSaveToast From a52faa7340f7ed85e6de370db21462fe0f33e74d Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 4 Oct 2021 13:03:55 -0700 Subject: [PATCH 18/24] Fixed qthread error coming from file i/o thread Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/Modifier.cpp | 41 ++++++++++++++----- .../View/Windows/Tools/UpgradeTool/Modifier.h | 5 +++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp index 3c62670ef0..f3da1ba309 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -203,6 +203,24 @@ namespace ScriptCanvasEditor ModifyNextAsset(); } + void Modifier::ReportSaveResult() + { + AZStd::lock_guard lock(m_mutex); + m_fileSaver.reset(); + + if (m_fileSaveResult.fileSaveError.empty()) + { + ReportModificationSuccess(); + } + else + { + ReportModificationError(m_fileSaveResult.fileSaveError); + } + + m_fileSaveResult = {}; + m_modifyState = ModifyState::Idle; + } + void Modifier::OnFileSaveComplete(const FileSaveResult& result) { if (!result.tempFileRemovalError.empty()) @@ -213,16 +231,10 @@ namespace ScriptCanvasEditor , result.tempFileRemovalError.c_str()); } + AZStd::lock_guard lock(m_mutex); + m_modifyState = ModifyState::ReportResult; m_fileSaver.reset(); - - if (result.fileSaveError.empty()) - { - ReportModificationSuccess(); - } - else - { - ReportModificationError(result.fileSaveError); - } + m_fileSaveResult = result; } void Modifier::OnSystemTick() @@ -328,9 +340,18 @@ namespace ScriptCanvasEditor } else { - if (m_modifyState == ModifyState::Idle) + AZStd::lock_guard lock(m_mutex); + + switch (m_modifyState) { + case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::Idle: ModifyCurrentAsset(); + break; + case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::ReportResult: + ReportSaveResult(); + break; + default: + break; } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h index 2a8a12e3cf..981a1eb746 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.h @@ -58,8 +58,11 @@ namespace ScriptCanvasEditor Idle, InProgress, Saving, + ReportResult }; + AZStd::recursive_mutex m_mutex; + // the two states reside in this class because the modification is only complete if the new source file saves out State m_state = State::GatheringDependencies; ModifyState m_modifyState = ModifyState::Idle; @@ -77,6 +80,7 @@ namespace ScriptCanvasEditor ModificationResult m_result; ModificationResults m_results; AZStd::unique_ptr m_fileSaver; + FileSaveResult m_fileSaveResult; void GatherDependencies(); const AZ::Data::AssetInfo& GetCurrentAsset() const; @@ -87,6 +91,7 @@ namespace ScriptCanvasEditor void ModificationComplete(const ModificationResult& result) override; void ReportModificationError(AZStd::string_view report); void ReportModificationSuccess(); + void ReportSaveResult(); void SaveModifiedGraph(const ModificationResult& result); void SortGraphsByDependencies(); void OnFileSaveComplete(const FileSaveResult& result); From a870c6ad80a77a03a4869f79595c448f99b9091b Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 5 Oct 2021 09:52:52 -0700 Subject: [PATCH 19/24] Fix explorer bugs and restore upgrade single option Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../ScriptCanvasBuilderWorkerUtility.cpp | 2 + .../Windows/Tools/UpgradeTool/Controller.cpp | 36 ++++++++------- .../Windows/Tools/UpgradeTool/Controller.h | 2 + .../View/Windows/Tools/UpgradeTool/Model.cpp | 24 +++++++++- .../Windows/Tools/UpgradeTool/ModelTraits.h | 2 +- .../Libraries/Core/ReceiveScriptEvent.cpp | 27 +++++------ .../Libraries/Core/ReceiveScriptEvent.h | 3 +- .../Libraries/Core/ScriptEventBase.cpp | 7 +-- .../ScriptCanvas/Translation/GraphToLua.cpp | 11 +++-- .../ScriptCanvas/Translation/GraphToX.cpp | 45 ++++++++++--------- .../ScriptCanvas/Translation/GraphToX.h | 5 ++- .../Translation/TranslationResult.cpp | 9 ++++ .../Translation/TranslationResult.h | 8 ++-- 13 files changed, 113 insertions(+), 68 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp index 0853789b19..665a481a17 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp @@ -113,6 +113,7 @@ namespace ScriptCanvasBuilder if (!isSuccessOutcome.IsSuccess()) { + // sanity check return AZ::Failure(isSuccessOutcome.TakeError()); } auto& translation = translationResult.m_translations.find(ScriptCanvas::Translation::TargetFlags::Lua)->second; @@ -481,6 +482,7 @@ namespace ScriptCanvasBuilder buildEntity->Activate(); } + AZ_Assert(buildEntity->GetState() == AZ::Entity::State::Active, "build entity not active"); return sourceGraph; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 4e4e842cb8..207f70aec1 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -131,6 +131,11 @@ namespace ScriptCanvasEditor } void Controller::OnButtonPressUpgrade() + { + OnButtonPressUpgradeImplementation({}); + } + + void Controller::OnButtonPressUpgradeImplementation(const AZ::Data::AssetInfo& assetInfo) { auto simpleUpdate = [this](AZ::Data::Asset asset) { @@ -202,12 +207,18 @@ namespace ScriptCanvasEditor SetLoggingPreferences(); ModifyConfiguration config; + config.modifySingleAsset = assetInfo; config.modification = simpleUpdate; config.onReadOnlyFile = onReadyOnlyFile; config.backupGraphBeforeModification = m_view->makeBackupCheckbox->isChecked(); ModelRequestsBus::Broadcast(&ModelRequestsTraits::Modify, config); } + void Controller::OnButtonPressUpgradeSingle(const AZ::Data::AssetInfo& assetInfo) + { + OnButtonPressUpgradeImplementation(assetInfo); + } + void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) { QList items = m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); @@ -325,7 +336,7 @@ namespace ScriptCanvasEditor OnScannedGraph(info, Filtered::Yes); } - void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, Filtered filtered) + void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] Filtered filtered) { m_view->tableWidget->insertRow(m_handledAssetCount); QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str())); @@ -338,19 +349,14 @@ namespace ScriptCanvasEditor rowGoToButton->setText("Upgrade"); rowGoToButton->setEnabled(false); SetRowBusy(m_handledAssetCount); -// \\ todo restore this -// connect(rowGoToButton, &QPushButton::clicked, [this, rowGoToButton, assetInfo] { -// -// // request upgrade of a single graph -// // AZ::SystemTickBus::QueueFunction([this, rowGoToButton, assetInfo]() { -// // // Queue the process state change because we can't connect to the SystemTick bus in a Qt lambda -// // UpgradeSingle(rowGoToButton, spinner, assetInfo); -// // }); -// // -// // AZ::SystemTickBus::ExecuteQueuedEvents(); -// -// }); - + connect + ( rowGoToButton + , &QPushButton::pressed + , this + , [this, assetInfo]() + { + this->OnButtonPressUpgradeSingle(assetInfo); + }); m_view->tableWidget->setCellWidget(m_handledAssetCount, static_cast(ColumnAction), rowGoToButton); } @@ -424,7 +430,7 @@ namespace ScriptCanvasEditor } QString spinnerText = QStringLiteral("Upgrade in progress - "); - if (config.modifySingleAsset) + if (config.modifySingleAsset.m_assetId.IsValid()) { spinnerText.append(" single graph"); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index fd297832bb..23f35840be 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -64,6 +64,8 @@ namespace ScriptCanvasEditor void OnButtonPressClose(); void OnButtonPressScan(); void OnButtonPressUpgrade(); + void OnButtonPressUpgradeImplementation(const AZ::Data::AssetInfo& assetInfo); + void OnButtonPressUpgradeSingle(const AZ::Data::AssetInfo& assetInfo); void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped) override; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp index ed17293ab7..98edef54bf 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp @@ -101,11 +101,33 @@ namespace ScriptCanvasEditor return; } + auto results = m_scanner->TakeResult(); + if (modification.modifySingleAsset.m_assetId.IsValid()) + { + auto iter = AZStd::find_if + ( results.m_unfiltered.begin() + , results.m_unfiltered.end() + , [&modification](const auto& candidate) + { + return candidate.info.m_assetId == modification.modifySingleAsset.m_assetId; + }); + + if (iter == results.m_unfiltered.end()) + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Requested upgrade graph not found in scanned list."); + return; + } + + WorkingAsset singleEntry = *iter; + results.m_unfiltered.clear(); + results.m_unfiltered.push_back(singleEntry); + } + m_modResults = {}; m_state = State::Modifying; m_log.Activate(); m_keepEditorAlive = AZStd::make_unique(); - auto results = m_scanner->TakeResult(); + m_modifier = AZStd::make_unique(modification, AZStd::move(results.m_unfiltered), [this](){ OnModificationComplete(); }); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h index 026748c344..01eb200542 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h @@ -26,7 +26,7 @@ namespace ScriptCanvasEditor { AZStd::function)> modification; AZStd::function onReadOnlyFile; - bool modifySingleAsset = false; + AZ::Data::AssetInfo modifySingleAsset; bool backupGraphBeforeModification = false; bool successfulDependencyUpgradeRequired = true; }; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp index 5a2eb80187..c548176af5 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp @@ -67,7 +67,7 @@ namespace ScriptCanvas void ReceiveScriptEvent::PopulateAsset(AZ::Data::Asset asset, SlotIdMapping& populationMapping) { - if (CreateHandler(asset)) + if (InitializeDefinition(asset)) { if (!CreateEbus()) { @@ -140,7 +140,6 @@ namespace ScriptCanvas } } - void ReceiveScriptEvent::InitializeEvent(AZ::Data::Asset asset, int eventIndex, SlotIdMapping& populationMapping) { if (!m_handler) @@ -353,6 +352,13 @@ namespace ScriptCanvas AZStd::optional ReceiveScriptEvent::GetEventIndex(AZStd::string eventName) const { + if (!m_handler) + { + const_cast(this)->InitializeDefinition(m_asset); + const_cast(this)->CreateEbus(); + } + + AZ_Error("ScriptCanvas", m_handler != nullptr, "GetEventIndex called and handler was not created"); return m_handler ? AZStd::optional(m_handler->GetFunctionIndex(eventName.c_str())) : AZStd::nullopt; } @@ -490,15 +496,10 @@ namespace ScriptCanvas return m_definition.IsAddressRequired() || (slot && slot->GetDataType().IsValid()); } - bool ReceiveScriptEvent::CreateHandler(AZ::Data::Asset asset) + bool ReceiveScriptEvent::InitializeDefinition(AZ::Data::Asset asset) { AZStd::lock_guard lock(m_mutex); - if (m_handler) - { - return true; - } - if (!asset) { return false; @@ -518,12 +519,11 @@ namespace ScriptCanvas } return true; - } void ReceiveScriptEvent::OnScriptEventReady(const AZ::Data::Asset& asset) { - if (CreateHandler(asset)) + if (InitializeDefinition(asset)) { CompleteInitialize(asset); } @@ -531,7 +531,7 @@ namespace ScriptCanvas bool ReceiveScriptEvent::CreateEbus() { - if (!m_ebus) + if (!m_ebus || !m_handler) { AZ::BehaviorContext* behaviorContext = nullptr; AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationBus::Events::GetBehaviorContext); @@ -547,13 +547,11 @@ namespace ScriptCanvas AZ_Assert(m_ebus, "Behavior Context EBus does not exist: %s", m_definition.GetName().c_str()); AZ_Assert(m_ebus->m_createHandler, "The ebus %s has no create handler!", m_definition.GetName().c_str()); AZ_Assert(m_ebus->m_destroyHandler, "The ebus %s has no destroy handler!", m_definition.GetName().c_str()); - AZ_Verify(m_ebus->m_createHandler->InvokeResult(m_handler, &m_definition), "Behavior Context EBus handler creation failed %s", m_definition.GetName().c_str()); - AZ_Assert(m_handler, "Ebus create handler failed %s", m_definition.GetName().c_str()); } - return true; + return m_ebus != nullptr && m_handler != nullptr; } bool ReceiveScriptEvent::IsOutOfDate(const VersionData& graphVersion) const @@ -597,7 +595,6 @@ namespace ScriptCanvas } } - AZStd::string ReceiveScriptEvent::GetUpdateString() const { if (m_ebus) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h index 0f8d673629..a41d0ba3f9 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h @@ -101,7 +101,7 @@ namespace ScriptCanvas Internal::ScriptEventEntry ConfigureEbusEntry(const ScriptEvents::Method& methodDefinition, const AZ::BehaviorEBusHandler::BusForwarderEvent& event, SlotIdMapping& populationMapping); - bool CreateHandler(AZ::Data::Asset asset); + bool InitializeDefinition(AZ::Data::Asset asset); void CompleteInitialize(AZ::Data::Asset asset); void PopulateAsset(AZ::Data::Asset asset, SlotIdMapping& populationMapping); bool m_eventInitComplete = false; @@ -120,7 +120,6 @@ namespace ScriptCanvas bool m_autoConnectToGraphOwner = true; bool m_connected; - }; } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ScriptEventBase.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ScriptEventBase.cpp index 3b01a8fa7c..e4cbfc94f7 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ScriptEventBase.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ScriptEventBase.cpp @@ -122,11 +122,8 @@ namespace ScriptCanvas void ScriptEventBase::OnActivate() { - if (!m_asset || m_asset.GetStatus() == AZ::Data::AssetData::AssetStatus::NotLoaded) - { - m_asset = AZ::Data::AssetManager::Instance().GetAsset(m_scriptEventAssetId, AZ::Data::AssetLoadBehavior::PreLoad); - m_asset.BlockUntilLoadComplete(); - } + m_asset = AZ::Data::AssetManager::Instance().GetAsset(m_scriptEventAssetId, AZ::Data::AssetLoadBehavior::PreLoad); + m_asset.BlockUntilLoadComplete(); } void ScriptEventBase::OnAssetReady(AZ::Data::Asset asset) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp index 9a1ef73126..ee7eb704bb 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp @@ -246,8 +246,7 @@ namespace ScriptCanvas } else { - ErrorList errors = { AZStd::string("provide translation failure details") }; - return AZ::Failure(errors); + return AZ::Failure(translation.MoveErrors()); } } @@ -874,7 +873,13 @@ namespace ScriptCanvas AZStd::optional eventIndex = ebusHandling->m_node->GetEventIndex(nameAndEventThread.first); if (!eventIndex) { - AddError(nullptr, aznew Internal::ParseError(ebusHandling->m_node->GetEntityId(), AZStd::string::format("EBus handler did not return a valid index for event %s", nameAndEventThread.first.c_str()))); + AddError(nullptr, + aznew Internal::ParseError( + ebusHandling->m_node->GetEntityId() + , AZStd::string::format + ( "EBus Handler %s did not return a valid index for event %s" + , ebusHandling->m_ebusName.c_str() + , nameAndEventThread.first.c_str()))); return; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.cpp index 09315ec4b0..d21fb354b1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.cpp @@ -107,27 +107,9 @@ namespace ScriptCanvas m_translationDuration = AZStd::chrono::microseconds(AZStd::chrono::system_clock::now() - m_translationStartTime).count(); } - AZStd::string GraphToX::ResolveScope(const AZStd::vector& namespaces) + AZStd::vector&& GraphToX::MoveErrors() { - AZStd::string resolution; - - if (!namespaces.empty()) - { - resolution = Grammar::ToIdentifier(namespaces[0]); - - for (size_t index = 1; index < namespaces.size(); ++index) - { - resolution += m_configuration.m_lexicalScopeDelimiter; - resolution += Grammar::ToIdentifier(namespaces[index]); - } - } - - return resolution; - } - - void GraphToX::SingleLineComment(Writer& writer) - { - writer.Write(m_configuration.m_singleLineComment); + return AZStd::move(m_errors); } void GraphToX::OpenBlockComment(Writer& writer) @@ -160,6 +142,29 @@ namespace ScriptCanvas writer.Indent(); } + AZStd::string GraphToX::ResolveScope(const AZStd::vector& namespaces) + { + AZStd::string resolution; + + if (!namespaces.empty()) + { + resolution = Grammar::ToIdentifier(namespaces[0]); + + for (size_t index = 1; index < namespaces.size(); ++index) + { + resolution += m_configuration.m_lexicalScopeDelimiter; + resolution += Grammar::ToIdentifier(namespaces[index]); + } + } + + return resolution; + } + + void GraphToX::SingleLineComment(Writer& writer) + { + writer.Write(m_configuration.m_singleLineComment); + } + void GraphToX::WriteCopyright(Writer& writer) { OpenBlockComment(writer); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.h index 062a58efe1..c4e189679a 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToX.h @@ -51,12 +51,13 @@ namespace ScriptCanvas AZStd::string_view GetGraphName() const; AZStd::string_view GetFullPath() const; AZStd::sys_time_t GetTranslationDuration() const; - AZStd::string ResolveScope(const AZStd::vector& namespaces); - void SingleLineComment(Writer& writer); + AZStd::vector&& MoveErrors(); void OpenBlockComment(Writer& writer); void OpenFunctionBlock(Writer& writer); void OpenNamespace(Writer& writer, AZStd::string_view ns); void OpenScope(Writer& writer); + AZStd::string ResolveScope(const AZStd::vector& namespaces); + void SingleLineComment(Writer& writer); void WriteCopyright(Writer& writer); void WriteDoNotModify(Writer& writer); void WriteLastWritten(Writer& writer); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.cpp index dd8b42730d..c39cac13a3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.cpp @@ -72,6 +72,15 @@ namespace ScriptCanvas resultString += entry->GetDescription(); } + for (const auto& errors : m_errors) + { + for (auto& entry : errors.second) + { + resultString += "* "; + resultString += entry->GetDescription(); + } + } + return resultString; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.h index 0cde56d5dd..bd616fbfbb 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/TranslationResult.h @@ -12,10 +12,11 @@ #include #include #include -#include #include -#include +#include +#include #include +#include namespace AZ { @@ -85,7 +86,7 @@ namespace ScriptCanvas AZStd::sys_time_t m_duration; }; - using ErrorList = AZStd::vector; + using ErrorList = AZStd::vector; using Errors = AZStd::unordered_map; using Translations = AZStd::unordered_map; @@ -102,7 +103,6 @@ namespace ScriptCanvas const AZStd::sys_time_t m_translationDuration; Result(AZStd::string invalidSourceInfo); - Result(Result&& source); Result(Grammar::AbstractCodeModelConstPtr model); Result(Grammar::AbstractCodeModelConstPtr model, Translations&& translations, Errors&& errors); From 75b0b23fab66876d343edd33d38303ee208b9a33 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 5 Oct 2021 13:40:21 -0700 Subject: [PATCH 20/24] allow multiple single upgrade requests Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/Controller.cpp | 180 ++++++++++-------- .../Windows/Tools/UpgradeTool/Controller.h | 4 + .../View/Windows/Tools/UpgradeTool/Model.cpp | 26 ++- .../View/Windows/Tools/UpgradeTool/Model.h | 3 +- 4 files changed, 127 insertions(+), 86 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 207f70aec1..492759c341 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -88,6 +88,22 @@ namespace ScriptCanvasEditor LogBus::Broadcast(&LogTraits::Clear); } + void Controller::EnableAllUpgradeButtons() + { + for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) + { + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(true); + } + } + } + + QList Controller::FindTableItems(const AZ::Data::AssetInfo& info) + { + return m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); + } + void Controller::OnButtonPressClose() { reject(); @@ -106,7 +122,7 @@ namespace ScriptCanvasEditor if (!scriptCanvasAsset) { AZ_Warning - ( ScriptCanvas::k_VersionExplorerWindow.data() + (ScriptCanvas::k_VersionExplorerWindow.data() , false , "InspectAsset: %s, AsestData failed to return ScriptCanvasAsset" , asset.GetHint().c_str()); @@ -184,7 +200,7 @@ namespace ScriptCanvasEditor if (graphComponent) { graphComponent->UpgradeGraph - ( asset + (asset , m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate , m_view->verbose->isChecked()); } @@ -195,7 +211,7 @@ namespace ScriptCanvasEditor { int result = QMessageBox::No; QMessageBox mb - ( QMessageBox::Warning + (QMessageBox::Warning , QObject::tr("Failed to Save Upgraded File") , QObject::tr("The upgraded file could not be saved because the file is read only.\n" "Do you want to make it writeable and overwrite it?") @@ -221,13 +237,14 @@ namespace ScriptCanvasEditor void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) { - QList items = m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); + QList items = FindTableItems(info); if (!items.isEmpty()) { for (auto* item : items) { int row = item->row(); SetRowBusy(row); + m_view->tableWidget->setCellWidget(row, ColumnAction, nullptr); } } } @@ -245,21 +262,23 @@ namespace ScriptCanvasEditor { VE_LOG("Failed to modify %s: %s", result.assetInfo.m_relativePath.c_str(), result.errorMessage.data()); } - - QList items = m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); - if (!items.isEmpty()) - { - for (auto* item : items) - { - int row = item->row(); - if (result.errorMessage.empty()) + QList items = FindTableItems(info); + for (auto* item : items) + { + int row = item->row(); + + if (result.errorMessage.empty()) + { + SetRowSucceeded(row); + } + else + { + SetRowFailed(row, ""); + + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) { - SetRowSucceeded(row); - } - else - { - SetRowFailed(row, ""); + button->setEnabled(false); } } } @@ -305,15 +324,6 @@ namespace ScriptCanvasEditor { m_view->onlyShowOutdated->setEnabled(true); - // Enable all the Upgrade buttons - for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) - { - if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) - { - button->setEnabled(true); - } - } - QString spinnerText = QStringLiteral("Scan Complete"); spinnerText.append(QString::asprintf(" - Discovered: %zu, Failed: %zu, Upgradeable: %zu, Up-to-date: %zu" , result.m_catalogAssets.size() @@ -324,6 +334,7 @@ namespace ScriptCanvasEditor m_view->spinner->SetText(spinnerText); SetSpinnerIsBusy(false); m_view->progressBar->setVisible(false); + EnableAllUpgradeButtons(); if (!result.m_unfiltered.empty()) { @@ -338,59 +349,67 @@ namespace ScriptCanvasEditor void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] Filtered filtered) { - m_view->tableWidget->insertRow(m_handledAssetCount); - QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str())); - m_view->tableWidget->setItem(m_handledAssetCount, static_cast(ColumnAsset), rowName); - SetRowSucceeded(m_handledAssetCount); + const int rowIndex = m_view->tableWidget->rowCount(); - if (filtered == Filtered::No) + if (filtered == Filtered::No || !m_view->onlyShowOutdated->isChecked()) { - QPushButton* rowGoToButton = new QPushButton(this); - rowGoToButton->setText("Upgrade"); - rowGoToButton->setEnabled(false); - SetRowBusy(m_handledAssetCount); - connect - ( rowGoToButton - , &QPushButton::pressed - , this - , [this, assetInfo]() + m_view->tableWidget->insertRow(rowIndex); + QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str())); + m_view->tableWidget->setItem(rowIndex, static_cast(ColumnAsset), rowName); + SetRowSucceeded(rowIndex); + + if (filtered == Filtered::No) + { + QPushButton* upgradeButton = new QPushButton(this); + upgradeButton->setText("Upgrade"); + upgradeButton->setEnabled(false); + SetRowBusy(rowIndex); + + connect + ( upgradeButton + , &QPushButton::pressed + , this + , [this, assetInfo]() { this->OnButtonPressUpgradeSingle(assetInfo); }); - m_view->tableWidget->setCellWidget(m_handledAssetCount, static_cast(ColumnAction), rowGoToButton); + + m_view->tableWidget->setCellWidget(rowIndex, static_cast(ColumnAction), upgradeButton); + } + + char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; + AZStd::string path = AZStd::string::format("@devroot@/%s", assetInfo.m_relativePath.c_str()); + AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); + AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); + AZ::StringFunc::Path::Normalize(path); + + bool result = false; + AZ::Data::AssetInfo info; + AZStd::string watchFolder; + QByteArray assetNameUtf8 = assetInfo.m_relativePath.c_str(); + AzToolsFramework::AssetSystemRequestBus::BroadcastResult + ( result + , &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath + , assetNameUtf8 + , info + , watchFolder); + AZ_Error + ( ScriptCanvas::k_VersionExplorerWindow.data() + , result + , "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + + QToolButton* browseButton = new QToolButton(this); + browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); + browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); + + QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); + connect(browseButton, &QPushButton::clicked, [absolutePath] { + AzQtComponents::ShowFileOnDesktop(absolutePath); + }); + + m_view->tableWidget->setCellWidget(rowIndex, static_cast(ColumnBrowse), browseButton); } - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; - AZStd::string path = AZStd::string::format("@devroot@/%s", assetInfo.m_relativePath.c_str()); - AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path); - AZ::StringFunc::Path::Normalize(path); - - bool result = false; - AZ::Data::AssetInfo info; - AZStd::string watchFolder; - QByteArray assetNameUtf8 = assetInfo.m_relativePath.c_str(); - AzToolsFramework::AssetSystemRequestBus::BroadcastResult - ( result - , &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath - , assetNameUtf8 - , info - , watchFolder); - AZ_Error - ( ScriptCanvas::k_VersionExplorerWindow.data() - , result - , "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); - - QToolButton* browseButton = new QToolButton(this); - browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); - browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); - - QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); - connect(browseButton, &QPushButton::clicked, [absolutePath] { - AzQtComponents::ShowFileOnDesktop(absolutePath); - }); - - m_view->tableWidget->setCellWidget(m_handledAssetCount, static_cast(ColumnBrowse), browseButton); OnScannedGraphResult(assetInfo); } @@ -403,11 +422,12 @@ namespace ScriptCanvasEditor void Controller::OnScanLoadFailure(const AZ::Data::AssetInfo& info) { - m_view->tableWidget->insertRow(m_handledAssetCount); + const int rowIndex = m_view->tableWidget->rowCount(); + m_view->tableWidget->insertRow(rowIndex); QTableWidgetItem* rowName = new QTableWidgetItem ( tr(AZStd::string::format("Load Error: %s", info.m_relativePath.c_str()).c_str())); - m_view->tableWidget->setItem(m_handledAssetCount, static_cast(ColumnAsset), rowName); - SetRowFailed(m_handledAssetCount, "Load failed"); + m_view->tableWidget->setItem(rowIndex, static_cast(ColumnAsset), rowName); + SetRowFailed(rowIndex, "Load failed"); OnScannedGraphResult(info); } @@ -425,8 +445,9 @@ namespace ScriptCanvasEditor if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) { button->setEnabled(false); - SetRowBusy(row); } + + SetRowBusy(row); } QString spinnerText = QStringLiteral("Upgrade in progress - "); @@ -464,6 +485,8 @@ namespace ScriptCanvasEditor m_view->spinner->SetText(spinnerText); SetSpinnerIsBusy(false); AddLogEntries(); + EnableAllUpgradeButtons(); + m_view->scanButton->setEnabled(true); } void Controller::OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) @@ -483,6 +506,11 @@ namespace ScriptCanvasEditor { SetRowFailed(row, ""); } + + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(true); + } } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index 23f35840be..ac18ff6cf5 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -22,6 +22,7 @@ AZ_POP_DISABLE_WARNING #endif class QPushButton; +class QTableWidgetItem; namespace Ui { @@ -61,6 +62,9 @@ namespace ScriptCanvasEditor int m_handledAssetCount = 0; void AddLogEntries(); + void EnableAllUpgradeButtons(); + QList FindTableItems(const AZ::Data::AssetInfo& assetInfo); + void OnButtonPressClose(); void OnButtonPressScan(); void OnButtonPressUpgrade(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp index 98edef54bf..d8d242adbb 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.cpp @@ -101,9 +101,9 @@ namespace ScriptCanvasEditor return; } - auto results = m_scanner->TakeResult(); if (modification.modifySingleAsset.m_assetId.IsValid()) { + const auto& results = m_scanner->GetResult(); auto iter = AZStd::find_if ( results.m_unfiltered.begin() , results.m_unfiltered.end() @@ -118,24 +118,32 @@ namespace ScriptCanvasEditor return; } - WorkingAsset singleEntry = *iter; - results.m_unfiltered.clear(); - results.m_unfiltered.push_back(singleEntry); + + m_state = State::ModifySingle; + m_modifier = AZStd::make_unique(modification, WorkingAssets{ *iter }, [this]() { OnModificationComplete(); }); + } + else + { + auto results = m_scanner->TakeResult(); + m_state = State::ModifyAll; + m_modifier = AZStd::make_unique(modification, AZStd::move(results.m_unfiltered), [this]() { OnModificationComplete(); }); } m_modResults = {}; - m_state = State::Modifying; m_log.Activate(); - m_keepEditorAlive = AZStd::make_unique(); - - m_modifier = AZStd::make_unique(modification, AZStd::move(results.m_unfiltered), [this](){ OnModificationComplete(); }); + m_keepEditorAlive = AZStd::make_unique(); } void Model::OnModificationComplete() { ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeComplete, m_modifier->GetResult()); m_modifier.reset(); - m_scanner.reset(); + + if (m_state == State::ModifyAll) + { + m_scanner.reset(); + } + Idle(); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h index e11f8857e7..58ad9877be 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h @@ -54,7 +54,8 @@ namespace ScriptCanvasEditor { Idle, Scanning, - Modifying, + ModifyAll, + ModifySingle }; State m_state = State::Idle; From ac836da605fe23e0322f8d95875d66a8f13c76b4 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 5 Oct 2021 14:43:19 -0700 Subject: [PATCH 21/24] disable upgrade all button until disparity from single upgrade is discovered Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Windows/Tools/UpgradeTool/Controller.cpp | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 492759c341..6fa0f1adfa 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -54,6 +54,7 @@ namespace ScriptCanvasEditor m_view->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn); connect(m_view->scanButton, &QPushButton::pressed, this, &Controller::OnButtonPressScan); connect(m_view->closeButton, &QPushButton::pressed, this, &Controller::OnButtonPressClose); + m_view->upgradeAllButton->setVisible(false); connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnButtonPressUpgrade); m_view->progressBar->setValue(0); m_view->progressBar->setVisible(false); @@ -237,15 +238,11 @@ namespace ScriptCanvasEditor void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const AZ::Data::AssetInfo& info) { - QList items = FindTableItems(info); - if (!items.isEmpty()) + for (auto* item : FindTableItems(info)) { - for (auto* item : items) - { - int row = item->row(); - SetRowBusy(row); - m_view->tableWidget->setCellWidget(row, ColumnAction, nullptr); - } + int row = item->row(); + SetRowBusy(row); + m_view->tableWidget->setCellWidget(row, ColumnAction, nullptr); } } @@ -263,8 +260,7 @@ namespace ScriptCanvasEditor VE_LOG("Failed to modify %s: %s", result.assetInfo.m_relativePath.c_str(), result.errorMessage.data()); } - QList items = FindTableItems(info); - for (auto* item : items) + for (auto* item : FindTableItems(info)) { int row = item->row(); @@ -440,23 +436,32 @@ namespace ScriptCanvasEditor ( const ModifyConfiguration& config , [[maybe_unused]] const WorkingAssets& assets) { - for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) - { - if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) - { - button->setEnabled(false); - } - - SetRowBusy(row); - } - QString spinnerText = QStringLiteral("Upgrade in progress - "); if (config.modifySingleAsset.m_assetId.IsValid()) { spinnerText.append(" single graph"); + + if (assets.size() == 1) + { + for (auto* item : FindTableItems(assets.front().info)) + { + int row = item->row(); + SetRowBusy(row); + } + } } else { + for (int row = 0; row < m_view->tableWidget->rowCount(); ++row) + { + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(false); + } + + SetRowBusy(row); + } + spinnerText.append(" all scanned graphs"); } @@ -491,26 +496,22 @@ namespace ScriptCanvasEditor void Controller::OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result) { - QList items = m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly); - if (!items.isEmpty()) + for (auto* item : FindTableItems(info)) { - for (auto* item : items) + int row = item->row(); + + if (result == Result::Success) { - int row = item->row(); + SetRowSucceeded(row); + } + else + { + SetRowFailed(row, ""); + } - if (result == Result::Success) - { - SetRowSucceeded(row); - } - else - { - SetRowFailed(row, ""); - } - - if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) - { - button->setEnabled(true); - } + if (QPushButton* button = qobject_cast(m_view->tableWidget->cellWidget(row, ColumnAction))) + { + button->setEnabled(true); } } From 502513f08112fd41e752756de4c9f376231af960 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:05:04 -0700 Subject: [PATCH 22/24] remove superflous comment Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp index 665a481a17..7d4cfec909 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp @@ -110,14 +110,12 @@ namespace ScriptCanvasBuilder const ScriptCanvas::Translation::Result translationResult = TranslateToLua(request); auto isSuccessOutcome = translationResult.IsSuccess(ScriptCanvas::Translation::TargetFlags::Lua); - if (!isSuccessOutcome.IsSuccess()) { - // sanity check return AZ::Failure(isSuccessOutcome.TakeError()); } - auto& translation = translationResult.m_translations.find(ScriptCanvas::Translation::TargetFlags::Lua)->second; + auto& translation = translationResult.m_translations.find(ScriptCanvas::Translation::TargetFlags::Lua)->second; AZ::Data::Asset asset; scriptAssetId.m_subId = AZ::ScriptAsset::CompiledAssetSubId; asset.Create(scriptAssetId); From 5969c94d22b007812c5a29c2efbbf087c69d9b0a Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 5 Oct 2021 17:46:55 -0700 Subject: [PATCH 23/24] Renamed controller.ui --> view.ui, minor tweaks in response to PR Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Editor/View/Windows/Tools/UpgradeTool/Controller.cpp | 6 +++--- .../Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h | 5 +++-- .../Code/Editor/View/Windows/Tools/UpgradeTool/Model.h | 2 +- .../View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp | 5 ----- .../Windows/Tools/UpgradeTool/{Controller.ui => View.ui} | 4 ++-- Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake | 2 +- 6 files changed, 10 insertions(+), 14 deletions(-) rename Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/{Controller.ui => View.ui} (99%) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 6fa0f1adfa..138532be0f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -34,8 +34,8 @@ #include #include -#include -#include +#include +// #include namespace ScriptCanvasEditor { @@ -43,7 +43,7 @@ namespace ScriptCanvasEditor { Controller::Controller(QWidget* parent) : AzQtComponents::StyledDialog(parent) - , m_view(new Ui::Controller()) + , m_view(new Ui::View()) { m_view->setupUi(this); m_view->tableWidget->horizontalHeader()->setVisible(false); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index ac18ff6cf5..298f755d56 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -11,6 +11,7 @@ #if !defined(Q_MOC_RUN) #include #include +#include #include #include #include @@ -26,7 +27,7 @@ class QTableWidgetItem; namespace Ui { - class Controller; + class View; } namespace AzQtComponents @@ -58,7 +59,7 @@ namespace ScriptCanvasEditor static constexpr int ColumnBrowse = 2; static constexpr int ColumnStatus = 3; - AZStd::unique_ptr m_view; + AZStd::unique_ptr m_view; int m_handledAssetCount = 0; void AddLogEntries(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h index 58ad9877be..ab0f710870 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Model.h @@ -21,7 +21,7 @@ namespace ScriptCanvasEditor { namespace VersionExplorer { - //!Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow + //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow //! the upgrade tool to work even if the editor is not in the foreground class EditorKeepAlive { diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp index 6f856b9d4c..c1faedc3a3 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp @@ -8,11 +8,6 @@ #include -namespace LoggerCpp -{ - -} - namespace ScriptCanvasEditor { namespace VersionExplorer diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui similarity index 99% rename from Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui rename to Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui index fdeb701f33..f549c821d6 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.ui +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/View.ui @@ -1,7 +1,7 @@ - Controller - + View + Qt::WindowModal diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake index b12c608fe5..609f7cd454 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake @@ -261,7 +261,6 @@ set(FILES Editor/View/Windows/ScriptCanvasEditorResources.qrc Editor/View/Windows/Tools/UpgradeTool/Controller.cpp Editor/View/Windows/Tools/UpgradeTool/Controller.h - Editor/View/Windows/Tools/UpgradeTool/Controller.ui Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp Editor/View/Windows/Tools/UpgradeTool/FileSaver.h Editor/View/Windows/Tools/UpgradeTool/LogTraits.h @@ -277,6 +276,7 @@ set(FILES Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.cpp Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h + Editor/View/Windows/Tools/UpgradeTool/View.ui Editor/Framework/ScriptCanvasGraphUtilities.inl Editor/Framework/ScriptCanvasGraphUtilities.h Editor/Framework/ScriptCanvasTraceUtilities.h From 46ae0d3f1ca824690ca0cfd6a8741be1186ffab0 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 6 Oct 2021 10:39:31 -0700 Subject: [PATCH 24/24] fix linux build error on unique_ptr deletion Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Editor/View/Windows/Tools/UpgradeTool/Controller.cpp | 6 +++++- .../Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 138532be0f..dbcd176ee5 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -35,7 +35,6 @@ #include #include -// #include namespace ScriptCanvasEditor { @@ -63,6 +62,11 @@ namespace ScriptCanvasEditor ModelNotificationsBus::Handler::BusConnect(); } + Controller::~Controller() + { + delete m_view; + } + void Controller::AddLogEntries() { const AZStd::vector* logs = nullptr; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h index 298f755d56..9842ea3da4 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.h @@ -52,6 +52,7 @@ namespace ScriptCanvasEditor AZ_CLASS_ALLOCATOR(Controller, AZ::SystemAllocator, 0); explicit Controller(QWidget* parent = nullptr); + ~Controller(); private: static constexpr int ColumnAsset = 0; @@ -59,7 +60,7 @@ namespace ScriptCanvasEditor static constexpr int ColumnBrowse = 2; static constexpr int ColumnStatus = 3; - AZStd::unique_ptr m_view; + Ui::View* m_view = nullptr; int m_handledAssetCount = 0; void AddLogEntries();