source save in place first pass

Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
This commit is contained in:
chcurran
2021-11-08 13:58:48 -08:00
parent 837e9f6105
commit a334ce09b4
9 changed files with 101 additions and 89 deletions
@@ -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<ScriptCanvas::ScriptCanvasData>(graphData.get(), stream, nullptr, &settings);
auto saveOutcome = JSRU::SaveObjectToStream<ScriptCanvas::ScriptCanvasData>(graphData, stream, nullptr, &settings);
if (!saveOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string("JSON serialization failed to save source: %s", saveOutcome.GetError().c_str()));
@@ -1067,9 +1067,9 @@ namespace ScriptCanvasEditor
m_owner = &owner;
}
ScriptCanvas::DataPtr Graph::GetOwnership() const
ScriptCanvas::ScriptCanvasData* Graph::GetOwnership() const
{
return ScriptCanvas::DataPtr(const_cast<Graph*>(this)->m_owner);
return const_cast<Graph*>(this)->m_owner;
}
bool Graph::CreateConnection(const GraphCanvas::ConnectionId& connectionId, const GraphCanvas::Endpoint& sourcePoint, const GraphCanvas::Endpoint& targetPoint)
@@ -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 <typename NodeType>
@@ -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<ScriptCanvas::AssetDescription*> 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<char, AZ::IO::MaxPathLength> 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<char, AZ::IO::MaxPathLength> 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<VersionExplorer::FileSaver>
( nullptr
, [this](const VersionExplorer::FileSaveResult& fileSaveResult) { OnSaveCallBack(fileSaveResult); });
UpdateSaveState();
BlockCloseRequests();
ScriptCanvasEditor::SourceHandle newLocation(inMemoryAssetId, {}, path);
m_fileSaver->Save(newLocation);
UpdateSaveState();
BlockCloseRequests();
}
void MainWindow::OnFileOpen()
@@ -53,6 +53,7 @@
#include <Editor/View/Widgets/AssetGraphSceneDataBus.h>
#include <Editor/View/Windows/Tools/UpgradeTool/Controller.h>
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
#if SCRIPTCANVAS_EDITOR
#include <Include/EditorCoreAPI.h>
@@ -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<VersionExplorer::FileSaver> m_fileSaver;
VersionExplorer::FileSaveResult m_fileSaveResult;
void OnSaveCallBack(const VersionExplorer::FileSaveResult& result);
};
}
@@ -15,6 +15,7 @@
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
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<ScriptCanvasEditor::ScriptCanvasAsset>())
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<AZ::Data::AssetData> 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;
@@ -29,10 +29,12 @@ namespace ScriptCanvasEditor
( AZStd::function<bool()> onReadOnlyFile
, AZStd::function<void(const FileSaveResult& result)> onComplete);
const SourceHandle& GetSource() const;
void Save(AZ::Data::Asset<AZ::Data::AssetData> asset);
void Save(const SourceHandle& source);
private:
SourceHandle m_source;
AZStd::function<void(const FileSaveResult& result)> m_onComplete;
AZStd::function<bool()> m_onReadOnlyFile;
@@ -259,7 +259,7 @@ namespace ScriptCanvasEditor
m_modifyState = ModifyState::Saving;
m_fileSaver = AZStd::make_unique<FileSaver>
( m_config.onReadOnlyFile
, [this](const FileSaveResult& result) { OnFileSaveComplete(result); });
, [this](const FileSaveResult& fileSaveResult) { OnFileSaveComplete(fileSaveResult); });
m_fileSaver->Save(result.asset);
}
@@ -13,7 +13,6 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h>
// #include <Editor/Include/ScriptCanvas/Components/EditorGraph.h>
#include "Core.h"
#include "Attributes.h"