source save in place first pass
Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user