From a334ce09b41abca514a3da3169f45681f74d822b Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 8 Nov 2021 13:58:48 -0800 Subject: [PATCH] source save in place first pass Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Assets/ScriptCanvasFileHandling.cpp | 4 +- .../Code/Editor/Components/EditorGraph.cpp | 4 +- .../ScriptCanvas/Components/EditorGraph.h | 2 +- .../Code/Editor/View/Windows/MainWindow.cpp | 139 +++++++++--------- .../Code/Editor/View/Windows/MainWindow.h | 5 +- .../Windows/Tools/UpgradeTool/FileSaver.cpp | 31 ++-- .../Windows/Tools/UpgradeTool/FileSaver.h | 2 + .../Windows/Tools/UpgradeTool/Modifier.cpp | 2 +- .../Code/Include/ScriptCanvas/Core/Core.cpp | 1 - 9 files changed, 101 insertions(+), 89 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp index 9e385443f2..4af7ff247e 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp @@ -173,7 +173,7 @@ namespace ScriptCanvasEditor } auto saveTarget = graphData->ModGraph(); - if (saveTarget || !saveTarget->GetGraphData()) + if (!saveTarget || !saveTarget->GetGraphData()) { return AZ::Failure(AZStd::string("source save container failed to return graph data")); } @@ -191,7 +191,7 @@ namespace ScriptCanvasEditor listener->OnSerialize(); } - auto saveOutcome = JSRU::SaveObjectToStream(graphData.get(), stream, nullptr, &settings); + auto saveOutcome = JSRU::SaveObjectToStream(graphData, stream, nullptr, &settings); if (!saveOutcome.IsSuccess()) { return AZ::Failure(AZStd::string("JSON serialization failed to save source: %s", saveOutcome.GetError().c_str())); diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index 4f78c8e1b1..2c9dbe0fd6 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -1067,9 +1067,9 @@ namespace ScriptCanvasEditor m_owner = &owner; } - ScriptCanvas::DataPtr Graph::GetOwnership() const + ScriptCanvas::ScriptCanvasData* Graph::GetOwnership() const { - return ScriptCanvas::DataPtr(const_cast(this)->m_owner); + return const_cast(this)->m_owner; } bool Graph::CreateConnection(const GraphCanvas::ConnectionId& connectionId, const GraphCanvas::Endpoint& sourcePoint, const GraphCanvas::Endpoint& targetPoint) diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h index 05619caa30..b5269cc45d 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h @@ -309,7 +309,7 @@ namespace ScriptCanvasEditor const GraphStatisticsHelper& GetNodeUsageStatistics() const; void MarkOwnership(ScriptCanvas::ScriptCanvasData& owner); - ScriptCanvas::DataPtr GetOwnership() const; + ScriptCanvas::ScriptCanvasData* GetOwnership() const; // Finds and returns all nodes within the graph that are of the specified type template diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index aede7ff9a1..deb75ff78c 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -1403,48 +1403,28 @@ namespace ScriptCanvasEditor void MainWindow::GetSuggestedFullFilenameToSaveAs(const ScriptCanvasEditor::SourceHandle& /*assetId*/, AZStd::string& /*filePath*/, AZStd::string& /*fileFilter*/) { // #sc_editor_asset - /* - ScriptCanvasMemoryAsset::pointer memoryAsset; - AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetId); - - AZStd::string assetPath; - if (memoryAsset) - { - assetPath = memoryAsset->GetAbsolutePath(); - - AZ::Data::AssetType assetType = memoryAsset->GetAsset().GetType(); - - ScriptCanvasAssetHandler* assetHandler; - AssetTrackerRequestBus::BroadcastResult(assetHandler, &AssetTrackerRequests::GetAssetHandlerForType, assetType); - AZ_Assert(assetHandler, "Asset type must have a valid asset handler"); - - AZ::EBusAggregateResults results; - AssetRegistryRequestBus::BroadcastResult(results, &AssetRegistryRequests::GetAssetDescription, assetType); - - ScriptCanvas::AssetDescription* description = nullptr; - for (auto item : results.values) - { - if (item->GetAssetType() == assetType) - { - description = item; - break; - } - } - - AZ_Assert(description, "Asset type must have a valid description"); - - fileFilter = description->GetFileFilterImpl(); - - AZStd::string tabName; - AssetTrackerRequestBus::BroadcastResult(tabName, &AssetTrackerRequests::GetTabName, assetId); - - assetPath = AZStd::string::format("%s/%s%s", description->GetSuggestedSavePathImpl(), tabName.c_str(), description->GetExtensionImpl()); - } - - AZStd::array resolvedPath; - AZ::IO::FileIOBase::GetInstance()->ResolvePath(assetPath.data(), resolvedPath.data(), resolvedPath.size()); - filePath = resolvedPath.data(); - */ +// +// ScriptCanvasMemoryAsset::pointer memoryAsset; +// AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, assetId); +// +// AZStd::string assetPath; +// if (memoryAsset) +// { +// assetPath = memoryAsset->GetAbsolutePath(); +// fileFilter = ScriptCanvasAssetDescription().GetFileFilterImpl(); +// +// AZStd::string tabName; +// AssetTrackerRequestBus::BroadcastResult(tabName, &AssetTrackerRequests::GetTabName, assetId); +// +// assetPath = AZStd::string::format("%s/%s%s" +// , ScriptCanvasAssetDescription().GetSuggestedSavePathImpl() +// , tabName.c_str() +// , ScriptCanvasAssetDescription().GetExtensionImpl()); +// } +// +// AZStd::array resolvedPath; +// AZ::IO::FileIOBase::GetInstance()->ResolvePath(assetPath.data(), resolvedPath.data(), resolvedPath.size()); +// filePath = resolvedPath.data(); } void MainWindow::OpenFile(const char* fullPath) @@ -1767,7 +1747,7 @@ namespace ScriptCanvasEditor // SaveAsEnd // SaveAssetImpl end - bool MainWindow::SaveAssetImpl(const ScriptCanvasEditor::SourceHandle& inMemoryAssetId, Save /*save*/) + bool MainWindow::SaveAssetImpl(const ScriptCanvasEditor::SourceHandle& inMemoryAssetId, Save save) { if (!inMemoryAssetId.IsValid()) { @@ -1783,15 +1763,23 @@ namespace ScriptCanvasEditor AZStd::string suggestedFilename; AZStd::string suggestedFileFilter; - GetSuggestedFullFilenameToSaveAs(inMemoryAssetId, suggestedFilename, suggestedFileFilter); - - EnsureSaveDestinationDirectory(suggestedFilename); - - QString filter = suggestedFileFilter.c_str(); - QString selectedFile; - bool isValidFileName = false; + if (save == Save::InPlace) + { + isValidFileName = true; + suggestedFileFilter = ScriptCanvasAssetDescription().GetExtensionImpl(); + suggestedFilename = inMemoryAssetId.Path(); + } + else + { + GetSuggestedFullFilenameToSaveAs(inMemoryAssetId, suggestedFilename, suggestedFileFilter); + } + + EnsureSaveDestinationDirectory(suggestedFilename); + QString filter = suggestedFileFilter.c_str(); + QString selectedFile = suggestedFilename.c_str(); + while (!isValidFileName) { selectedFile = AzQtComponents::FileDialog::GetSaveFileName(this, tr("Save As..."), suggestedFilename.data(), filter); @@ -1815,7 +1803,7 @@ namespace ScriptCanvasEditor // QMessageBox::information(this, "Unable to Save", AZStd::string::format("You must select a path within the current project\n\n%s", assetRoot.c_str()).c_str()); // } // else -if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) + if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) { isValidFileName = !(fileName.empty()); } @@ -1823,7 +1811,6 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) { QMessageBox::information(this, "Unable to Save", "File name cannot be empty"); } - } else { @@ -1842,20 +1829,20 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) } SaveAs(internalStringFile, inMemoryAssetId); - m_newlySavedFile = internalStringFile; - // Forcing the file add here, since we are creating a new file AddRecentFile(m_newlySavedFile.c_str()); - return true; } + return false; } - void MainWindow::OnSaveCallback(bool saveSuccess, ScriptCanvasEditor::SourceHandle memoryAsset) + void MainWindow::OnSaveCallBack(const VersionExplorer::FileSaveResult& result) { + const bool saveSuccess = result.fileSaveError.empty(); + auto memoryAsset = m_fileSaver->GetSource(); int saveTabIndex = m_tabBar->FindTab(memoryAsset); AZStd::string tabName = saveTabIndex >= 0 ? m_tabBar->tabText(saveTabIndex).toUtf8().data() : ""; @@ -1864,8 +1851,9 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) // #sc_editor_asset find a tab with the same path name and close non focused old ones with the same name // Update the editor with the new information about this asset. const ScriptCanvasEditor::SourceHandle& fileAssetId = memoryAsset; + int currentTabIndex = m_tabBar->currentIndex(); // We've saved as over a new graph, so we need to close the old one. - if (saveTabIndex != m_tabBar->currentIndex()) + if (saveTabIndex != currentTabIndex) { // Invalidate the file asset id so we don't delete trigger the asset flow. m_tabBar->setTabData(saveTabIndex, QVariant::fromValue(Widget::GraphTabMetadata())); @@ -1926,6 +1914,14 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) // Soft switch the asset id here. We'll do a double scene switch down below to actually switch the active assetid m_activeGraph = fileAssetId; + + if (tabName.at(tabName.size() - 1) == '*') + { + tabName = tabName.substr(0, tabName.size() - 2); + } + + m_tabBar->UpdateFileState(fileAssetId, Tracker::ScriptCanvasFileState::UNMODIFIED); + m_tabBar->SetTabText(saveTabIndex, tabName.c_str()); } else { @@ -1947,11 +1943,11 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) } else { - // Something weird happens with our saving. Where we are relying on these scene changes being called. - ScriptCanvasEditor::SourceHandle previousAssetId = m_activeGraph; - - OnChangeActiveGraphTab(ScriptCanvasEditor::SourceHandle()); - OnChangeActiveGraphTab(previousAssetId); +// // Something weird happens with our saving. Where we are relying on these scene changes being called. +// ScriptCanvasEditor::SourceHandle previousAssetId = m_activeGraph; +// +// OnChangeActiveGraphTab(ScriptCanvasEditor::SourceHandle()); +// OnChangeActiveGraphTab(previousAssetId); } UpdateAssignToSelectionState(); @@ -1964,7 +1960,7 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) // This is called during saving, so the is saving flag is always true Need to update the state after this callback is complete. So schedule for next system tick. AddSystemTickAction(SystemTickActionFlag::UpdateSaveMenuState); - if (m_closeCurrentGraphAfterSave) + if (saveSuccess && m_closeCurrentGraphAfterSave) { AddSystemTickAction(SystemTickActionFlag::CloseCurrentGraph); } @@ -1974,6 +1970,7 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) EnableAssetView(memoryAsset); UnblockCloseRequests(); + m_fileSaver.reset(); } bool MainWindow::ActivateAndSaveAsset(const ScriptCanvasEditor::SourceHandle& unsavedAssetId) @@ -1984,17 +1981,17 @@ if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName)) void MainWindow::SaveAs(AZStd::string_view path, ScriptCanvasEditor::SourceHandle inMemoryAssetId) { - AZ_TracePrintf("ScriptCanvas", "Saving %s to %.*s", inMemoryAssetId.Path().c_str(), path.data()); - // #sc_editor_asset maybe delete this - DisableAssetView(inMemoryAssetId); - // use the file saver, make new version that works on source handle and not asset - // then...connect the failed and succeed versions - // to OnSaveCallBack + m_fileSaver = AZStd::make_unique + ( nullptr + , [this](const VersionExplorer::FileSaveResult& fileSaveResult) { OnSaveCallBack(fileSaveResult); }); - UpdateSaveState(); - BlockCloseRequests(); + ScriptCanvasEditor::SourceHandle newLocation(inMemoryAssetId, {}, path); + m_fileSaver->Save(newLocation); + + UpdateSaveState(); + BlockCloseRequests(); } void MainWindow::OnFileOpen() diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index 0f126456c0..6704c10fda 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -53,6 +53,7 @@ #include #include +#include #if SCRIPTCANVAS_EDITOR #include @@ -788,6 +789,8 @@ namespace ScriptCanvasEditor //! this object manages the Save/Restore operations Workspace* m_workspace; - void OnSaveCallback(bool saveSuccess, ScriptCanvasEditor::SourceHandle previousFileAssetId); + AZStd::unique_ptr m_fileSaver; + VersionExplorer::FileSaveResult m_fileSaveResult; + void OnSaveCallBack(const VersionExplorer::FileSaveResult& result); }; } 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 82a046b0fc..f36f72234b 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace FileSaverCpp { @@ -58,6 +59,11 @@ namespace ScriptCanvasEditor , m_onComplete(onComplete) {} + const SourceHandle& FileSaver::GetSource() const + { + return m_source; + } + void FileSaver::PerformMove ( AZStd::string tmpFileName , AZStd::string target @@ -179,7 +185,7 @@ namespace ScriptCanvasEditor else { FileSaveResult result; - result.fileSaveError = "Source file was and remained read-only"; + result.fileSaveError = "Source file is read-only"; result.tempFileRemovalError = RemoveTempFile(tmpFileName); m_onComplete(result); } @@ -188,10 +194,12 @@ namespace ScriptCanvasEditor void FileSaver::OnSourceFileReleased(const SourceHandle& source) { + AZStd::string fullPath = source.Path(); 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(source.Path().c_str(), tmpFileName)) + // 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"; @@ -199,23 +207,24 @@ namespace ScriptCanvasEditor return; } - bool tempSavedSucceeded = false; + AZStd::string saveError; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); if (fileStream.IsOpen()) { - if (asset.GetType() == azrtti_typeid()) + auto saveOutcome = ScriptCanvasEditor::SaveToStream(source, fileStream); + if (!saveOutcome.IsSuccess()) { - ScriptCanvasEditor::ScriptCanvasAssetHandler handler; - tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); + saveError = saveOutcome.TakeError(); } fileStream.Close(); } - if (!tempSavedSucceeded) + if (!saveError.empty()) { FileSaveResult result; - result.fileSaveError = "Save asset data to temporary file failed"; + result.fileSaveError = AZStd::string::format("Save asset data to temporary file failed: %s", saveError.c_str()); m_onComplete(result); return; } @@ -265,6 +274,8 @@ namespace ScriptCanvasEditor void FileSaver::Save(const SourceHandle& source) { + m_source = source; + if (source.Path().empty()) { FileSaveResult result; @@ -285,7 +296,7 @@ namespace ScriptCanvasEditor void FileSaver::Save(AZ::Data::Asset asset) { - // #sc_editor_asset fix this path from the version explorer + // #sc_editor_asset fix/remove this path that is used by the version explorer AZStd::string relativePath, fullPath; AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId()); bool fullPathFound = false; 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 6ec0daa2b7..439db2d260 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/FileSaver.h @@ -29,10 +29,12 @@ namespace ScriptCanvasEditor ( AZStd::function onReadOnlyFile , AZStd::function onComplete); + const SourceHandle& GetSource() const; void Save(AZ::Data::Asset asset); void Save(const SourceHandle& source); private: + SourceHandle m_source; AZStd::function m_onComplete; AZStd::function m_onReadOnlyFile; 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 f3da1ba309..0e4190b18d 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Modifier.cpp @@ -259,7 +259,7 @@ namespace ScriptCanvasEditor m_modifyState = ModifyState::Saving; m_fileSaver = AZStd::make_unique ( m_config.onReadOnlyFile - , [this](const FileSaveResult& result) { OnFileSaveComplete(result); }); + , [this](const FileSaveResult& fileSaveResult) { OnFileSaveComplete(fileSaveResult); }); m_fileSaver->Save(result.asset); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp index 15e2192ee8..064029eb03 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp @@ -13,7 +13,6 @@ #include #include #include -// #include #include "Core.h" #include "Attributes.h"